← 環境変数・シークレット管理 コンテナ(Docker) →

📑 この章の目次

title: 認証・認可 icon: 🔑 card_desc: 誰がアクセスしてよいかを決める仕組み — 認証と認可の違い・セッション/JWT・OAuth・MFA slug: 05-auth

05 認証・認可 — 「誰か」と「何をしてよいか」を区別する作法

「ログイン機能を作って」——この一言に、「本人確認(認証)」と「権限確認(認可)」という2つの全く別の問題が隠れています。この章では、現場で一番混同されやすいこの2つを、根本から区別できるようにします。


一言でいうと

認証(Authentication)は「あなたは誰か」を確認すること。認可(Authorization)は「あなたは何をしてよいか」を判断すること。この2つはセットで語られますが、別の問題です。ログイン画面でパスワードを入力するのは認証、ログイン後に「他人の注文履歴は見えない」になっているのは認可。認可を抜きにすると、誰もが管理者になれてしまいます。


1. なぜ認証・認可が必要なのか

まず、これがない世界を想像してください。

GET /api/users/123/orders    ← 誰が頼んだリクエストか分からない

このAPIに認証・認可がないと、何が起きるか:

これらは悪意がなくても起きる事故です。「自分のデータを見ようとしたら、URLの打ち間違いで他人のデータが見えた」という設計ミスは、現実によくあります。

通称: IDOR(アイディーオーアール/Insecure Direct Object Reference)。URLのIDを書き換えるだけで他人データにアクセスできる脆弱性。認可チェック忘れの代表例。

認証・認可は、「使い勝手」のためでなく「安全」のための仕組みです。後回しにされがちですが、最初から設計に組み込むのが作法です(→ 後述)。


2. 🔑 「認証」と「認可」の区別

ここが本章の核心です。この2つを混同するのが、初学者が一番よく陥る罠です。

認証(Authentication)= 誰か

「あなたはですか?」を確認すること。代表的な手段:

認証が成功すると、システムは「この利用者はユーザーID=123の山田さんだ」と身元を特定します。

認可(Authorization)= 何をしてよいか

「山田さんは、何をしてよいか」を判断すること。身元が分かった上で、さらに:

💡 権限の管理には「役割(管理者・一般等)で分ける」方式(RBAC: 役割ベースアクセス制御)等がよく使われます。いずれにせよ「誰が・何をしてよいか」をルール化しておくのが認可です。

例えていうと: ホテルのカードキー

フロントで身分証を提示してチェックインするのが認証。「あなたは201号室の山田様ですね」と身元を確認します。

部屋のカードキーで201号室のドアを開けるのが認可。201号室には入れるが、他人の部屋(202号室)のカードキーは使えない。これが「自分のリソースにはアクセスできる・他人のにはできない」という認可の構造です。

認証(Authentication) 認可(Authorization)
質問 ですか? 何をしてよいか?
タイミング ログイン時 ログイン後の毎操作
パスワード確認 「自分の注文か」「管理者か」
失敗例 「パスワードが違います」 「このページは閲覧権限がありません」

💡 頭文字の A が同じなので混同しやすいのが難点です。Authentication(認証)と Authorization(認可)。英語圏でも略すと両方「Auth」になるため、文脈で読み分けます。


3. セッション・Cookie方式 —— ブラウザ型の古典

「毎回パスワードを入力する」のは現実的ではありません。ログイン状態を維持する仕組みが必要です。その1つがセッション方式です。

仕組み

1. ログイン(ID + パスワード送信)
       ↓
2. サーバーが「この人はログイン中」と記憶(セッション生成)
       ↓
3. サーバーが「セッションID」をCookieでブラウザに渡す
       ↓
4. 以降のリクエストにはCookieが自動送信される
       ↓
5. サーバーはセッションIDを見て「誰か」を特定

メリットとデメリット

メリット デメリット
ブラウザがCookieを自動送信で楽 状態をサーバーが記憶(複数台構成でセッション共有の工夫が要る)
サーバー側でセッションを即座に無効化できる(ログアウト確実) モバイルアプリ・他サービス連携に不向き
歴史が長く実績豊富 CSRFの対策が別途必要(後述)

💡 「ステートフル」(状態あり)な方式。サーバーが「誰がログイン中か」を覚えているのが特徴。そのためログアウトはサーバー側でセッションを消せば確実(Cookieを消すだけでは不十分)。API(ステートレス指向)とは相性が良くない面があります(→ 第3章 REST の「ステートレス」参照)。


4. トークン方式 JWT —— API・モバイル向き

セッション方式の「サーバーが状態を記憶する」という負担を減らすため、トークン方式が登場しました。代表が JWT(ジェイダブリューティー/通称「ジョット」/JSON Web Token)です。

トークンとは

ログイン成功時、サーバーはトークン(入場券のような文字列)を発行します。以降、クライアントはリクエストのたびこのトークンを添えて送ります。サーバーはトークンを見て「誰か」「権限」を判断します。

JWT の特徴

JWT は、署名付きの JSON データです。中身は大きく3部構成:

ヘッダ.ペイロード.署名

💡 ペイロードは誰でも読めます(Base64でエンコードされているだけ・暗号化ではない)。重要なのは「署名があることで改ざんを検知できる」点。鍵を持たない攻撃者は、署名付きの正しいトークンを作れません。

メリットとデメリット

メリット デメリット
サーバーが状態を記憶しなくてよい(ステートレス) 発行後の無効化が難しい(有効期限が切れるまで有効)
モバイル・他サービス連携に向く ペイロードは読めるので機密情報を入れてはいけない
複数台構成でスケールしやすい 扱いを間違えると重大な脆弱性になる(→ 後述)

💡 無効化の工夫: JWTは「発行したら期限まで有効」が基本ですが、実運用では「短命のアクセストークン長命のリフレッシュトークン」の2段構えにし、リフレッシュトークンをサーバー側で無効化できるようにする等の工夫がよく使われます。

JWTの落とし穴: 「署名検証をしない」「alg: none攻撃を許す」「機密情報をペイロードに入れる」等の実装ミスが、深刻な認証バイパスにつながります。ライブラリを正しく使い、検証は必ず行います。


5. OAuth / OpenID Connect —— 「Googleでログイン」の正体

Googleでログイン」「GitHubでログイン」を見たことがあるでしょう。これの正体が OAuth(オース/通称「オーオース」も/OAuth 2.0)と、その上に乗る OpenID Connect(オープンアイディー・コネクト/OIDC)です。

OAuth は「委譲」

OAuth の核心は委譲(いじょう)——「あなたの代わりに、限られたことだけ、外部のサービスに許可する」仕組みです。

例: あなたが「写真印刷サービス」にGoogleフォトの写真へのアクセスを許可する。

あなた  →  Google: 「写真印刷サービスに写真を読む権限を渡して」
Google  →  写真印刷サービス: 「写真を読むためのアクセストークン」を発行
写真印刷サービス  →  GoogleフォトAPI: トークンを使って写真を取得

OpenID Connect は「認証」

OAuth(委譲=認可)の上に、「この人はGoogleアカウントの誰か」という認証の仕組みを乗せたのが OIDC。「Googleでログイン」のボタンを押すと、Googleが「この人はこの人です」と**保証(IDトークン発行)**してくれます。

OAuth 2.0 OpenID Connect
役割 認可(委譲: 限られた権限を貸す) 認証(この人は誰か)
よく使う場面 「アプリに〇〇へのアクセスを許可」 「Googleでログイン」
関係 基盤(下回り) OAuth の上に認証を乗せたもの

「外部に任せて安心」ではない: OIDC を使う側は、受け取ったIDトークンの署名と内容(発行者・有効期限・宛先等)を必ず検証します。検証をサボると、偽のIDトークンで成りすまされる事故に繋がります。「成熟した基盤に任せる」選択は有効ですが、検証の責任は使う側にある点に注意。


6. 多要素認証 MFA —— 「1つの鍵」に頼らない

パスワードだけだと、1つ漏れただけで侵入されるリスクがあります。これを減らすのが多要素認証MFA/エムエフエー)です。

認証の3要素

MFA は、以下の異なる性質の要素を組み合わせます:

要素 特徴
知識(知っていること) パスワード・暗証番号 忘れたら困る・他人に教えうる
所有(持っていること) スマホ(SMS/アプリ)・セキュリティキー 物理的に必要・なくすと困る
生体(本人であること) 指紋・顔・虹彩 忘れない・なくさないが変更不可

💡 「所有」の代表格としてパスキーFIDO2 / WebAuthn 等の技術)が近年広がっています。パスワードをなくし、フィッシング(偽サイト騙し)に強いのが特徴。注目される「パスワードレス」の方向です。

「パスワード(知識)+ スマホのワンタイムコード(所有)」のように、異なる性質を2つ以上組み合わせるのが MFA の基本。「同じ性質」を2つ(例: パスワード+もう一つパスワード)は、同一要素の重複で MFA の意味が薄れます。

💡 2FA(ツーエフエー/二要素認証)は MFA の「2つ組み合わせ」版。現場では 2FA / MFA ほぼ同義で使われます。

なぜ効果的か

パスワードが漏洩しても、**スマホ(所有)**がなければログインできません。攻撃者は「パスワードを知っている」だけでなく「物理的にスマホも手に入れる」必要があり、難易度が跳ね上がります。


7. よくある落とし穴と、なぜ「作法」なのか

❌ やってはいけないこと

落とし穴 何が起きるか 正しい対応
パスワードを平文で保存 DB漏洩ですべてバレる ハッシュ化bcrypt等の専用アルゴリズム)して保存(→ 第4章
認可チェックを忘れる(IDOR) 他人データが見える 自分のリソースか・権限があるか」を毎操作で確認
トークンをlocalStorage等に無防備に置く XSS(スクリプト注入)で盗まれる 保管場所を吟味(HttpOnly Cookie 等・用途で判断)
HTTPSを使わない 通信を盗聴されてトークン・パスワード漏洩 本番は必ずHTTPS(→ 第4章: 暗号化通信)
JWTの署名検証をしない 任意のトークンで成りすませる ライブラリを正しく使い必ず検証
権限を「フロントだけ」で隠す APIを直接叩かれると突破される サーバー側で必ず認可チェック(フロントの隠蔽はUX用)
CSRF対策をしない(Cookie方式) 悪意あるサイトから勝手にリクエスト送られる SameSite属性・CSRFトークン等で対策
ログイン試行を無制限に許す ブルートフォース(総当たり)で破られる 試行回数制限・ロック(→ 第3章: レート制限)

✅ 認証・認可の設計の作法

  1. 認証と認可を明確に分ける —— 「誰か」と「何をしてよいか」は別のレイヤー
  2. 認可チェックはサーバー側で毎回 —— フロントのUI制御だけでは不十分
  3. パスワードは絶対ハッシュ化bcrypt等・生保存・可逆復元しない)
  4. HTTPSを必須にする(本番での平文通信は論外)
  5. MFAで「1つの鍵」に頼らない(知識+所有等の組み合わせ)
  6. 成熟した基盤(OIDC等)の活用を検討(自作リスクの回避・ただし検証は必須)
  7. ブルートフォース対策(試行回数制限・ロック)を忘れない

💡 CSRF(シーエスアールエフ/Cross-Site Request Forgery/「偽造リクエスト」): ユーザーがログイン中に、悪意ある別サイトが「勝手にリクエストを送る」攻撃。Cookieが自動送信される仕組みを悪用するため、Cookie方式では特に注意が必要です。

面接・実務での意味

「認証と認可の違い、説明できますか?」

この質問は、「安全な設計ができるか」を問う一番手軽な検査です。「同じだろ」と答える人は、IDOR等の認可不備を作りがちです。逆に「認証は誰か・認可は何をしてよいか」と即答でき、さらに「認可チェックはサーバー側で毎回必須」と言える人は、現場で信頼されます。


まとめ

💡 次のステップ: 誰がアクセスしてよいかの「認証・認可」が見えました。次は、開発現場で「環境を丸ごと運ぶ」もう一つの基盤技術——**コンテナ(Docker)**を扱います。第6章では、開発環境と本番環境の差異をなくす作法を学びます。