Upgrade to Pro — share decks privately, control downloads, hide ads and more …

OAuth 2 & OpenID Connect 入門

OAuth 2 & OpenID Connect 入門

DeNA, Mobility Technologies合同の勉強会にて発表した資料です。
認証認可技術である OAuth2 と OpenID Connect について、雰囲気で使っている人向けに多少踏み込んで解説しています。

Yoshitaro Makise

November 20, 2021
Tweet

Other Decks in Programming

Transcript

  1. ▪ OAuth 2 と OpenID Connect の概要がわかる ▪ OAuth 2

    を認証に使ってはいけない理由がわかる ▪ OAuth 2 仕様の最近の改訂がなんとなくわかる ゴール
  2. ▪ 忘れてください ▪ Twitter はまだ使っている(OAuth1 & OAuth2) ▪ v2 API

    で OAuth2 に完全移行する様子 https://twittercommunity.com/t/announcing-oauth-2-0-beta/159 189 OAuth 1 ?
  3. なぜ OAuth2 が必要? ユーザーID・パスワードを 3rd party サービスに渡すと、以 下の問題がある ▪ 3rd

    party サービスはあらゆる操作ができてしまう ▪ 3rd party サービスが悪意を持った物と判明した場合、権限を取り消 すにはパスワードの変更をするしかない ▪ 3rd party サービスが攻撃されると、ユーザーID・パスワードが漏洩 する可能性がある
  4. ▪ confidential client ▪ クライアントシークレットを秘匿できる ▪ サーバーサイドのWebアプリケーション等 ▪ public client

    ▪ クライアントシークレットを秘匿できない ▪ ブラウザ上の JavaScript のみで動くアプリケーション、 スマートフォンアプリ等 ※ クライアントID, クライアントシークレットは事前に authz server か ら発行されたもの Client の種類
  5. ▪ authorization code flow ← 今回はこれのみ説明 ▪ implicit flow ▪

    client credentials flow ▪ resource owner password credentials flow ↑ grant type とも呼ばれる OAuth2 の4つの認可フロー
  6. ▪ confidential client 向けのフロー ▪ public client でも使える(後述) ▪ まず

    client に対して認可コード (authorization code) を 発行し、それを利用してアクセストークンを発行すると いう2段階を踏む Authorization code flow
  7. 3. Authorization request GET /authorize ?response_type=code &client_id=CEBoJysyLTNx &state=oYy67R1MRDIe &scope=write &redirect_uri=https://client.example.com/callback

    HTTP/1.1 Host: auth.example.com response_type “code”: authorization code の発行を要求 client_id 事前登録されたクライアントID state クライアントが生成したランダムな文字列。CSRF対策 scope クライアントが要求するスコープ redirect_uri クライアントのURL (事前登録したもの)
  8. 8. Authorization response HTTP/1.1 302 Found Location: https://client.example.com/callback ?code=LG0woSXfjcnmZl1eEB5UXUCq &state=oYy67R1MRDIe

    Host: auth.example.com code authorization code state 3. のリクエストに含まれる state
  9. 10. Token request POST /token HTTP/1.1 Host: auth.example.com Authorization: Basic

    Q0VCb0p5c3lMVE54Ojl0WmlFYXhIbjVtUnM2RUU Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &code=LG0woSXfjcnmZl1eEB5UXUCq &redirect_uri=https://client.example.com/callback Authorization header クライアントID:クライアントシークレットのBase64 (Basic認証) grant_type “authorization_code” code 8. のレスポンスで得た authorization code redirect_uri 3. のリクエストに含まれる redirect_uri
  10. 11. Token response HTTP/1.1 200 OK Content-Type: application/json; charset=UTF-8 Cache-Control:

    no-store Pragma: no-cache { "access_token": "HcnbNvYC1kyfwpcu", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "zONV1KOHi021MbHXRbjjZsXK" } access_token アクセストークン token_type “Bearer”: Bearer トークンであることを表す expires_in アクセストークンの有効期限(秒) refresh_token (optional) リフレッシュトークン
  11. ▪ authorization code の取得を経由する意義 ▪ client の認証 ▪ ブラウザ等を介さず直接 authz

    server から client にアクセス トークンを渡せる (アクセストークン漏洩防止) Authorization code flow
  12. ▪ authorization code flow ▪ implicit flow ▪ client credentials

    flow ▪ resource owner password credentials flow ↑ RFC 6749: OAuth 2.0 Authorization Framework で定義されたもの OAuth2 の4つの認可フロー (再掲)
  13. ▪ OAuth 2.0 策定時から事情が変わってきた ▪ 広く使われるにつれ、セキュリティが弱い箇所が判明 ▪ ブラウザの機能向上(CORS, History API)により、よりセキュアなフロー

    を利用できるようになった → 追加の拡張やベストプラクティスが提案されている ▪ RFC 7636: Proof Key for Code Exchange by OAuth Public Clients ▪ RFC 8252: OAuth 2.0 for Native Apps ▪ OAuth 2.0 Security Best Current Practice (Internet-Draft) ▪ OAuth 2.0 for Browser-Based Apps (Internet-Draft) RFC 6749 はもう古い
  14. ▪ authorization code flow ← 基本これ使う ▪ public client の場合

    PKCE 必須 ▪ confidential client の場合 PKCE 推奨 ▪ implicit flow ← 非推奨 ▪ client credentials flow ▪ resource owner password credentials flow ← 禁止 PKCE = RFC 7636: Proof Key for Code Exchange OAuth2 の現時点の推奨
  15. PKCE (in authorization code flow) ▪ authorization request, token request

    にそれぞれ code_challenge, code_verifier という値を受け渡し、authz server 側で検証 ▪ public client で authorization code flow を利用した場合に発生 しうる、認可コード横取り攻撃 を防止
  16. ▪ 認証(authentication): 誰であるかを確認すること ▪ 認可(authorization): リソースアクセスの権限を与えること OAuth 2 を認証に使える…? ▪

    アクセストークンを使ってプロフィールAPI からメールアドレス等を 取得、それをもって Client にログインしたことにする ただの OAuth 2 を認証に使ってはいけない
  17. ▪ アクセストークンが漏洩した場合、Client へのなりすましログインが 可能になる 例: ▪ 悪意のあるユーザーが何らかの手段で A さんの(プロフィールを取得でき る)アクセストークンを取得

    ↓ ▪ 悪意のあるユーザーが Authz Server へのログイン後、自分用のアクセ ストークンを A さんのアクセストークンに差し替え、Client へ送る ↓ ▪ Client はアクセストークンを受け取り、A さんのプロフィールを取得し たため、以降のセッションを A さんがログインしたと見なす ただの OAuth 2 を認証に使ってはいけない
  18. ▪ OAuth 2 のアクセストークンの多くは bearer トークン ▪ bearer トークン(持参人トークン) ▪

    トークンを持っている client なら利用でき、所有者や発行者につ いての検証が求められない ▪ 切符に例えられる ▪ bearer トークンを認証の拠り所にする事が NG Bearer トークン
  19. ▪ 「ただの」OAuth 2 はダメ ▪ 何らかトークン検証の仕組みを入れれば認証に使うことは可能ではあ る ▪ Facebook, GitHub

    等は OAuth2 を拡張して認証を実現している らしい ▪ 自分で発明するのはお勧めしない ▪ OpenID Connect 使いましょう ただの OAuth 2 を認証に使ってはいけない
  20. ▪ OpenID Connect 1.0: OAuth 2.0 の上に構築された、認証のための プロトコル ▪ 異なるサービス間でのアカウント連携が可能になる

    = サービス間でユーザーの紐付けが可能になる ▪ ソーシャルログイン ▪ その他様々な応用 OpenID Connect
  21. ▪ authorization code flow ← 今回はこれのみ説明 ▪ implicit flow ▪

    hybrid flow OpenID Connect の3つの認可フロー
  22. ヘッダー { "typ": "JWT", "alg": "RS256", "kid": "1dbc18c24fe5f913dbdf1550" } typ

    Type。JWT であることを表す alg Algorithm。RS256 = 公開鍵暗号RSA + ハッシュアルゴリズム SHA256 kid Key ID。公開鍵のID (alg = RS256 の場合)
  23. ペイロード { "iss": "https://accounts.google.com", "aud": "3444....7tsd0.apps.googleusercontent.com", "sub": "108557382958601058182", "iat": 1636095225,

    "exp": 1636098825, "nonce": "JO6Fy2xkPfP2pzyg" } iss Issuer。ID Token の発行者 aud Audience。Relying Party のクライアントID sub Subject。End user の識別子 iat Issued at。JWTの発行時刻 (UNIX time) exp Expiration time。ID Token の有効期限 nonce 認証リクエストに含まれる nonce (後述) と同じ値
  24. 3. Authorization request (認可コード取得のリクエスト) GET /authorize ?response_type=code &scope=openid profile email

    &client_id=CEBoJysyLTNx &state=oYy67R1MRDIe &redirect_uri=https://client.example.com/callback &nonce=JO6Fy2xkPfP2pzyg HTTP/1.1 Host: auth.example.com scope Relying Party が要求するスコープ openid: OpenID Connect で必須 profile: プロフィール情報へのアクセス(optional) email: メールアドレスへのアクセス(optional) nonce Relying Party が生成したランダムな文字列。リプレイ攻撃の防止用 OAuth 2 との差分:
  25. 10. Token request (トークン取得のリクエスト) POST /token HTTP/1.1 Host: auth.example.com Authorization:

    Basic Q0VCb0p5c3lMVE54Ojl0WmlFYXhIbjVtUnM2RUU Content-Type: application/x-www-form-urlencoded grant_type=authorization_code &code=LG0woSXfjcnmZl1eEB5UXUCq &redirect_uri=https://client.example.com/callback OAuth 2 との差分:なし
  26. 11. Token response HTTP/1.1 200 OK Content-Type: application/json; charset=UTF-8 Cache-Control:

    no-store Pragma: no-cache { "access_token": "HcnbNvYC1kyfwpcu", "token_type": "Bearer", "refresh_token": "zONV1KOHi021MbHXRbjjZsXK", "expires_in": 3600, "id_token": "eyJhbGciOiJSU◦◦◦◦◦XAiOiJKV1QifQ.eyJpc3MiOiJodHRw◦◦◦◦◦OjE2MzYwOTg4MjV 9.RB2YO15wqMQBBIJx4n7◦◦◦◦◦yIQuu6Gnquyrw-6Fg" } id_token ID Token OAuth 2 との差分:
  27. ID Token ペイロードの検証 { "iss": "https://accounts.google.com", "aud": "3444....7tsd0.apps.googleusercontent.com", "sub": "108557382958601058182",

    "iat": 1636095225, "exp": 1636098825, "nonce": "JO6Fy2xkPfP2pzyg" } iss ID Token の発行者 → 利用する ID Provider のものと一致するか aud Relying Party のクライアントID → 自分のクライアントIDと一致するか sub End User の識別子 iat JWTの発行時刻 (UNIX time) → 古すぎないか確認(optional) exp ID Token の有効期限 → 過ぎていないか確認 nonce → 認証リクエストに含まれる nonce と一致するか確認
  28. ▪ OAuth 2 ▪ 認可のためのプロトコル ▪ フロー例: authorization code flow

    ▪ OAuth 2.0 から追加の拡張やベストプラクティスが存在 ▪ (何も対策せずに)認証に使ってはいけない ▪ OpenID Connect ▪ OAuth 2 の上に構築された、認証のためのプロトコル ▪ ID Token を受け渡すことで認証が可能になる まとめ
  29. ▪ 雰囲気でOAuth2.0を使っているエンジニアがOAuth2.0を整理し て、手を動かしながら学べる本 ▪ OAuth、OAuth認証、OpenID Connectの違いを整理して理解できる 本 ▪ ↑ この2冊は入門におすすめ

    ▪ 本資料作成にあたってもシーケンス図や説明の流れなど参考にさ せて頂きました ▪ https://oauth.net/specs/ ▪ https://openid.net/developers/specs/ ▪ OAuth認証とは何か?なぜダメなのか - 2020冬 - r-weblife 参考