はじめに
RFC 6749 で定義されている認可フローは 4 つのあるので、そのうちの 1 つである Authorization Code Flow を Auth0 を使って触れた。
Authorization Code Flow
RFC 6749 の 4.1. Authorization Code Grant
に記述されているフロー。
認可サーバーの API エンドポイントへリクエストし、レスポンスとして有効期間の短い認可コードを受けとり、その認可コードを使って認可サーバーのエンドポイントへアクセスし、そのレスポンスとしてアクセストークンを取得する、というもの。
環境設定
Auth0 環境設定
Auth0 に、Auth0 を利用するアプリケーションを登録する。 ここではアプリケーションタイプを「SPA」にしているけど動かすだけなら多分何でも良い。
ただし、 Allowed Callback URLs
を指定する必要がある。 認可フロー時のパラメータとして指定する audience
の値がここで許可されたものと一致する必要がある。末尾の /
の有無が違っただけで Access Denied となるので、ここで /
を付与している場合は認可フロー時の audience
パラメータでも指定する。
https を受けられるものなら何でも良いはずで、今回は https://localhost:3000/
としておく。
※後述で、ローカルでアプリケーションを起動して https://localhost:3000/
を受けられるようにしておく。
ローカルの http サーバー環境設定
自己証明書作成を作成する。
% openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -subj "/C=JP" -nodes -keyout server.key -out server.crt
適当に下記のような main.go
を作成する。
package main import ( "fmt" "log" "net/http" ) type String string func (s String) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprint(w, s) } func main() { http.Handle("/", String("Hello World.")) router := http.NewServeMux() router.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) w.Write([]byte(`{"status":"200 OK"}`)) })) srv := &http.Server{ Addr: "localhost:3000", Handler: router, } if err := srv.ListenAndServeTLS("server.crt", "server.key"); err != nil { log.Fatalf("There was an error with the http server: %v", err) } }
http Server を起動させる。
% go run main.go
Authorization Code Flow の処理
Authorization Request
ブラウザで、Auth0 の /authorize
エンドポイントへリクエストする。URL 全体としては下記のようなものになる。
リクエストパラメータの audience
はコールバックURLに指定したものと同じにする必要がある。client_id
は上述で作成したアプリケーションの値を用いる。
https://{Auth0テナントドメイン}.auth0.com/authorize?audience=https://localhost:3000/&scope=openid profile email&response_type=code&client_id=********&redirect_uri=https://localhost:3000/
初回は下記のような画面が出てくるので、サインアップする。サインアップすると Auth0 側にユーザーが作成される。
Authorization Response
ブラウザの URL で下記のようなものが返される。このコードをメモする。この値は多分 10 分程度が有効期限と思われる。
https://localhost:3000/?code=Df********aP
Access Token Request
取得したコードの値を用いて、Auth0 の /oauth/token
エンドポイントへリクエストする。
code
パラメータは、上記で取得したものを、client_id
, client_secret
パラメータは上述で作成したアプリケーションの値を用いる。
% curl --request POST \ --url 'https://{Auth0テナントドメイン}.auth0.com/oauth/token' \ --header 'content-type: application/x-www-form-urlencoded' \ --data 'grant_type=authorization_code&client_id=********&client_secret=********&code=Df********aP&redirect_uri=https://localhost:3000/'
Access Token Response
レスポンスとして下記のようなものが返されれば成功となる。
{"access_token":"********","scope":"openid profile email","expires_in":86400,"token_type":"Bearer"}%
まとめ
Auth0 を使って Authorization Code Flow の流れを実践してみた。 文字ベースで見ていた仕様の実際の処理の流れのイメージが理解できたのでよかった。