dshimizu/blog

アルファ版

Auth0 を使って Authorization Code Flow 認可の仕組みに触れた

はじめに

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 の流れを実践してみた。 文字ベースで見ていた仕様の実際の処理の流れのイメージが理解できたのでよかった。

参考