#はじめに

「Googleでログイン」「GitHubで続ける」——これらのボタンを押したとき、裏側では何が起きているのでしょうか?

OAuth 2.0とOIDC(OpenID Connect)は、このような「ソーシャルログイン」や「API連携」を実現するための標準仕様です。これらを理解することで、セキュアな認証・認可システムを設計できるようになります。

この記事を読むと、以下のことができるようになります:

  • 認証と認可の違いを理解できる
  • OAuth 2.0の基本的なフローがわかる
  • OIDCがOAuth 2.0に何を追加するのかがわかる
  • 実装時のセキュリティ上の注意点を理解できる

#認証と認可の違い

OAuth 2.0とOIDCを理解するには、まず「認証」と「認可」の違いを明確にする必要があります。

#認証(Authentication)

「あなたは誰ですか?」 を確認すること。

ユーザー: 「私は山田です」
システム: 「パスワードを入力してください」
ユーザー: 「****」
システム: 「確かに山田さんですね」 ← 認証完了

#認可(Authorization)

「あなたは何ができますか?」 を確認すること。

山田さん: 「Googleドライブのファイルにアクセスしたい」
Google: 「このアプリにファイルへのアクセスを許可しますか?」
山田さん: 「許可する」
Google: 「アクセス権を与えます」 ← 認可完了

#重要なポイント

認証認可
質問Who are you?What can you do?
結果身元の確認権限の付与
ログインAPIアクセス許可

OAuth 2.0は認可の仕様であり、認証の仕様ではありません。これは非常に重要な違いです。

#OAuth 2.0とは

OAuth 2.0は、サードパーティアプリケーションにリソースへのアクセス権を安全に委譲するための認可フレームワークです。

#なぜ必要か

従来の方法では、サードパーティアプリにパスワードを渡す必要がありました。

# 危険な従来の方法
「このアプリにGoogleのユーザー名とパスワードを入力してください」

問題:
- パスワードが漏洩するリスク
- アプリに全権限が渡る
- パスワード変更時に再設定が必要

OAuth 2.0では、パスワードを渡さずに、必要な権限だけを委譲できます。

# OAuth 2.0の方法
「Googleにリダイレクトして、このアプリにカレンダーへのアクセスを許可してください」

メリット:
- パスワードを共有しない
- 必要な権限だけを付与
- いつでも取り消し可能

#OAuth 2.0の登場人物

役割説明
リソースオーナーリソースの所有者(ユーザー)あなた
クライアントリソースにアクセスしたいアプリカレンダーアプリ
認可サーバーアクセス権を発行するサーバーGoogleの認可エンドポイント
リソースサーバー保護されたリソースを持つサーバーGoogle Calendar API

#認可コードフロー

最もセキュアで一般的なフローです。Webアプリケーションで推奨されます。

[ユーザー]      [クライアントアプリ]      [認可サーバー]      [リソースサーバー]
    |                  |                      |                     |
    |-- 1. ログインボタン -->|                |                     |
    |                  |                      |                     |
    |<-- 2. 認可サーバーへリダイレクト --------|                     |
    |                  |                      |                     |
    |------------------ 3. 認可リクエスト ---->|                     |
    |                  |                      |                     |
    |<----------------- 4. ログイン画面 ------|                     |
    |                  |                      |                     |
    |------------------ 5. 認証情報入力 ----->|                     |
    |                  |                      |                     |
    |<----------------- 6. 権限確認画面 ------|                     |
    |                  |                      |                     |
    |------------------ 7. 許可する ---------->|                     |
    |                  |                      |                     |
    |<-- 8. 認可コード付きでリダイレクト ------|                     |
    |                  |                      |                     |
    |                  |-- 9. 認可コード + クライアントシークレット -->|
    |                  |                      |                     |
    |                  |<-- 10. アクセストークン --|                 |
    |                  |                      |                     |
    |                  |------------------- 11. API呼び出し ------->|
    |                  |                      |                     |
    |                  |<------------------- 12. リソース ----------|
    |                  |                      |                     |
    |<-- 13. 結果表示 --|                      |                     |

#各ステップの詳細

#2-3. 認可リクエスト

GET https://accounts.google.com/o/oauth2/v2/auth
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/callback
  &response_type=code
  &scope=https://www.googleapis.com/auth/calendar.readonly
  &state=xyz123
パラメータ説明
client_idアプリの識別子
redirect_uri認可後のリダイレクト先
response_typecode(認可コードフロー)
scope要求する権限
stateCSRF対策用のランダム値

#8. 認可コードの受け取り

GET https://yourapp.com/callback
  ?code=AUTHORIZATION_CODE
  &state=xyz123

stateの検証を必ず行ってください。 リクエスト時に送ったstateと一致しなければ、CSRF攻撃の可能性があります。

#9-10. トークンの取得

POST https://oauth2.googleapis.com/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=https://yourapp.com/callback
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET

レスポンス:

{
  "access_token": "ya29.a0AfH6...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "1//0g..."
}

#PKCE(Proof Key for Code Exchange)

SPAやモバイルアプリなど、クライアントシークレットを安全に保管できない環境では、PKCEを使用します。

#PKCEの仕組み

  1. クライアントがランダムなcode_verifierを生成
  2. code_verifierのハッシュ値(code_challenge)を認可リクエストに含める
  3. トークン取得時にcode_verifierを送信
  4. 認可サーバーがハッシュを検証
# 認可リクエスト
code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256

# トークンリクエスト
code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

これにより、認可コードを傍受されても、code_verifierがなければトークンを取得できません。

#OpenID Connect(OIDC)

OIDCは、OAuth 2.0の上に認証機能を追加した仕様です。

OAuth 2.0だけでは「誰がログインしたか」はわかりません(認可のみ)。OIDCはIDトークンを導入し、ユーザーの身元情報を取得できるようにします。

#OIDCが追加するもの

要素説明
IDトークンユーザー情報を含むJWT
UserInfoエンドポイントユーザー情報を取得するAPI
標準スコープopenid, profile, emailなど

#IDトークンの例

{
  "iss": "https://accounts.google.com",
  "sub": "110169484474386276334",
  "aud": "YOUR_CLIENT_ID",
  "exp": 1311281970,
  "iat": 1311280970,
  "name": "山田太郎",
  "email": "yamada@gmail.com",
  "picture": "https://..."
}

#OIDCフロー

OAuth 2.0のフローとほぼ同じですが、scopeopenidを含め、レスポンスにid_tokenが追加されます。

# 認可リクエスト
scope=openid profile email

# トークンレスポンス
{
  "access_token": "ya29.a0AfH6...",
  "id_token": "eyJhbGciOiJSUzI1...",  ← これが追加
  "token_type": "Bearer",
  "expires_in": 3600
}

#セキュリティ上の注意点

#1. stateパラメータの使用

CSRF攻撃を防ぐため、必ずstateパラメータを使用し、コールバック時に検証してください。

// 認可リクエスト前
const state = generateRandomString();
sessionStorage.setItem('oauth_state', state);

// コールバック時
const returnedState = new URLSearchParams(window.location.search).get('state');
if (returnedState !== sessionStorage.getItem('oauth_state')) {
  throw new Error('Invalid state parameter');
}

#2. redirect_uriの厳密な検証

認可サーバー側で、登録されたredirect_uriと完全一致するか検証してください。

# 攻撃例
redirect_uri=https://yourapp.com/callback/../../../evil.com

# 対策: 完全一致のみ許可

#3. PKCEの使用

SPAやモバイルアプリでは、必ずPKCEを使用してください。

#4. トークンの安全な保管

  • アクセストークン: メモリまたは短命Cookie
  • リフレッシュトークン: HttpOnly Cookie
  • IDトークン: 検証後、必要な情報のみ保持

#5. IDトークンの検証

IDトークンを受け取ったら、以下を検証してください:

  • 署名の検証
  • iss(発行者)が期待値と一致
  • aud(対象者)が自分のclient_idと一致
  • exp(有効期限)が現在時刻より後

#まとめ

  • 認証は「誰か」、認可は「何ができるか」
  • OAuth 2.0は認可の仕様、OIDCが認証を追加
  • 認可コードフローが最も安全、SPAではPKCEを併用
  • IDトークンでユーザー情報を取得(OIDC)
  • セキュリティ対策: state、PKCE、redirect_uri検証、トークン検証

#次のステップ

Cookie・認証・セッションモジュールはこれで完了です。Cookieの基本から、SameSite属性、セッション管理、JWT、そしてOAuth 2.0/OIDCまで学びました。

次のモジュールでは、オリジンとセキュリティについて学びます。同一オリジンポリシー、CORS、CSPなど、ブラウザのセキュリティモデルを理解しましょう。

#参考リンク