Slide 1

Slide 1 text

Yoshitaro Makise 株式会社 Mobility Technologies OAuth 2 & OpenID Connect 入門

Slide 2

Slide 2 text

▪ OAuth 2 と OpenID Connect の概要がわかる ▪ OAuth 2 を認証に使ってはいけない理由がわかる ▪ OAuth 2 仕様の最近の改訂がなんとなくわかる ゴール

Slide 3

Slide 3 text

3 OAuth 2

Slide 4

Slide 4 text

▪ 認可(authorization)のためのプロトコル ▪ = 権限移譲のためのプロトコル ※ HTTP(S)サービスが対象 OAuth 2 とは? 一時的・ 限定的な 権限移譲 アクセス

Slide 5

Slide 5 text

▪ 忘れてください ▪ Twitter はまだ使っている(OAuth1 & OAuth2) ▪ v2 API で OAuth2 に完全移行する様子 https://twittercommunity.com/t/announcing-oauth-2-0-beta/159 189 OAuth 1 ?

Slide 6

Slide 6 text

なぜ OAuth2 が必要? アクセス ユーザーID パスワード

Slide 7

Slide 7 text

なぜ OAuth2 が必要? ユーザーID・パスワードを 3rd party サービスに渡すと、以 下の問題がある ▪ 3rd party サービスはあらゆる操作ができてしまう ▪ 3rd party サービスが悪意を持った物と判明した場合、権限を取り消 すにはパスワードの変更をするしかない ▪ 3rd party サービスが攻撃されると、ユーザーID・パスワードが漏洩 する可能性がある

Slide 8

Slide 8 text

OAuth2 のロール(登場人物)

Slide 9

Slide 9 text

ロールの関係 ① ①リソースへのアクセス権を要求 ② ②アクセス権の移譲を許可するか確認 ③ ③アクセス権の移譲を許可 ④アクセストークンを発行 ④ ⑤ ⑤アクセストークンを利用しリソース にアクセス

Slide 10

Slide 10 text

▪ confidential client ▪ クライアントシークレットを秘匿できる ▪ サーバーサイドのWebアプリケーション等 ▪ public client ▪ クライアントシークレットを秘匿できない ▪ ブラウザ上の JavaScript のみで動くアプリケーション、 スマートフォンアプリ等 ※ クライアントID, クライアントシークレットは事前に authz server か ら発行されたもの Client の種類

Slide 11

Slide 11 text

▪ authorization code flow ← 今回はこれのみ説明 ▪ implicit flow ▪ client credentials flow ▪ resource owner password credentials flow ↑ grant type とも呼ばれる OAuth2 の4つの認可フロー

Slide 12

Slide 12 text

▪ confidential client 向けのフロー ▪ public client でも使える(後述) ▪ まず client に対して認可コード (authorization code) を 発行し、それを利用してアクセストークンを発行すると いう2段階を踏む Authorization code flow

Slide 13

Slide 13 text

Authorization code flow

Slide 14

Slide 14 text

Authorization code flow authorization code 取得 アクセストークン取得 リソースへのアクセス

Slide 15

Slide 15 text

Authorization code 取得 authorization code 取得

Slide 16

Slide 16 text

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 (事前登録したもの)

Slide 17

Slide 17 text

認証画面

Slide 18

Slide 18 text

認可画面

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Authorization code flow アクセストークン取得

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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) リフレッシュトークン

Slide 23

Slide 23 text

▪ authorization code の取得を経由する意義 ▪ client の認証 ▪ ブラウザ等を介さず直接 authz server から client にアクセス トークンを渡せる (アクセストークン漏洩防止) Authorization code flow

Slide 24

Slide 24 text

24 OAuth 2 最近の改訂

Slide 25

Slide 25 text

▪ authorization code flow ▪ implicit flow ▪ client credentials flow ▪ resource owner password credentials flow ↑ RFC 6749: OAuth 2.0 Authorization Framework で定義されたもの OAuth2 の4つの認可フロー (再掲)

Slide 26

Slide 26 text

▪ 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 はもう古い

Slide 27

Slide 27 text

▪ 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 の現時点の推奨

Slide 28

Slide 28 text

PKCE (in authorization code flow) ▪ authorization request, token request にそれぞれ code_challenge, code_verifier という値を受け渡し、authz server 側で検証 ▪ public client で authorization code flow を利用した場合に発生 しうる、認可コード横取り攻撃 を防止

Slide 29

Slide 29 text

29 OAuth認証

Slide 30

Slide 30 text

▪ 認証(authentication): 誰であるかを確認すること ▪ 認可(authorization): リソースアクセスの権限を与えること OAuth 2 を認証に使える…? ▪ アクセストークンを使ってプロフィールAPI からメールアドレス等を 取得、それをもって Client にログインしたことにする ただの OAuth 2 を認証に使ってはいけない

Slide 31

Slide 31 text

▪ アクセストークンが漏洩した場合、Client へのなりすましログインが 可能になる 例: ▪ 悪意のあるユーザーが何らかの手段で A さんの(プロフィールを取得でき る)アクセストークンを取得 ↓ ▪ 悪意のあるユーザーが Authz Server へのログイン後、自分用のアクセ ストークンを A さんのアクセストークンに差し替え、Client へ送る ↓ ▪ Client はアクセストークンを受け取り、A さんのプロフィールを取得し たため、以降のセッションを A さんがログインしたと見なす ただの OAuth 2 を認証に使ってはいけない

Slide 32

Slide 32 text

▪ OAuth 2 のアクセストークンの多くは bearer トークン ▪ bearer トークン(持参人トークン) ▪ トークンを持っている client なら利用でき、所有者や発行者につ いての検証が求められない ▪ 切符に例えられる ▪ bearer トークンを認証の拠り所にする事が NG Bearer トークン

Slide 33

Slide 33 text

▪ 「ただの」OAuth 2 はダメ ▪ 何らかトークン検証の仕組みを入れれば認証に使うことは可能ではあ る ▪ Facebook, GitHub 等は OAuth2 を拡張して認証を実現している らしい ▪ 自分で発明するのはお勧めしない ▪ OpenID Connect 使いましょう ただの OAuth 2 を認証に使ってはいけない

Slide 34

Slide 34 text

34 OpenID Connect

Slide 35

Slide 35 text

▪ OpenID Connect 1.0: OAuth 2.0 の上に構築された、認証のための プロトコル ▪ 異なるサービス間でのアカウント連携が可能になる = サービス間でユーザーの紐付けが可能になる ▪ ソーシャルログイン ▪ その他様々な応用 OpenID Connect

Slide 36

Slide 36 text

OpenID Connect のロール(登場人物)

Slide 37

Slide 37 text

▪ authorization code flow ← 今回はこれのみ説明 ▪ implicit flow ▪ hybrid flow OpenID Connect の3つの認可フロー

Slide 38

Slide 38 text

OIDC Authorization code flow

Slide 39

Slide 39 text

▪ End User の認証に使われるトークン ▪ フォーマットは JWT (JSON Web Token) と規定されている ID Token

Slide 40

Slide 40 text

▪ RFC 7519: JSON Web Token (JWT) ▪ JSON を署名や暗号化してやりとりするためのフォーマット ▪ 署名付き = 作成者の保証、改ざん検知ができる JWT

Slide 41

Slide 41 text

JWTの構造 eyJhbGciOiJSU○○○○○XAiOiJKV1QifQ.eyJpc3MiOiJodHRw○○○○○OjE2MzYwOTg4MjV9 .RB2YO15wqMQBBIJx4n7○○○○○yIQuu6Gnquyrw-6Fg eyJhbGciOiJSU○○○○○XAiOiJKV1QifQ.        ← ヘッダー eyJpc3MiOiJodHRw○○○○○OjE2MzYwOTg4MjV9.     ← ペイロード RB2YO15wqMQBBIJx4n7○○○○○yIQuu6Gnquyrw-6Fg   ← 署名 ピリオドで区切られた 3つの Base64UrlEncode文字列

Slide 42

Slide 42 text

ヘッダー { "typ": "JWT", "alg": "RS256", "kid": "1dbc18c24fe5f913dbdf1550" } typ Type。JWT であることを表す alg Algorithm。RS256 = 公開鍵暗号RSA + ハッシュアルゴリズム SHA256 kid Key ID。公開鍵のID (alg = RS256 の場合)

Slide 43

Slide 43 text

ペイロード { "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 (後述) と同じ値

Slide 44

Slide 44 text

▪ base64urlEncode(header) + '.' + base64urlEncode(payload) を秘密鍵で署名したものを base64urlEncode したもの 署名

Slide 45

Slide 45 text

OIDC Authorization code flow (再掲)

Slide 46

Slide 46 text

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 との差分:

Slide 47

Slide 47 text

8. Authorization response (認可コード返却) HTTP/1.1 302 Found Location: https://client.example.com/callback ?code=LG0woSXfjcnmZl1eEB5UXUCq &state=oYy67R1MRDIe Host: auth.example.com OAuth 2 との差分:なし

Slide 48

Slide 48 text

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 との差分:なし

Slide 49

Slide 49 text

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 との差分:

Slide 50

Slide 50 text

▪ 署名を検証する ▪ alg:RS256の場合、公開鍵を使って検証 ▪ 公開鍵は通常、ID Provider が提供しているエンドポイントにて 公開されている ▪ RFC 7517: JSON Web Key (JWK) ▪ ペイロードを検証する ID Token の検証

Slide 51

Slide 51 text

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 と一致するか確認

Slide 52

Slide 52 text

▪ OAuth 2 ▪ 認可のためのプロトコル ▪ フロー例: authorization code flow ▪ OAuth 2.0 から追加の拡張やベストプラクティスが存在 ▪ (何も対策せずに)認証に使ってはいけない ▪ OpenID Connect ▪ OAuth 2 の上に構築された、認証のためのプロトコル ▪ ID Token を受け渡すことで認証が可能になる まとめ

Slide 53

Slide 53 text

▪ 雰囲気でOAuth2.0を使っているエンジニアがOAuth2.0を整理し て、手を動かしながら学べる本 ▪ OAuth、OAuth認証、OpenID Connectの違いを整理して理解できる 本 ▪ ↑ この2冊は入門におすすめ ▪ 本資料作成にあたってもシーケンス図や説明の流れなど参考にさ せて頂きました ▪ https://oauth.net/specs/ ▪ https://openid.net/developers/specs/ ▪ OAuth認証とは何か?なぜダメなのか - 2020冬 - r-weblife 参考