Slide 1

Slide 1 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 2020年2⽉4⽇ ヤフー株式会社 倉林 雅 ⿊帯ハンズオン 〜認証技術〜 Go⾔語で学ぶYahoo! ID連携の⿊帯ハンズオン

Slide 2

Slide 2 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. プロフィール 2 倉林 雅(くらはやし まさる) ヤフー株式会社 認証技術⿊帯 / ID・セキュリティエンジニア OpenID ファウンデーション・ジャパン 理事 / エバンジェリスト

Slide 3

Slide 3 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 3 https://twitter.com/kura_lab

Slide 4

Slide 4 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. ⿊帯制度 4 該当分野について突出した知識とスキルを 持っている第⼀⼈者 ⿊帯制度 http://hr.yahoo.co.jp/workplace/culture.html

Slide 5

Slide 5 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. アジェンダ 5 1. OpenID Connectの概要説明 2. Go⾔語によるYahoo! ID連携の実装 3. 実装のポイント、セキュリティ対策の解説 4. まとめ

Slide 6

Slide 6 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. OpenID Connectの概要説明

Slide 7

Slide 7 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 7 OpenID Connectの提供する機能 簡単にいうと 「ユーザー認証」と「属性情報取得」

Slide 8

Slide 8 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 8 所持しているIDのサービスを選択 ログインをする

Slide 9

Slide 9 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 9 同意をする 情報がプリセットされる

Slide 10

Slide 10 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. ⽤語集 10 IdP (Identity Provider) • 認証を⾏ってID、属性情報を提供する RP (Relying Party) • IdPの認証を利⽤してEnd-Userにサービスを提供する Claim • IdPやEnd-Userなどの属性情報

Slide 11

Slide 11 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. OpenIDとは 11 • OpenIDはユーザーの認証の技術 • (OpenID AXで属性を取得する拡張はある) • XML・SOAPベースのプロトコル

Slide 12

Slide 12 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. OpenID 12 2006年 • OpenID Authentication 1.1 • OpenID Simple Registration Extension 1.0 2007年 • OpenID Authentication 2.0 • OpenID Attribute Exchange 1.0

Slide 13

Slide 13 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. OAuth 13 • OAuth 1.0とOAuth 2.0はユーザーの認可の技術 • ユーザーのリソースアクセス(Web API)が⽬的 • JSONとRESTライクのプロトコル

Slide 14

Slide 14 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. OAuth 14 2009年 • OAuth 1.0a 2010年 • OAuth 1.0 Protocol 2012年 • OAuth 2.0 Authorization Framework オーオースッ

Slide 15

Slide 15 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. OpenID Connectとは 15 • ユーザーの認証と認可を兼ね備えた技術 • OpenIDとは異なる技術でOAuth 2.0を拡張した プロトコル • JSONとRESTライクのプロトコル • 2014年2⽉にローンチ

Slide 16

Slide 16 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 16 https://openid.net/connect/

Slide 17

Slide 17 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 17 https://openid.net/connect/ OpenID ConnectはOAuth 2.0や JSON Web Tokenなどの技術で構成されている

Slide 18

Slide 18 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. OpenID Connect 18 Web API連携・ユーザー認証・ ユーザー属性情報取得に必要な仕様が定義れている 認可 認証 属性取得 OAuth 2.0 JSON Web Token

Slide 19

Slide 19 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. OpenID Connect 19 • OpenID Connectには多様なユースケースに適 応できるよう3つのフローが定義されている 1. Implicit Flow 2. Authorization Code Flow 3. Hybrid Flow

Slide 20

Slide 20 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Implicit Flow 20 • 主にスクリプト⾔語を⽤いて実装されブラウザ上で 動作するClientによって使⽤される • Access TokenとID Tokenは、Clientに直接返却され End-UserとEnd-UserのUser Agentにアクセスする アプリケーションに露出する可能性がある • Authorization Serverはクライアント認証を⾏わない

Slide 21

Slide 21 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 21 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server Resource Server (UserInfo) 0.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 6.Access Token/ID Token 8.Access Token 9.Claims 4.同意画⾯ 10.属性情報取得完了 7.ログイン完了 Implicit Flow

Slide 22

Slide 22 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Authorization Code Flow 22 • ClientにAuthorization Codeを返却し、Clientはそれを 直接ID TokenおよびAccess Tokenと交換するため、 User AgentやUser Agent上の他の不正アプリケーショ ンなどにトークンが露呈することがない • Authorization Serverは、Authorization Codeを Access Tokenと交換する前にClientを認証することも できる • Client SecretをClientとAuthorization Serverの間でセ キュアに保てるClientに適している

Slide 23

Slide 23 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 23 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server Resource Server (UserInfo) 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token/ID Token 11.Access Token 12.Claims 4.同意画⾯ 0-2.処理開始 6.Authorization Code 7.Tokenリクエスト(Authorization Code) 13.属性情報取得完了 9.ログインセッション 発⾏ 10.ログイン完了 Authorization Code Flow

Slide 24

Slide 24 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Hybrid Flow 24 • Authorization EndpointからAccess TokenとID Token がブラウザー上のClientに直接返却される • さらにAuthorization Codeが返却され、Token EndpointでAccess TokenとID TokenがBack-End Serverに返却される

Slide 25

Slide 25 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 25 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server Resource Server (UserInfo) 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 12.Access Token/ID Token 15.Access Token 16.Claims 4.同意画⾯ 0-2.処理開始 6.Authorization Code/Access Token/ID Token 11.Tokenリクエスト(Authorization Code) 17.属性情報取得完了 13.ログインセッション 発⾏ 14.ログイン完了 10.Authorization Code 8.Access Token 7.クライアントサイド ログイン完了 9.クライアントサイド 属性情報取得完了 Hybrid Flow

Slide 26

Slide 26 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Hybrid Flowを導⼊する前に 26 • Authorization Codeをサーバーへ送信する前に、 Clientサイドでユーザー認証をいち早く完了させたい場 合などに利⽤できる • ただし、⼤抵の3rd PartyアプリケーションはID管理を Back-End Serverで⾏うため、Clientサイドのユー ザー認証は不要である • Hybrid Flowを導⼊する前に、Authorization Code FlowでID連携の要件を満たすことができるか検討すべ きである

Slide 27

Slide 27 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Go⾔語によるYahoo! ID連携の実装

Slide 28

Slide 28 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 0. 事前準備 • Go実⾏環境セットアップ • 以下の⼿順に従い環境を設定し動作確認をしてください。 • https://github.com/kura-lab/kuroobi-hands-on- 2020/tree/20200204/practice00 • 今回は「go1.13.7」のバージョンを使⽤します。 注意点 2020年2⽉4⽇時点の演習のソースコードは 「master」ブランチではなく「20200204」ブランチになっています。

Slide 29

Slide 29 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 0. 事前準備 • OpenID Connectを提供しているYahoo! JAPANの Yahoo! ID連携 v2を利⽤します。 • Yahoo! ID連携とは • https://developer.yahoo.co.jp/yconnect/v2/introduction.html

Slide 30

Slide 30 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 0. 事前準備 30 • 以下のサイトの1〜3のステップに従いClient IDを登録する。 • Yahoo! ID連携 v2 > 利⽤までのステップ • https://developer.yahoo.co.jp/yconnect/v2/ • 今回は「サーバーサイド(Yahoo! ID連携 v2)」のClient IDを 使って「Authorization Code Flow」をGo⾔語で実装します。 • Client IDとClient Secretを発⾏してしてください。 • コールバックURLに「http://localhost:8080/callback」を 登録してください。

Slide 31

Slide 31 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 1. Authorizationリクエスト 31 • RP(Client)からUserAgentを利⽤してIdP (AuthN/AuthZ Server)へリクエストする • IdPのID(Yahoo! JAPAN ID)でログインし、ユー ザー同意画⾯を表⽰し同意を取得する https://github.com/kura-lab/kuroobi-hands-on-2020/tree/20200204/practice01 演習ソースコード

Slide 32

Slide 32 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 32 ログイン ログイン templates/index.html

Slide 33

Slide 33 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 33 ログイン ログイン templates/index.html テンプレートへ渡される値の プレースホルダー

Slide 34

Slide 34 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 34 ログイン完了 ... templates/callback.html

Slide 35

Slide 35 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 35 ... ログイン完了
ユーザー識別⼦︓{{ .Subject }}
メールアドレス︓{{ .Email }}
戻る

Slide 36

Slide 36 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 36 ... ログイン完了
ユーザー識別⼦︓{{ .Subject }}
メールアドレス︓{{ .Email }}
戻る

Slide 37

Slide 37 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 37 エラー {{.}} templates/error.html

Slide 38

Slide 38 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 38 func main() { // 1-1. マルチプレクサにハンドラを登録 mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, fmt.Sprintf("http://localhost:%d/index", config.Port), http.StatusMovedPermanently) }) mux.HandleFunc("/index", index) mux.HandleFunc("/callback", callback) ... practice01/server.go

Slide 39

Slide 39 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 39 func main() { // 1-1. マルチプレクサにハンドラを登録 mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, fmt.Sprintf("http://localhost:%d/index", config.Port), http.StatusMovedPermanently) }) mux.HandleFunc("/index", index) mux.HandleFunc("/callback", callback) ... practice01/server.go アクセスのあったURLに合わせて ルーティング

Slide 40

Slide 40 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 40 ... // 1-2. サーバー設定 server := &http.Server{ Addr: fmt.Sprintf("0.0.0.0:%d", config.Port), Handler: mux, ReadTimeout: time.Second * 10, WriteTimeout: time.Second * 600, MaxHeaderBytes: 1 << 20, // 1MB } err := server.ListenAndServe() if err != nil { log.Fatal(err) } } practice01/server.go

Slide 41

Slide 41 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 41 ... const ( Port = 8080 ) ... // 1-3. Client ID、Client Secretを定義 const ( ClientID = "" ClientSecret = "" ) // 1-4. リダイレクトURIを定義 var RedirectURI = fmt.Sprintf("http://localhost:%d/callback", Port) // 1-5. OpenID ConnectのURLを定義 const ( OIDCURL = "https://auth.login.yahoo.co.jp" ) ... config/config.go

Slide 42

Slide 42 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 42 ... const ( Port = 8080 ) ... // 1-3. Client ID、Client Secretを定義 const ( ClientID = "" ClientSecret = "" ) // 1-4. リダイレクトURIを定義 var RedirectURI = fmt.Sprintf("http://localhost:%d/callback", Port) // 1-5. OpenID ConnectのURLを定義 const ( OIDCURL = "https://auth.login.yahoo.co.jp" ) ... config/config.go ⼤⽂字はじまりの変数︓Public変数 ⼩⽂字はじまりの変数︓Private変数

Slide 43

Slide 43 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 43 ... import ( ... // 1-6. 設定パッケージのインポート "github.com/kura-lab/kuroobi-hands-on-2020/config" ) ... practice01/server.go

Slide 44

Slide 44 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 44 ... // 1-7. テンプレートをレンダリング var ( indexTemplate = template.Must(template.ParseFiles(”../templates/index.html")) callbackTemplate = template.Must(template.ParseFiles("../templates/callback.html")) errorTemplate = template.Must(template.ParseFiles("../templates/error.html")) ) ... practice01/server.go

Slide 45

Slide 45 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 45 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server Resource Server (UserInfo) Authorization Code Flow

Slide 46

Slide 46 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 46 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 0-2.処理開始 Authorization Code Flow Resource Server (UserInfo)

Slide 47

Slide 47 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 47 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 0-2.処理開始 Authorization Code Flow RPからIdPへ認証・認可をUser Agentを利⽤して GETのリダイレクト(もしくはPOST)でリクエスト Resource Server (UserInfo)

Slide 48

Slide 48 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 48 HTTP/1.1 302 Found Location: https://auth.login.yahoo.co.jp/yconnect/v2/authorization? client_id=dj00aiZpPXVlM...& response_type=code& scope=openid+email& redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fcallback& state=abc& nonce=xyz& prompt=consent

Slide 49

Slide 49 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 49 // AuthorizationリクエストのURLを⽣成 func index(w http.ResponseWriter, r *http.Request) { // 1-8. AuthorizationリクエストURL⽣成 u, err := url.Parse(config.OIDCURL) if err != nil { // 1-9. 構造体にエラー⽂⾔を格納してerror.htmlをレンダリング w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "url parse error") return } u.Path = path.Join(u.Path, "yconnect/v2/authorization") q := u.Query() ... practice01/server.go

Slide 50

Slide 50 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 50 // AuthorizationリクエストのURLを⽣成 func index(w http.ResponseWriter, r *http.Request) { // 1-8. AuthorizationリクエストURL⽣成 u, err := url.Parse(config.OIDCURL) if err != nil { // 1-9. 構造体にエラー⽂⾔を格納してerror.htmlをレンダリング w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "url parse error") return } u.Path = path.Join(u.Path, "yconnect/v2/authorization") q := u.Query() ... practice01/server.go テンプレートの プレースホルダーに渡す値

Slide 51

Slide 51 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 51 ... // 1-10. response_typeにAuthorization Code Flowを指定 q.Set("response_type", "code") q.Set("client_id", config.ClientID) q.Set("redirect_uri", config.RedirectURI) // 1-11. UserInfoエンドポイントから取得するscopeを指定 q.Set("scope", "openid email") // 1-12. ログイン画⾯と同意画⾯の強制表⽰ q.Set("prompt", "login consent") q.Set("nonce", "NONCE_STUB") u.RawQuery = q.Encode() // 1-13. 構造体にURLをセットしindex.htmlをレンダリング w.WriteHeader(http.StatusOK) indexTemplate.Execute(w, u.String()) } practice01/server.go

Slide 52

Slide 52 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 52 ... // 1-10. response_typeにAuthorization Code Flowを指定 q.Set("response_type", "code") q.Set("client_id", config.ClientID) q.Set("redirect_uri", config.RedirectURI) // 1-11. UserInfoエンドポイントから取得するscopeを指定 q.Set("scope", "openid email") // 1-12. ログイン画⾯と同意画⾯の強制表⽰ q.Set("prompt", "login consent") q.Set("nonce", "NONCE_STUB") u.RawQuery = q.Encode() // 1-13. 構造体にURLをセットしindex.htmlをレンダリング w.WriteHeader(http.StatusOK) indexTemplate.Execute(w, u.String()) } practice01/server.go response_typeの指定によってフローがわかる response_typeの値 Flow code Authorization Code id_token Implicit id_token token Implicit code id_token Hybrid code token Hybrid code id_token token Hybrid

Slide 53

Slide 53 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 53 ... // 1-10. response_typeにAuthorization Code Flowを指定 q.Set("response_type", "code") q.Set("client_id", config.ClientID) q.Set("redirect_uri", config.RedirectURI) // 1-11. UserInfoエンドポイントから取得するscopeを指定 q.Set("scope", "openid email") // 1-12. ログイン画⾯と同意画⾯の強制表⽰ q.Set("prompt", "login consent") q.Set("nonce", "NONCE_STUB") u.RawQuery = q.Encode() // 1-13. 構造体にURLをセットしindex.htmlをレンダリング w.WriteHeader(http.StatusOK) indexTemplate.Execute(w, u.String()) } practice01/server.go ログイン画⾯(login)、同意画⾯(consent)の表⽰を強制 しt礼しないと不要な場合は省略される

Slide 54

Slide 54 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 54 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 4.同意画⾯ 0-2.処理開始 Authorization Code Flow IdPがログイン・同意をユーザーに要求 Resource Server (UserInfo)

Slide 55

Slide 55 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 2. Tokenリクエスト 55 • Authorizationリクエストを正常に終えると Authorization Code値が返却される • Authorization Code値をIdP(AuthN/AuthZ Server) へリクエストし、Access TokenとRefresh Token、ID Tokenを取得する https://github.com/kura-lab/kuroobi-hands-on-2020/tree/20200204/practice02 演習ソースコード

Slide 56

Slide 56 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 56 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 4.同意画⾯ 0-2.処理開始 6.Authorization Code Authorization Code Flow ユーザーが認可した情報が Authorization Codeとして User Agentを通じて Back-End Serverへ返却される Access Token等を 直接Clientサイドへ返却せず 有効期限の短い⼀時トークンとして Authorization Codeを 返却するためImplicit Flowよりも強固 Resource Server (UserInfo)

Slide 57

Slide 57 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 57 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 4.同意画⾯ 0-2.処理開始 6.Authorization Code 7.Tokenリクエスト(Authorization Code) Authorization Code Flow Authorization Codeに加えてサーバー間で Client IDとClient Secretによるクライアント認証を ⾏うためImplicit Flowよりも強固 Resource Server (UserInfo)

Slide 58

Slide 58 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 58 POST /yconnect/v2/token HTTP/1.1 Host: auth.login.yahoo.co.jp Content-Type: application/x-www-form-urlencoded grant_type=authorization_code&client_id=djsaWss2ka6sn...& client_secret=inlakw1cqa2asCcr...& code=SplxlOBeZQQYbYS6WxSbIA& redirect_uri=https%3A%2F%2Flocalhoost%3A8080%2Fcallback

Slide 59

Slide 59 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 59 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token/ID Token 4.同意画⾯ 0-2.処理開始 6.Authorization Code 7.Tokenリクエスト(Authorization Code) Authorization Code Flow 認可のAccess Tokenと IdPが⾏ったユーザー認証の 情報を含むID Tokenを返却 Resource Server (UserInfo)

Slide 60

Slide 60 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 60 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token/ID Token 4.同意画⾯ 0-2.処理開始 6.Authorization Code 7.Tokenリクエスト(Authorization Code) 9.ログインセッション 発⾏ 10.ログイン完了 Authorization Code Flow Resource Server (UserInfo)

Slide 61

Slide 61 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 61 HTTP/1.1 200 OK Cache-Control: private, no-store, no-cache, must-revalidate Pragma: no-cache Content-Type: application/json { "access_token":"KyTCfK8VtfW...", "token_type":"Bearer", "expires_in":3600, "id_token":"eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3Mi OiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leG FtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP- mB92K27uhbUJU1p1r_wW1gFWFOEjXk", "refresh_token":"gE3tiP5nPp7...” }

Slide 62

Slide 62 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 62 // Access Tokenの取得、ID Tokenの取得と検証 // UserInfoエンドポイントからユーザー属性情報の取得 func callback(w http.ResponseWriter, r *http.Request) { // 2-1. クエリを取得 query := r.URL.Query() ... // 2-2. Tokenリクエスト values := url.Values{} values.Set("grant_type", "authorization_code") values.Add("client_id", config.ClientID) values.Add("client_secret", config.ClientSecret) values.Add("redirect_uri", config.RedirectURI) ... practice02/server.go

Slide 63

Slide 63 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 63 // Access Tokenの取得、ID Tokenの取得と検証 // UserInfoエンドポイントからユーザー属性情報の取得 func callback(w http.ResponseWriter, r *http.Request) { // 2-1. クエリを取得 query := r.URL.Query() ... // 2-2. Tokenリクエスト values := url.Values{} values.Set("grant_type", "authorization_code") values.Add("client_id", config.ClientID) values.Add("client_secret", config.ClientSecret) values.Add("redirect_uri", config.RedirectURI) ... practice02/server.go grant_typeでAuthorization Codeの値を渡すことを指定 refresh_tokenを指定することでAccess Tokenの更新もできる

Slide 64

Slide 64 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 64 ... // 2-3. redirect_uriからAuthorization Codeを抽出 values.Add("code", query["code"][0]) tokenResponse, err := http.Post(config.OIDCURL+"/yconnect/v2/token", "application/x-www-form-urlencoded", strings.NewReader(values.Encode())) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to post request") return } ... practice02/server.go

Slide 65

Slide 65 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 65 ... defer func() { _, err = io.Copy(ioutil.Discard, tokenResponse.Body) if err != nil { log.Panic(err) } err = tokenResponse.Body.Close() if err != nil { log.Panic(err) } }() ... practice02/server.go

Slide 66

Slide 66 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 66 ... defer func() { _, err = io.Copy(ioutil.Discard, tokenResponse.Body) if err != nil { log.Panic(err) } err = tokenResponse.Body.Close() if err != nil { log.Panic(err) } }() ... practice02/server.go Discardで書き込んだバイトを捨てる

Slide 67

Slide 67 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 67 ... // 2-4. TokenエンドポイントのJSONレスポンスの結果を格納する構造体 type TokenResponse struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` RefreshToken string `json:"refresh_token"` ExpiresIn int `json:"expires_in"` IDToken string `json:"id_token"` } ... practice02/server.go

Slide 68

Slide 68 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 68 ... // 2-5. Tokenレスポンスを構造体に格納 var tokenData TokenResponse err = json.NewDecoder(tokenResponse.Body).Decode(&tokenData) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to read token's json body") return } log.Println("requested token endpoint") ... practice02/server.go

Slide 69

Slide 69 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 3. UserInfoリクエスト 69 • Tokenリクエストで取得したAccess TokenをUserInfo エンドポイントへリクエストする • IdPに登録されているユーザーの属性情報を取得する https://github.com/kura-lab/kuroobi-hands-on-2020/tree/20200204/practice03 演習ソースコード

Slide 70

Slide 70 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. UserInfoエンドポイント 70 • ⽒名や住所、メールアドレスなどの属性情報を標準仕様 化して取得しやすいように属性情報(Claim)を定義 • 関連した属性情報ごとにアクセス制限としてScopeを定 義 • RPのサービスに必要な属性情報だけをIdPに要求するこ とが可能

Slide 71

Slide 71 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 定義されている属性情報 71 Claim Scope 説明 sub - ユーザー識別⼦ name profile ⽒名 give_name profile 名 family_name profile 姓 middle_name profile ミドルネーム nickname profile ニックネーム preferred_ username profile 簡略名 Claim Scope 説明 profile profile プロフィール情報の URL picture profile プロフィール画像の URL website profile サイトURL gender profile 性別 birthdate profile ⽣年⽉⽇ email email メールアドレス email_verified email メールアドレスの 検証済みの有無

Slide 72

Slide 72 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 定義されている属性情報 72 Claim Scope 説明 zoneinfo profile タイムゾーン locale profile 国コード update profile 属性情報更新⽇時 phone_number phone 電話番号 phone_number _verified phone 電話番号の検証済み の有無 Claim Scope 説明 address/country address 国コード address/postal_code address 郵便番号 address/region address 都道府県 address/locality address 市区町村 address/formatted address 住所

Slide 73

Slide 73 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. ユーザー属性情報取得の留意点 73 • 全Scopeを指定すればすべての属性情報を取得すること ができる • 関連した属性情報ごとにScopeがわけられているのは、 サービスに必要なものに絞って取得できるにしている • 不要な属性情報の取得はユーザーの不安につながるため 注意が必要

Slide 74

Slide 74 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 74 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token/ID Token 11.Access Token 4.同意画⾯ 0-2.処理開始 6.Authorization Code 7.Tokenリクエスト(Authorization Code) 9.ログインセッション 発⾏ 10.ログイン完了 Authorization Code Flow 属性情報の取得が必要な場合は UserInfoエンドポイントへ Access Tokenを送信 Resource Server (UserInfo)

Slide 75

Slide 75 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 75 GET /yconnect/v2/attribute HTTP/1.1 Host: auth.login.yahoo.co.jp Authorization: Bearer SlAV32hkKG...

Slide 76

Slide 76 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 76 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token/ID Token 11.Access Token 12.Claims 4.同意画⾯ 0-2.処理開始 6.Authorization Code 7.Tokenリクエスト(Authorization Code) 13.属性情報取得完了 9.ログインセッション 発⾏ 10.ログイン完了 Authorization Code Flow 各属性情報がJSONで返却される Resource Server (UserInfo)

Slide 77

Slide 77 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 77 HTTP/1.1 200 OK Content-Type: application/json { “sub”: “YIZ7F3ZBD...”, “name”: “倉林 雅”, “given_name”: “雅”, “family_name”: “倉林”, “nickname”: “kura”, “picture”: “https://giwiz-display-name.c.yimg.jp/d/iwiz-display- name/...”, “email”: “[email protected]” }

Slide 78

Slide 78 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 78 ... // 3-1. UserInfoリクエスト userInfoRequest, err := http.NewRequest( "POST", "https://userinfo.yahooapis.jp/yconnect/v2/attribute", nil, ) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to create user attribute request") return } ... practice03/server.go

Slide 79

Slide 79 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 79 ... userInfoRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded") userInfoRequest.Header.Set("Authorization", "Bearer "+tokenData.AccessToken) userInfoResponse, err := http.DefaultClient.Do(userInfoRequest) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to user attribute request") return } ... practice03/server.go

Slide 80

Slide 80 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 80 ... userInfoRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded") userInfoRequest.Header.Set("Authorization", "Bearer "+tokenData.AccessToken) userInfoResponse, err := http.DefaultClient.Do(userInfoRequest) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to user attribute request") return } ... practice03/server.go OAuth 2.0 Bearer Token 認可されたAccess Tokenを指定

Slide 81

Slide 81 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 81 ... defer func() { _, err = io.Copy(ioutil.Discard, userInfoResponse.Body) if err != nil { log.Panic(err) } err = userInfoResponse.Body.Close() if err != nil { log.Panic(err) } }() ... practice03/server.go

Slide 82

Slide 82 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 82 ... // 3-2. UserInfoエンドポイントのJSONレスポンスの結果を格納する構造体 type UserInfoResponse struct { Subject string `json:"sub"` Email string `json:"email"` } ... practice03/server.go

Slide 83

Slide 83 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 83 ... // 3-3. UserInfoレスポンスを構造体に格納 var userInfoData UserInfoResponse err = json.NewDecoder(userInfoResponse.Body).Decode(&userInfoData) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to parse user info json") return } log.Println("requested userinfo endpoint") ... // 3-4. 構造体にユーザー属性情報をセットしcallback.htmlをレンダリング w.WriteHeader(http.StatusOK) callbackTemplate.Execute(w, userInfoData) log.Println("[[ login completed ]]") ... practice03/server.go

Slide 84

Slide 84 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 実装のポイント、セキュリティ対策の解説

Slide 85

Slide 85 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. CSRF (Cross-Site Request Forgery) 85 ⼀般的な場合 • 別のサイトに⽤意したコンテンツ上の罠のリンクを踏ま せることなどをきっかけとして、インターネットショッ ピングの最終決済や退会などのWebアプリケーション の重要な処理を呼び出すようユーザーを誘導する攻撃 OAuth 2.0/OpenID Connectの場合 • 悪意あるユーザーの認可コードを被害者に乗っ取らせ情 報を窃取する

Slide 86

Slide 86 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 86 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token/ID Token 9.Access Token 10.Claims 4.同意画⾯ 0-2.処理開始 6.Authorization Code 7.Tokenリクエスト(Authorization Code) 11.属性情報取得 ログイン完了 Authorization Code Flow CSRFの 攻撃対象になる部分は どこでしょう︖ Resource Server (UserInfo)

Slide 87

Slide 87 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 87 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token/ID Token 9.Access Token 10.Claims 4.同意画⾯ 0-2.処理開始 6.Authorization Code 7.Tokenリクエスト(Authorization Code) 11.属性情報取得 ログイン完了 Authorization Code Flow 他ユーザーのAuthorization Codeに 置き換えができてしまう Resource Server (UserInfo) 対策なしのままではAuthorizationリクエストから Authorization Codeを受け取るまで セッションが同⼀であることを保証できない

Slide 88

Slide 88 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 88 Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token/ID Token 9.Access Token 10.Claims 4.同意画⾯ 0-2.処理開始 6.悪意あるユーザーのAuthorization Code 7.Tokenリクエスト(Authorization Code) 11.属性情報取得 ログイン完了 Authorization Code Flow 悪意あるユーザーが⾃⾝のIDで ログイン、同意を⾏いBE Serverへ送信せず Authorization Codeを取得する Resource Server (UserInfo)

Slide 89

Slide 89 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 89 Client (User Agent) Back-End Server AuthN/AuthZ Server 11.Access Token/ID Token 12.Access Token 13.Claims 10.Tokenリクエスト(Authorization Code) 14.属性情報取得 ログイン完了 End-User 7.redirect_uri 8.URLクリック 9.悪意あるユーザーの Authorization Code Authorization Code Flow 悪意あるユーザーのIDで取得した Access Tokenを含んだredirect_uriを フィッシングサイトなどでアクセスさせる 乗っ取らせてサービスを利⽤させ ユーザーの情報を窃取する Resource Server (UserInfo)

Slide 90

Slide 90 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. state 90 • OAuth 2.0にはCSRF対策として「state」パラメーター が定義されている • RPがAuthorizationリクエストで指定したstate値と Authorizationレスポンスで認可コードと同時に返却さ れるstate値の⼀致を検証することで認可コードの置き 換えに夜乗っ取らせを防⽌する

Slide 91

Slide 91 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 91 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト(state=xyz) 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token/ID Token 9.Access Token 10.Claims 4.同意画⾯ 0-2.処理開始 6.Authorization Code + state=xyz 7.Tokenリクエスト(Authorization Code) 11.属性情報取得 ログイン完了 Authorization Code Flow RPのセッション (HTTPOnlyのCookieなど) に紐付けたstate値を送信 Authorization Codeと共にstate値が返却される セッションに紐づけたstate値と⼀致するか 検証することでCSRFを防⽌ Resource Server (UserInfo)

Slide 92

Slide 92 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 92 Client (User Agent) Back-End Server AuthN/AuthZ Server 11.Access Token/ID Token 12.Access Token 13.Claims 10.Tokenリクエスト(Authorization Code) 14.属性情報取得 ログイン完了 End-User 7.redirect_uri 8.URLクリック 9.悪意あるユーザーの Authorization Code + state=abc Authorization Code Flow 被害者のセッションに紐づくstate値 (サービスのAuthorizationリクエストに アクセスしていなければセッションもない) と⼀致しないため置き換えを検知できる Resource Server (UserInfo)

Slide 93

Slide 93 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 4. CSRF対策(state値の検証) 93 • Authorizationレスポンスで返却されるAuthorization Code値の置き換えによるCSRF攻撃を対策する • RPで⽣成したstate値をセッションCookieに紐付ける • state値をAuthorizationリクエストで送信する • 返却されたstate値がとセッションCookieに紐付けた state値と同⼀であるかを検証する https://github.com/kura-lab/kuroobi-hands-on-2020/tree/20200204/practice04 演習ソースコード

Slide 94

Slide 94 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 94 ... // 4-1. ランダム⽂字列を⽣成 func init() { rand.Seed(time.Now().UnixNano()) } var randLetters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") func generateRandomString() string { result := make([]rune, 32) for i := range result { result[i] = randLetters[rand.Intn(len(randLetters))] } return string(result) } ... practice04/server.go

Slide 95

Slide 95 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 95 ... // 4-2. セッションCookieに紐付けるstate値を⽣成し保存 state := generateRandomString() stateCookie := &http.Cookie{ Name: "state", Value: state, HttpOnly: true, } http.SetCookie(w, stateCookie) ... // 4-3. セッションCookieに紐づけたstate値を指定 q.Set("state", state) ... practice04/server.go

Slide 96

Slide 96 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 96 ... // 4-2. セッションCookieに紐付けるstate値を⽣成し保存 state := generateRandomString() stateCookie := &http.Cookie{ Name: "state", Value: state, HttpOnly: true, } http.SetCookie(w, stateCookie) ... // 4-3. セッションCookieに紐づけたstate値を指定 q.Set("state", state) ... practice04/server.go 今回はstateというフィールド名で Cookieを発⾏

Slide 97

Slide 97 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 97 ... // 4-4. redirect_uriからstate値の抽出 stateQuery, ok := query["state"] if !ok { w.WriteHeader(http.StatusBadRequest) errorTemplate.Execute(w, "state query not found") return } state := stateQuery[0] storedState, err := r.Cookie("state") if err != nil { w.WriteHeader(http.StatusBadRequest) errorTemplate.Execute(w, "state cookie error") return } ... practice04/server.go

Slide 98

Slide 98 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 98 ... // 4-5. セッションCookieに紐づけていたstate値の破棄 stateCookie := &http.Cookie{ Name: "state", MaxAge: -1, } http.SetCookie(w, stateCookie) // 4-6. state値の検証 if state != storedState.Value { w.WriteHeader(http.StatusBadRequest) errorTemplate.Execute(w, "state does not match stored one") return } log.Println("success to verify state") ... practice04/server.go

Slide 99

Slide 99 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. ID Tokenとは 99 • ユーザー認証情報を含む改ざん検知⽤の署名付きToken • JSON Web Token(JWT)フォーマット • IdPが認証したユーザーの認証情報を含めRPが検証し RP側のセッション管理に⽤いる ID

Slide 100

Slide 100 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. JSON Web Token(JWT) 100 • JSONをBase64urlエンコード(URL SafeなBase64エン コード)したシグネチャ(ハッシュ値もしくはデジタル署 名)付きトークン • ヘッダー・ペイロード・シグネチャの3つから構成される • シグネチャはハッシュ(HMAC)と 公開鍵暗号(RSA・ECDSA)をサポート • JWTと表記して「jot(ジョット)」と発⾳する Jot down

Slide 101

Slide 101 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 101 eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIU zI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleH AiOjEzMDA4MTkzODAsDQogImh0dHA 6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp 0cnVlfQ.dBjftJeZ4CVP- mB92K27uhbUJU1p1r_wW1gFWFOEj Xk ID Token

Slide 102

Slide 102 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 102 eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIU zI1NiJ9 . eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzM DA4MTkzODAsDQogImh0dHA6Ly9leG FtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ . dBjftJeZ4CVP- mB92K27uhbUJU1p1r_wW1gFWFOEj Xk Header Payload Signature ピリオド区切りの3つの部位から構成される

Slide 103

Slide 103 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 103 eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIU zI1NiJ9 . eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzM DA4MTkzODAsDQogImh0dHA6Ly9leG FtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ . dBjftJeZ4CVP- mB92K27uhbUJU1p1r_wW1gFWFOEj Xk Header Payload Signature Base64エンコードは「/」や「=」が 含まれURL Safeでないため Base64urlエンコードが利⽤されている

Slide 104

Slide 104 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 104 eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIU zI1NiJ9 { "type": "JWT", "alg": "RS256" } Header Signature Base64urlデコード 置換前 置換後 “-” “+” “/” “_” (データ⻑ % 4)の 数だけ”=”をパディング Base64urlデコード Base64デコード

Slide 105

Slide 105 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 105 { "type": "JWT", "alg": "RS256" } type: JSON Web Token

Slide 106

Slide 106 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 106 { "type": "JWT", "alg": "RS256" } algorithm: Signatureのアルゴリズム RS256=RSA SHA-256 alg アルゴリズム 実装要求 HS256 HMAC SHA-256 RS256 RSA SHA-256 推奨 ES256 ECDSA SHA-256 推奨 JWT サポートアルゴリズム

Slide 107

Slide 107 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 107 eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIU zI1NiJ9 . eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzM DA4MTkzODAsDQogImh0dHA6Ly9leG FtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ . dBjftJeZ4CVP- mB92K27uhbUJU1p1r_wW1gFWFOEj Xk Header Payload Signature Header + ”.” + Payloadを ⼊⼒データとする

Slide 108

Slide 108 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 108 eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIU zI1NiJ9 . eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzM DA4MTkzODAsDQogImh0dHA6Ly9leG FtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ . dBjftJeZ4CVP- mB92K27uhbUJU1p1r_wW1gFWFOEj Xk Header Payload Signature 検証結果が正しければ PayloadのClaim(属性情報)を参照する typのアルゴリズムで⼊⼒データとSignatureと IdPが公開している公開鍵をつかって改ざんを検証

Slide 109

Slide 109 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 109 eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzM DA4MTkzODAsDQogImh0dHA6Ly9leG FtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ { "iss":"https://idp.example.com", "sub":"123456789", "aud":"abcdefg", "nonce":"xyz", "iat":1291836800, "exp":1300819380, "nonce":"xyz..." } Payload Base64urlデコード

Slide 110

Slide 110 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 110 { "iss":"https://idp.example.com", "sub":"123456789", "aud":"abcdefg", "nonce":"xyz", "iat":1291836800, "exp":1300819380, "nonce":"xyz..." } issuer ID Tokenの発⾏社(IdP)

Slide 111

Slide 111 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 111 { "iss":"https://idp.example.com", "sub":"123456789", "aud":"abcdefg", "nonce":"xyz", "iat":1291836800, "exp":1300819380, "nonce":"xyz..." } subject ユーザー識別⼦(認証の対象者)

Slide 112

Slide 112 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 112 { "iss":"https://idp.example.com", "sub":"123456789", "aud":"abcdefg", "nonce":"xyz", "iat":1291836800, "exp":1300819380, "nonce":"xyz..." } audience Client ID(ID Tokenの発⾏先)

Slide 113

Slide 113 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 113 { "iss":"https://idp.example.com", "sub":"123456789", "aud":"abcdefg", "nonce":"xyz", "iat":1291836800, "exp":1300819380, "nonce":"xyz..." } 発⾏社(iss)が どのRP(aud)に対して どのユーザー(sub)を認証した のかを⽰している

Slide 114

Slide 114 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. リプレイ攻撃 114 ⼀般的な場合 • 有効なデータ転送が故意または不正に繰り返し/遅延される ことによる攻撃 • IPパケットの置換によるDNS偽装の⼀部のように、発信者 や攻撃者がデータを傍受し再送信することによって実⾏さ れる OpenID Connectの場合 • ID Tokenを傍受し不正ログインを試みる

Slide 115

Slide 115 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 115 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server Resource Server (UserInfo) 0.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 6.Access Token/ID Token 8.Access Token 9.Claims 4.同意画⾯ 10.属性情報取得完了 7.ログイン完了 Implicit Flow リプレイ攻撃の 対象になる部分は どこでしょう︖

Slide 116

Slide 116 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 116 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server Resource Server (UserInfo) 0.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 6.Access Token/ID Token 8.Access Token 9.Claims 4.同意画⾯ 10.属性情報取得完了 7.ログイン完了 Implicit Flow 通信経路から傍受されたID Tokenを 受け⼊れてしまう

Slide 117

Slide 117 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 117 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server Resource Server (UserInfo) 0.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 6.Access Token/ID Token 4.同意画⾯ Proxyなどを⽤いて ID Tokenを傍受 8.ログイン完了 7.ID Token Implicit Flow

Slide 118

Slide 118 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. nonce (number used once) 118 • OpenID ConnectにはID Tokenのリプレイ攻撃対策と して「nonce」パラメーターが定義されている • RPがAuthorizationリクエストで指定したnonce値と 返却されるID Tokenの内部に含まれるnonce値の ⼀致を検証することで繰り返し送信されるID Tokenの リプレイ攻撃を防⽌する

Slide 119

Slide 119 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 119 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0.処理開始 1.Authorizationリクエスト(nonce=xyz) 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token 9.Claims 4.同意画⾯ 10.属性情報取得完了 7.ログイン完了 6.Access Token/ID Token(nonce=xyz) Implicit Flow RPのセッション (HTTPOnlyのCookieなど) に紐付けた値を送信 nonce値を含んだID Tokenが返却される セッションに紐づけたnonce値と⼀致するか 検証することでリプレイ攻撃を防⽌ Resource Server (UserInfo)

Slide 120

Slide 120 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 120 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0.処理開始 1.Authorizationリクエスト 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 6.Access Token/ID Token(nonce=123) 4.同意画⾯ 8.ログイン完了 7.ID Token(nonce=123) Implicit Flow 被害者のセッションに紐づくnonce値 (サービスのAuthorizationリクエストに アクセスしていなければセッションもない) と⼀致しないため置き換えを検知できる Resource Server (UserInfo)

Slide 121

Slide 121 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. nonceの検証 121 • nonceの検証はID Tokenの再送が起こりうるケースのみ必須 • クライアントサイドでID Tokenを受け取るHybridフローの場合は 必須 • Authorization CodeフローのRPとIdPのサーバー間で安全に ID Tokenが送受信される場合にはnonceの検証は任意でよい

Slide 122

Slide 122 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 5. リプレイ攻撃対策(nonce値の検証) 122 • Tokenレスポンスで返却されるID Tokenの再送による リプレイ攻撃を対策する • RPで⽣成したnonce値をセッションCookieに紐付ける • nonce値をAuthorizationリクエストで送信する • ID Tokenに含まれるnonce値がセッションCookieに紐 付けたnonce値と同⼀であるかを検証する https://github.com/kura-lab/kuroobi-hands-on-2020/tree/20200204/practice05 演習ソースコード

Slide 123

Slide 123 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 123 End-User Client (User Agent) Back-End Server AuthN/AuthZ Server 0-1.処理開始 1.Authorizationリクエスト(nonce=xyz) 2.ログイン画⾯ 3.クレデンシャル 情報⼊⼒ 5.同意 8.Access Token/ID Token(nonce=xyz) 4.同意画⾯ 0-2.処理開始 6.Authorization Code 7.Tokenリクエスト(Authorization Code) 9.ログインセッション 発⾏ 10.ログイン完了 Authorization Code Flow ID Tokenに含まれる nonce値を検証 nonce値を⽣成し セッションCookieに紐づける Resource Server (UserInfo)

Slide 124

Slide 124 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 124 ... // 5-1. セッションCookieに紐付けるnonce値を⽣成し保存 nonce := generateRandomString() nonceCookie := &http.Cookie{ Name: "nonce", Value: nonce, HttpOnly: true, } http.SetCookie(w, nonceCookie) log.Println("stored state and nonce in session") ... // 5-2. セッションCookieに紐づけたnonce値を指定 q.Set("nonce", nonce) ... practice05/server.go

Slide 125

Slide 125 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 125 ... // 5-3. ID Tokenのデータ部の分解 idTokenParts := strings.SplitN(tokenData.IDToken, ".", 3) log.Println("header: ", idTokenParts[0]) log.Println("payload: ", idTokenParts[1]) log.Println("signature: ", idTokenParts[2]) // 5-4. ID Tokenのヘッダーの検証 header, err := base64.RawURLEncoding.DecodeString(idTokenParts[0]) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to decode ID Token") return } ... practice05/server.go

Slide 126

Slide 126 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 126 ... // 5-3. ID Tokenのデータ部の分解 idTokenParts := strings.SplitN(tokenData.IDToken, ".", 3) log.Println("header: ", idTokenParts[0]) log.Println("payload: ", idTokenParts[1]) log.Println("signature: ", idTokenParts[2]) // 5-4. ID Tokenのヘッダーの検証 header, err := base64.RawURLEncoding.DecodeString(idTokenParts[0]) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to decode ID Token") return } ... practice05/server.go Base64デコードではなく Base64URLデコード

Slide 127

Slide 127 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 127 ... // 5-5. ID Tokenのヘッダーを格納する構造体 type IDTokenHeader struct { Type string `json:"typ"` Algorithm string `json:"alg"` KeyID string `json:"kid"` } ... // 5-6. ID Tokenのヘッダーを構造体に格納 var idTokenHeader IDTokenHeader err = json.Unmarshal(header, &idTokenHeader) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to decode ID Token") return } ... practice05/server.go

Slide 128

Slide 128 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 128 ... // 5-7. typ値の検証 if idTokenHeader.Type != "JWT" { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "invalid id token type") return } // 5-8. alg値の検証 if idTokenHeader.Algorithm != "RS256" { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "invalid id token algorithm") return } ... practice05/server.go

Slide 129

Slide 129 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 129 ... // 5-9. JWKsリクエスト jwksResponse, err := http.Get(config.OIDCURL + "/yconnect/v2/jwks") if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to get jwk") return } ... practice05/server.go

Slide 130

Slide 130 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 130 ... defer func() { _, err = io.Copy(ioutil.Discard, jwksResponse.Body) if err != nil { log.Panic(err) } err = jwksResponse.Body.Close() if err != nil { log.Panic(err) } }() ... practice05/server.go

Slide 131

Slide 131 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 131 { "keys": [ { "kid": "0cc175b9c0f1b6a831c399e269772661", "kty": "RSA", "alg": "RS256", "use": "sig", "n": "0bXcnrheJ2snfq1wv6Qz8...", "e": "AQAB" }, ... ] }

Slide 132

Slide 132 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 132 ... // 5-11. JWKsレスポンスを構造体に格納 var jwksData JWKsResponse err = json.NewDecoder(jwksResponse.Body).Decode(&jwksData) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to read jwk's json body") return } log.Println("requested jwks endpoint") ... practice05/server.go

Slide 133

Slide 133 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 133 ... // 5-12. modulus値とexponent値の抽出 var modulus, exponent string for _, keySet := range jwksData.KeySets { if keySet.KeyID == idTokenHeader.KeyID { log.Println("kid: " + keySet.KeyID) if keySet.KeyType != "RSA" || keySet.Algorithm != idTokenHeader.Algorithm || keySet.Use != "sig" { w.WriteHeader(http.StatusUnauthorized) errorTemplate.Execute(w, "invalid kid, alg or use") return } modulus = keySet.Modulus exponent = keySet.Exponent break } } ... practice05/server.go

Slide 134

Slide 134 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 134 ... if modulus == "" || exponent == "" { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to extract modulus or exponent") return } log.Println("extracted modulus and exponent") ... practice05/server.go

Slide 135

Slide 135 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 135 ... // 5-13. n(modulus)とe(exponent)から公開鍵を⽣成 decodedModulus, err := base64.RawURLEncoding.DecodeString(modulus) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to decode modulus") return } decodedExponent, err := base64.StdEncoding.DecodeString(exponent) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to decode exponent") return } ... practice05/server.go

Slide 136

Slide 136 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 136 ... var exponentBytes []byte if len(decodedExponent) < 8 { exponentBytes = make([]byte, 8-len(decodedExponent), 8) exponentBytes = append(exponentBytes, decodedExponent...) } else { exponentBytes = decodedExponent } ... practice05/server.go

Slide 137

Slide 137 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 137 ... reader := bytes.NewReader(exponentBytes) var e uint64 err = binary.Read(reader, binary.BigEndian, &e) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to read binary exponent") return } generatedPublicKey := rsa.PublicKey{N: big.NewInt(0).SetBytes(decodedModulus), E: int(e)} log.Println("generated public key: ", generatedPubli ... practice05/server.go

Slide 138

Slide 138 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 138 ... // 5-14. ID Tokenの署名を検証 decodedSignature, err := base64.RawURLEncoding.DecodeString(idTokenParts[2]) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to decode signature") return } hash := crypto.Hash.New(crypto.SHA256) _, err = hash.Write([]byte(idTokenParts[0] + "." + idTokenParts[1])) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to create id token hash") return } ... practice05/server.go

Slide 139

Slide 139 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 139 ... hashed := hash.Sum(nil) err = rsa.VerifyPKCS1v15(&generatedPublicKey, crypto.SHA256, hashed, decodedSignature) if err != nil { log.Println("failed to verify signature") w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to verify signature") return } log.Println("success to verify signature") ... practice05/server.go

Slide 140

Slide 140 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 140 ... // 5-15. ID Tokenのペイロードをデコード decodedPayload, err := base64.RawURLEncoding.DecodeString(idTokenParts[1]) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to decode payload") return } ... practice05/server.go

Slide 141

Slide 141 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 141 ... // 5-16. ID Tokenのペイロードを格納する構造体 type IDTokenPayload struct { Issuer string `json:"iss"` Subject string `json:"sub"` Audience []string `json:"aud"` Expiration int `json:"exp"` IssueAt int `json:"iat"` AuthTime int `json:"auth_time"` Nonce string `json:"nonce"` AuthenticationMethodReference []string `json:"amr"` AccessTokenHash string `json:"at_hash"` } ... practice05/server.go

Slide 142

Slide 142 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 142 ... // 5-17. ID Tokenのペイロードを構造体へ格納 idTokenPayload := new(IDTokenPayload) err = json.Unmarshal(decodedPayload, idTokenPayload) if err != nil { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "failed to parse payload json") return } ... practice05/server.go

Slide 143

Slide 143 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 143 ... // 5-18. issuer値の検証 log.Println("id token issuer: ", idTokenPayload.Issuer) if idTokenPayload.Issuer != oidcURL+"/yconnect/v2" { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "mismatched issuer") return } log.Println("success to verify issuer") ... practice05/server.go

Slide 144

Slide 144 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 144 ... // 5-19. audience値の検証 log.Println("id token audience: ", idTokenPayload.Audience) var isValidAudience bool for _, audience := range idTokenPayload.Audience { if audience == ClientID { log.Println("mached audience: ", audience) isValidAudience = true break } } if !isValidAudience { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "mismatched audience") return } ... practice05/server.go

Slide 145

Slide 145 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 145 ... // 5-20. セッションCookieからnonce値の抽出 storedNonce, err := r.Cookie("nonce") if err != nil { w.WriteHeader(http.StatusBadRequest) errorTemplate.Execute(w, "nonce cookie error") return } ... practice05/server.go

Slide 146

Slide 146 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 146 ... // 5-21. セッションCookieに紐づけていたnonce値の破棄 nonceCookie := &http.Cookie{ Name: "nonce", MaxAge: -1, } http.SetCookie(w, nonceCookie) log.Println("id token nonce: ", idTokenPayload.Nonce) log.Println("stored nonce: ", storedNonce.Value) if idTokenPayload.Nonce != storedNonce.Value { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "nonce does not match stored one") return } log.Println("success to verify nonce") ... practice05/server.go

Slide 147

Slide 147 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 147 ... // 5-22. iat値の検証 log.Println("id token iat: ", idTokenPayload.IssueAt) if int(time.Now().Unix())-idTokenPayload.IssueAt >= 600 { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "too far away from current time") return } log.Println("success to verify issue at") ... practice05/server.go

Slide 148

Slide 148 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 148 ... // 5-23. at_hash値の検証 receivedAccessTokenHash := sha256.Sum256([]byte(tokenData.AccessToken)) halfOfAccessTokenHash := receivedAccessTokenHash[:len(receivedAccessTokenHash)/2] encodedhalfOfAccessTokenHash := base64.RawURLEncoding.EncodeToString(halfOfAccessTokenHash) log.Println("id token at_hash: ", idTokenPayload.AccessTokenHash) log.Println("generated at_hash: ", encodedhalfOfAccessTokenHash) if idTokenPayload.AccessTokenHash != encodedhalfOfAccessTokenHash { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "mismatched at_hash") return } log.Println("success to verify at_hash") ... practice05/server.go

Slide 149

Slide 149 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 149 ... // 5-23. at_hash値の検証 receivedAccessTokenHash := sha256.Sum256([]byte(tokenData.AccessToken)) halfOfAccessTokenHash := receivedAccessTokenHash[:len(receivedAccessTokenHash)/2] encodedhalfOfAccessTokenHash := base64.RawURLEncoding.EncodeToString(halfOfAccessTokenHash) log.Println("id token at_hash: ", idTokenPayload.AccessTokenHash) log.Println("generated at_hash: ", encodedhalfOfAccessTokenHash) if idTokenPayload.AccessTokenHash != encodedhalfOfAccessTokenHash { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "mismatched at_hash") return } log.Println("success to verify at_hash") ... practice05/server.go Access Tokenのハッシュ値の オクテットの前半をBase64URLエンコードした値

Slide 150

Slide 150 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 150 ... // 5-24. 以下の値の検証および利⽤は任意 // - idTokenPayload.Expiration // - idTokenPayload.AuthTime // - idTokenPayload.AuthenticationMethodReference ... practice05/server.go

Slide 151

Slide 151 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 151 ... // 5-25. sub値の検証 log.Println("id token sub: ", idTokenPayload.Subject) log.Println("userinfo sub: ", userInfoData.Subject) if idTokenPayload.Subject != userInfoData.Subject { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "mismatched user id") return } log.Println("success to verify user id") ... practice05/server.go

Slide 152

Slide 152 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. 152 ... // 5-25. sub値の検証 log.Println("id token sub: ", idTokenPayload.Subject) log.Println("userinfo sub: ", userInfoData.Subject) if idTokenPayload.Subject != userInfoData.Subject { w.WriteHeader(http.StatusInternalServerError) errorTemplate.Execute(w, "mismatched user id") return } log.Println("success to verify user id") ... practice05/server.go ID Tokenで認証したユーザーと UserInfoで取得したユーザーが⼀致しているかを検証

Slide 153

Slide 153 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. まとめ

Slide 154

Slide 154 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. まとめ 154 1. OpenID Connectの概要説明 • OpenID ConnectはOpenIDとは異なりOAuth 2.0をベースとした認証・認 可のプロトコルである • 多様なユースケースに適応できるよう3つのフローが定義されている 2. Go⾔語によるYahoo! ID連携の実装 • Authorizationリクエスト、Tokenリクエスト、UserInfoリクエストをGo ⾔語で実装し⼀連のAuthorization Code Flowを学んだ 3. 実装のポイント、セキュリティ対策の解説 • OpenID ConnectによるCSRF対策、リプレイ攻撃対策を学んだ • RPのユーザー認証に⽤いるID Tokenの検証を実装した

Slide 155

Slide 155 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. ご清聴ありがとうございました

Slide 156

Slide 156 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. Appendix

Slide 157

Slide 157 text

Copyright (C) 2020 Yahoo Japan Corporation. All Rights Reserved. OpenID Connectの仕様について 158 • OpenID Connectの概要や詳細な仕様について学習をする際には、 以下のWebサイトや仕様書、解説のスライドをご参照ください。 • Welcome to OpenID Connect -openid.net- • https://openid.net/connect/ • OpenID Connect Core 1.0 incorporating errata set 1 • https://openid.net/specs/openid-connect-core-1_0.html • OpenID Connect Core 1.0 incorporating errata set 1(⽇本語訳) • https://openid-foundation-japan.github.io/openid-connect-core-1_0.ja.html • OpenID Connect ⼊⾨ 〜コンシューマーにおけるID連携のトレンド〜 • https://www.slideshare.net/kura_lab/openid-connect-id