認証と認可 — 誰が何をできるかを管理する仕組み

バイブコーディング入門 — 第16回

前回のおさらいと、今回のテーマ

前回(第15回)では、JSONを正面から取り上げた。6つのデータ型、入れ子構造の読み方、よくある文法ミス5つ、そしてバリデーション(検証)の方法。JSONが読めるようになったことで、APIのレスポンスが暗号ではなく普通の文章に見えるようになった。

さて、ここまでの連載で「Webアプリの仕組み」をかなり理解できるようになった。URI、HTTP、REST API、JSON。あなたはもう、AIが書いたコードの構造を読み解く力を持っている。

しかし、1つ大きなテーマが残っている。ログイン機能だ。

あなたが30人の人材紹介会社の管理職だとしよう。社内で使う候補者管理アプリをバイブコーディングで作った。候補者の名前、連絡先、面接記録、年収情報が入っている。このアプリにログイン機能がなかったら、URLを知っている人は誰でも全データにアクセスできてしまう。取引先にURLが漏れたら、候補者の年収情報まで見られてしまう。

ログイン機能の裏側で動いているのが、今回のテーマ「認証」と「認可」だ。

認証(にんしょう)は「あなたは誰ですか?」の確認。認可(にんか)は「あなたは何をしていいですか?」の確認。この2つは似ているようで、まったく違う概念だ。

今回学ぶこと:

  • 認証と認可の違い(なぜ両方必要なのか)
  • パスワード認証の仕組み(パスワードはどう保存されるのか)
  • OAuth(オーオース)の仕組み(Googleアカウントでログインできる理由)
  • JWT(ジェイダブリューティー)の仕組み(ログイン状態を維持するトークン)
  • バイブコーディングでAIにログイン機能を依頼するテンプレート

第11回で学んだCookieとセッションの知識が、ここで一気につながる。

認証と認可の違い — ホテルのたとえで理解する

認証と認可を、ホテルにたとえてみよう。

あなたがホテルにチェックインする場面を想像してほしい。

フロントで身分証を見せる。これが認証だ。「この人は予約した田中太郎さん本人である」と確認すること。

フロントでルームキーを受け取る。このキーで開けられるのは503号室だけだ。スイートルームのドアは開かない。従業員専用のバックヤードにも入れない。これが認可だ。「田中太郎さんは503号室にだけ入れる」という権限の管理。

Webアプリに置き換えてみよう。

認証の例:

  • ログイン画面でメールアドレスとパスワードを入力する
  • Googleアカウントでログインボタンを押す
  • スマートフォンに届いた6桁のコードを入力する

認可の例:

  • 一般社員は自分の担当案件だけ見える。マネージャーはチーム全員の案件が見える
  • 経理部門だけが売上データをダウンロードできる
  • 管理者だけがユーザーを追加・削除できる

認証が先で、認可が後。この順番は絶対だ。「誰だかわからない人に権限を渡す」ことはありえない。

バイブコーディングでアプリを作るとき、「ログイン機能をつけて」とだけAIに伝えると、認証だけ実装されて認可が抜け落ちることがある。「ログイン機能をつけて、さらに役割ごとにアクセスできる画面を分けて」と伝えれば、認証と認可の両方が実装される。

パスワード認証の仕組み — パスワードはそのまま保存されない

もっとも基本的な認証方式が、パスワード認証だ。メールアドレスとパスワードを入力してログインする、おなじみの方式。

ここで1つ、意外に知られていない事実がある。あなたのパスワードは、サーバーにそのまま保存されていない。

「え、じゃあどうやって照合しているの?」と思うかもしれない。

答えは「ハッシュ化」だ。ハッシュ化とは、元のデータを一方通行で別の文字列に変換することだ。

たとえば、パスワードが mypassword123 だとする。これをハッシュ化すると、こんな文字列になる。

$2b$10$N9qo8uLOickgx2ZMRZoMye.IjqXbOW5LYmFm1C6cGnMhKPnUq2HBG

この変換は一方通行だ。ハッシュ化された文字列から元のパスワードに戻すことはできない。

ログイン時の流れはこうなる。

  1. あなたがパスワードを入力する
  2. サーバーがそのパスワードをハッシュ化する
  3. データベースに保存されているハッシュ値と比較する
  4. 一致すれば「本人」と判断する

なぜわざわざこんなことをするのか。理由は明確だ。万が一データベースが流出しても、パスワードそのものは漏れない。ハッシュ値からは元のパスワードに戻せないので、攻撃者がデータベースを盗んでも、すぐにはログインできない。

バイブコーディングでログイン機能を作るとき、AIは通常このハッシュ化を自動で実装してくれる。しかし、「パスワードがどう保存されているか」を知っておくと、セキュリティに関する判断ができるようになる。たとえば、サービスから「あなたのパスワードはXXXXです」というメールが届いたら、そのサービスはパスワードをそのまま保存している可能性がある。それは危険なサービスだ。

セッションとトークン — ログイン状態をどう維持するか

ログインに成功した後、どうやって「ログイン中」の状態を維持するのか。ここで第11回の知識がつながる。

第11回で学んだ通り、HTTPはステートレス(状態を持たない)だ。サーバーは「さっきログインした人」と「初めてアクセスした人」を区別できない。そこで、ログイン成功後に「通行証」を発行する。

通行証の渡し方には、大きく2つの方式がある。

方式1: セッション方式(サーバー側で管理)

ログインに成功すると、サーバーが「セッションID」という通行証を発行する。この通行証の番号だけをCookieに入れてブラウザに渡す。通行証の中身(誰がログインしているか、いつまで有効か)はサーバー側に保存する。

たとえるなら、映画館の半券だ。半券にはチケット番号だけが書いてある。座席情報や料金は映画館のシステムに記録されている。

方式2: トークン方式(クライアント側で管理)

ログインに成功すると、サーバーが「トークン」という通行証を発行する。この通行証には「誰がログインしているか」「いつまで有効か」「どの権限を持っているか」の情報がすべて書き込まれている。サーバーはこの情報を保存しない。

たとえるなら、パスポートだ。パスポートには本人の情報がすべて記載されている。入国審査官はパスポートを見るだけで判断できる。どこかのデータベースに問い合わせる必要がない。

どちらの方式が良いかは、アプリの規模と用途による。小規模なアプリならセッション方式で十分だ。複数のサービスを連携させる大規模なシステムでは、トークン方式が使われることが多い。

バイブコーディングでSupabase(スーパーベース)というサービスを使う場合は、トークン方式が採用されている。AIに「Supabaseの認証機能を使ってログインを実装して」と伝えれば、トークン方式で実装してくれる。

OAuth(オーオース)— Googleアカウントでログインできる理由

Webサービスのログイン画面で「Googleでログイン」「LINEでログイン」というボタンを見たことがあるだろう。あのボタンの裏側で動いているのが OAuth(オーオース)だ。正式名称は「OAuth 2.0」で、他のサービスのアカウント情報を借りて本人確認をする仕組みだ。

なぜOAuthが生まれたのか。理由は2つある。

1つ目: ユーザーの手間を減らすため。新しいサービスを使うたびに、メールアドレスとパスワードを登録するのは面倒だ。すでに持っているGoogleアカウントやLINEアカウントでログインできれば、登録の手間がなくなる。

2つ目: パスワード管理のリスクを減らすため。サービスごとにパスワードを設定すると、同じパスワードを使い回しがちだ。1つのサービスからパスワードが流出すると、他のサービスにも被害が広がる。OAuthを使えば、パスワードを預ける先をGoogle等の大手に限定できる。

OAuthの流れを、具体的に追ってみよう。あなたが「タスク管理アプリ」に「Googleでログイン」ボタンを押した場合。

  1. タスク管理アプリが、Googleに「この人の本人確認をお願いします」とリクエストを送る
  2. 画面がGoogleのログインページに切り替わる
  3. あなたがGoogleアカウントのパスワードを入力する(パスワードはGoogleにだけ送られる。タスク管理アプリには送られない)
  4. Googleが「この人は確かに田中太郎です」という証明書(認可コード)をタスク管理アプリに渡す
  5. タスク管理アプリがその証明書をGoogleに提示して、アクセストークン(通行証)を受け取る
  6. ログイン完了。以降はこのアクセストークンを使って通信する

ここで重要なのは、手順3だ。パスワードはGoogleにだけ送られる。タスク管理アプリはパスワードを知ることがない。これがOAuthの最大のメリットだ。

「でも、タスク管理アプリにGoogleのデータを全部見られるのでは?」という不安があるかもしれない。心配はいらない。OAuthでは「何の情報を共有するか」を細かく指定できる。たとえば「名前とメールアドレスだけ」「Googleカレンダーの読み取りだけ」のように、必要最小限の情報だけを許可する。Googleのログイン画面で「このアプリが以下の情報にアクセスします」という確認画面が出るのは、このためだ。

JWT(ジェイダブリューティー)— 通行証の中身を読む

OAuthやトークン認証で発行される「トークン」の代表的な形式が、JWT(ジェイダブリューティー)だ。正式名称は JSON Web Token(ジェイソン・ウェブ・トークン)。名前の通り、前回学んだJSONがベースになっている。

JWTは、見た目がこんな文字列だ。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Iu田中太郎IiwiYWRtaW4iOmZhbHNlfQ.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

一見すると暗号のように見えるが、実は3つのパートがドット(.)で区切られている。

パート1: ヘッダー(どの方式で署名したか) パート2: ペイロード(中身。誰の通行証か、いつまで有効か、どの権限か) パート3: 署名(改ざんされていないことの証明)

前回のJSON知識を使って、パート2(ペイロード)を読んでみよう。このパートは単にBase64(ベースロクジュウヨン)という方式でエンコード(変換)されているだけだ。デコード(元に戻す)すると、こうなる。

{
  "sub": "user_12345",
  "name": "田中太郎",
  "role": "manager",
  "exp": 1744905600
}

これは前回学んだJSONそのものだ。

  • sub: ユーザーID(誰の通行証か)
  • name: ユーザー名
  • role: 権限(manager = マネージャー権限)
  • exp: 有効期限(数字はUNIXタイムスタンプという形式で、2025年4月16日のような日時を表す)

ここで気づいてほしいことがある。JWTのペイロードには「認証」の情報(この通行証はuser_12345のもの)と「認可」の情報(roleがmanager)の両方が入っている。サーバーはこのJWTを受け取るだけで、「誰で」「何ができるか」を判断できる。データベースに問い合わせる必要がない。

ただし、JWTのペイロードは暗号化されていない。Base64でエンコードされているだけなので、誰でも中身を読める。だからJWTにパスワードやクレジットカード番号を入れてはいけない。パート3の署名があるので「改ざん」はできないが、「閲覧」はできる。ここが重要なポイントだ。

多要素認証(MFA)— パスワードだけでは足りない時代

ここまでパスワード認証、OAuth、JWTを見てきた。しかし、現代のWebセキュリティでは「パスワードだけでは不十分」という考え方が主流になっている。

多要素認証(たようそにんしょう)、英語ではMFA(Multi-Factor Authentication)という仕組みがある。「2段階認証」という呼び方のほうが聞き覚えがあるかもしれない。

認証に使える要素は、大きく3種類ある。

  1. 知識: パスワード、PINコード、秘密の質問(あなたが知っていること)
  2. 所持: スマートフォン、セキュリティキー、ICカード(あなたが持っているもの)
  3. 生体: 指紋、顔、虹彩(あなた自身の体の特徴)

多要素認証は、このうち2つ以上を組み合わせる。たとえば「パスワード(知識)+ スマートフォンに届く6桁コード(所持)」の組み合わせ。パスワードが漏れても、スマートフォンを持っていなければログインできない。

バイブコーディングでアプリを作るとき、社内の機密データを扱うなら多要素認証の導入を検討する価値がある。Supabaseでは、メール認証に加えて、TOTP(タイムベースのワンタイムパスワード。Google Authenticator等で表示される6桁の数字)に対応している。

よくある不安と答え

OAuthで外部サービスにデータを全部見られるのか

見られない。OAuthでは「スコープ」という仕組みで、共有する情報の範囲を限定する。「名前とメールアドレスだけ」「カレンダーの読み取りだけ」のように、必要最小限だけを許可する。ログイン画面で表示される確認ダイアログに、どの情報を共有するかが書いてある。

パスワードを忘れたとき「パスワードの再設定」しかできないのはなぜか

パスワードがハッシュ化されて保存されているからだ。サービス側もあなたの元のパスワードを知らない。だから「パスワードを教える」ことはできず、「新しいパスワードを設定してもらう」しかない。パスワードリセットのメールが届く方式は、メールアドレスの所有者であることの確認(認証)も兼ねている。

JWTの有効期限が切れたらどうなるのか

アクセスが拒否される。一般的なアプリでは、有効期限が短いアクセストークン(15分〜1時間)と、有効期限が長いリフレッシュトークン(数日〜数週間)の2種類を使う。アクセストークンが切れたら、リフレッシュトークンを使って新しいアクセストークンを自動で取得する。ユーザーが頻繁にログインし直す必要がないのは、この仕組みのおかげだ。

自社アプリにログイン機能は必須なのか

社外に公開しない社内ツールでも、複数人が使うならログイン機能は付けたほうがよい。「誰が何をしたか」のログ(操作記録)を残せるし、退職者のアカウントを無効にすることもできる。1人だけで使う個人ツールなら、ログイン機能は不要な場合もある。

バイブコーディングで認証機能を頼むテンプレート

バイブコーディングでAIにログイン機能を依頼するとき、次のテンプレートが使える。


テンプレート: 認証・認可機能の実装依頼

「このアプリにログイン機能を追加したい。

認証方式:

  • メールアドレスとパスワードによるログイン
  • Googleアカウントでのログイン(OAuth)
  • パスワードリセット機能

認可(権限管理):

  • 管理者(admin): すべての機能にアクセス可能。ユーザーの追加・削除ができる
  • マネージャー(manager): チーム全員のデータを閲覧・編集できる。ユーザー管理はできない
  • 一般ユーザー(member): 自分のデータだけ閲覧・編集できる

技術的な要件:

  • Supabaseの認証機能を使うこと
  • パスワードは必ずハッシュ化して保存すること
  • ログイン画面、新規登録画面、パスワードリセット画面を作ること
  • ログインしていない場合はログイン画面にリダイレクトすること
  • 権限のない画面にアクセスした場合は403エラー画面を表示すること

まずデータベースのテーブル設計をJSONで見せてほしい。OKが出たら実装に入って。」


このテンプレートのポイントは3つある。

1つ目: 認証と認可を明確に分けて指示している。「ログイン機能をつけて」だけでは認可が抜ける。

2つ目: 権限の種類と、各権限でできることを具体的に書いている。admin、manager、memberの3段階で、それぞれの操作範囲が明確だ。

3つ目: 「まずデータベース設計をJSONで見せて」と段階を分けている。第13回のリソース設計、第15回のJSON知識を活かして、実装前にデータ構造を確認できる。

認証まわりのセキュリティで知っておくべきこと

バイブコーディングでAIがログイン機能を実装してくれたとしても、以下の3点は自分でチェックしておきたい。

1点目: パスワードの最低要件を設けているか。8文字以上、英数字混合など、短すぎるパスワードを拒否する仕組みがあるか。

2点目: ログイン失敗時のメッセージが具体的すぎないか。「メールアドレスが存在しません」と表示すると、攻撃者に「このメールアドレスは登録されていない」という情報を与えてしまう。「メールアドレスまたはパスワードが正しくありません」のように、どちらが間違っているかを特定できないメッセージが望ましい。

3点目: ログイン試行回数の制限があるか。パスワードを何回でも試せる状態だと、総当たり攻撃(ブルートフォースアタック)のリスクがある。5回失敗したら一定時間ロックする、といった制限を設けるのが一般的だ。

これらのチェックポイントをAIに伝えるには、こう依頼すればよい。「パスワードは8文字以上・英数字混合を必須にして。ログイン失敗メッセージはメールアドレスとパスワードのどちらが間違いかを特定できないようにして。5回連続で失敗したら15分間ロックして」。

まとめ

認証(あなたは誰?)と認可(あなたは何をしていい?)は、ログイン機能の両輪だ。パスワードはハッシュ化されて保存され、元に戻すことはできない。OAuth(オーオース)は、GoogleやLINEのアカウントを借りて本人確認する仕組みで、パスワードを預ける先を限定できる。JWT(ジェイダブリューティー)は、ユーザー情報と権限を1つのトークンに詰め込んだ通行証で、中身はJSONだ。バイブコーディングでログイン機能を依頼するときは、認証と認可を分けて具体的に指示することが、安全なアプリを作る第一歩になる。

次回は「HTTPS・セキュリティの基本 — 知らなかったでは済まない」。通信の暗号化、XSS、SQLインジェクションなど、バイブコーダーが最低限知っておくべきセキュリティの基礎を解説する。

参考リファレンス

  • 前回: 第15回「JSON完全理解 — データ形式の文法とバリデーション」(/articles/vc-015)
  • 次回: 第17回「HTTPS・セキュリティの基本 — 知らなかったでは済まない」(/articles/vc-017)
  • 第11回「ステートレスとCookie/セッション — ログイン状態の正体」(/articles/vc-011)
  • 第13回「リソース設計の実践 — AIに伝わるデータ構造の考え方」(/articles/vc-013)
  • バイブコーディング入門 カリキュラム(/vibe-coding)