Table of Contents
RFC 7636 : コード交換のための証明キー(PKCE、「ピクシー」と発音)は、認可コードの傍受攻撃に対する対策に関する仕様です。
この仕様は 2015 年 9 月に公開され、以下の変更が追加されました。
code_challenge
パラメータおよび code_challenge_method
パラメータを追加。code_verifier
パラメータを追加。この仕組みにより、認可サーバーはコードベリファイアを持たない悪意のあるアプリケーションからのトークンリクエストを拒否できるようになります。
PKCE を使用する認可リクエストでは、code_challenge
パラメータを必須とし、オプションで code_challenge_method
パラメータを指定できます。
code_challenge
パラメータの値は、コードベリファイアに対してコードチャレンジメソッド(計算ロジック)を適用することで求められます。
コードベリファイアは、[A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
の文字を使用するランダムな文字列であり、最小 43 文字、最大 128 文字の長さである必要があります。
定義されているコードチャレンジメソッドは plain
と S256
です。それぞれのコードベリファイアをコードチャレンジに変換する計算ロジックは以下のとおりです。
メソッド | ロジック |
---|---|
plain |
code_challenge = code_verifier |
S256 |
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) |
plain
メソッドは入力を変更しないため、code_verifier
と code_challenge
の値は同じになります。
S256
メソッドは入力の SHA-256 ハッシュを計算し、そのハッシュ値を Base64-URL エンコードします。たとえば、code_verifier
の値が dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
の場合、code_challenge
の値は E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
になります。
S256
を使用する場合、クライアントアプリケーションは認可リクエストに code_challenge_method=S256
を含める必要があります。code_challenge_method
パラメータを省略すると、認可サーバーはデフォルト値として plain
を使用します。
認可コードを生成した後、認可サーバーはそれをデータベースに保存し、リクエストに含まれていたコードチャレンジおよびコードチャレンジメソッドも記録します。
認可サーバーは、後にクライアントアプリケーションからのトークンリクエストを検証するために、保存されたコードチャレンジおよびコードチャレンジメソッドを使用します。
PKCE に特化した認可エンドポイントのレスポンスは特にありません。通常のレスポンスと同じです。
認可サーバーから認可コードを受け取った後、クライアントアプリケーションはトークンリクエストを行います。トークンリクエストには、認可コードに加えて、コードチャレンジを計算するために使用したコードベリファイアを含める必要があります。
コードベリファイアを指定するためのリクエストパラメータの名前は code_verifier
です。
PKCE をサポートする認可サーバーのトークンエンドポイントは、トークンリクエストに有効なコードベリファイアが含まれているかどうかを確認します。
このチェックは、grant_type
が authorization_code
であり、トークンリクエストに含まれる認可コードがコードチャレンジと関連付けられている場合にのみ実行されます。
上記の条件を満たしているにもかかわらず、トークンリクエストに有効なコードベリファイアが含まれていない場合、そのリクエストは悪意のあるアプリケーションからのものと見なされ、認可サーバーはエラーレスポンスを返します。
検証は 2 つのコードチャレンジの比較によって行われます。
1 つは 認可リクエスト に含まれ、データベースに保存されているもの。
もう 1 つは トークンリクエスト に含まれる code_verifier
を使用して認可サーバーが計算したもの。
この 2 つが一致する場合、そのトークンリクエストは元の認可リクエストを行った正当なクライアントアプリケーションからのものと見なされます。それ以外の場合は、悪意のあるアプリケーションからのリクエストと見なされます。
トークンリクエストが検証されると、認可サーバーは通常どおりアクセストークンを発行します。
まだ Authlete アカウントをお持ちでない場合は、こちら から無料でサインアップできます。所要時間はわずか 5 分です。
認可リクエストを作成するには、サービス ID および クライアント ID が必要です。
サービス ID および クライアント ID が必要な場合は、クイックセットアップガイド に従ってサービスとクライアントをセットアップしてください。
また、Authlete 管理コンソール で サービス ID および クライアント ID を確認できます。
以下のセクションでは、サービスとクライアント設定の方法について説明します。
表. サービス設定
タブ | パラメータ | 値 |
---|---|---|
サービス設定 > エンドポイント > 基本設定 | サポート可能な認可タイプ | AUTHORIZATION_CODE を含める |
サービス設定 > エンドポイント > 基本設定 | サポート可能なレスポンスタイプ | CODE を含める |
エンドポイントの設定:
AUTHORIZATION_CODE
を選択します。CODE
を選択します。表. クライアント設定
タブ | パラメータ | 値 |
---|---|---|
クライアント設定 > 基本設定 > 一般 | クライアントタイプ | PUBLIC を選択 |
クライアント設定 > エンドポイント > 基本設定 | サポート可能な認可タイプ | AUTHORIZATION_CODE を含める |
クライアント設定 > エンドポイント > 基本設定 | サポート可能なレスポンスタイプ | CODE を含める |
クライアント設定 > エンドポイント > 基本設定 | リダイレクトURI | https://api.authlete.com/api/mock/redirection/service-api-key |
クライアント基本設定の構成:
公開
ラジオボタンを選択します。クライアントエンドポイントの構成:
クライアント設定 > エンドポイント > 基本設定 に移動します。
サポート可能な認可タイプ セクションで AUTHORIZATION_CODE
を選択します。
サポート可能なレスポンスタイプ セクションで CODE
を選択します。
リダイレクトURI の下で 追加 をクリックします。リダイレクトURLを次のように調整してください:
https://us.authlete.com/api/mock/redirection/service-id
変更を保存 をクリックして変更を適用します。
[OAuth2 Basic] で説明されているように、Authlete の認可 API は認可サーバーに代わって認可リクエストの検証を行います。
次の curl
コマンドを使用して、認可サーバーから Authlete API へ認可リクエストを送信できます。<Service ID>
、<Service Access Token>
、<Client ID>
、<Ticket>
を適切な値に置き換えてください。
# Linux/Mac
curl -v -X POST "https://us.authlete.com/api/<Service ID e.g. 10738933707579>/auth/authorization" \
-H "Authorization: Bearer <Service Access Token e.g. Xg6jVpJCvsaXvy2ks8R5WzjdMYlvQqOym3slDX0wNhQ>" \
-d "ticket=5tqii9i_pUp1iteacZGUtdjikRnqGSrPwW7lqoH1Pcc" \
-d "subject=john.s@example.com" \
-d "response_type=code" \
-d "client_id=<Client ID e.g.26478243745571>" \
-d "redirect_uri=https://client.example.org/cb/example.com" \
-d "code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM" \
-d "code_challenge_method=S256"
# Windows (PowerShell)
curl.exe -v -X POST "https://us.authlete.com/api/<Service ID e.g. 10738933707579>/auth/authorization" `
-H "Authorization: Bearer <Service Access Token e.g. Xg6jVpJCvsaXvy2ks8R5WzjdMYlvQqOym3slDX0wNhQ>" `
-d "ticket=5tqii9i_pUp1iteacZGUtdjikRnqGSrPwW7lqoH1Pcc" `
-d "subject=john.s@example.com" `
-d "response_type=code" `
-d "client_id=<Client ID e.g.26478243745571>" `
-d "redirect_uri=https://client.example.org/cb/example.com" `
-d "code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM" `
-d "code_challenge_method=S256"
このリクエストには code_challenge
および code_challenge_method
パラメータが含まれています。PKCE を実装するには、これらのパラメータを含めてテストする必要があります。
また、Authlete 管理コンソール で code_challenge
および code_challenge_method
を設定することもできます。
リクエストが有効な場合、Authlete は次のようなレスポンスを返します。
{
"action": "INTERACTION",
"resultCode": "A004001",
"resultMessage": "[A004001] Authlete has successfully issued a ticket to the service (API Key = 933860280) for the authorization request from the client (ID = 2800496004). [response_type=code, openid=false]",
"ticket": "cElOaH9j4mS6AiIGR9oLqHlDn9jpvcNjqSgyRqfcmAE",
"client": {...},
"service": {...},
}
リソースオーナーが認証され、同意が得られた場合、認可サーバーは issue エンドポイントを呼び出して認可コードを取得します。
次の curl
コマンドを使用して、トークンリクエストを送信できます。<Service ID>
、<Service Access Token>
、<Ticket>
を適切な値に置き換えてください。
# Linux/Mac
curl -X POST "https://us.authlete.com/api/<Service ID e.g. 10738933707579>/auth/authorization/issue" \
-H "Authorization: Bearer <Service Access Token e.g. Xg6jVpJCvsaXvy2ks8R5WzjdMYlvQqOym3slDX0wNhQ>" \
-H "Content-Type: application/json" \
-d '{ "ticket": "<Ticket e.g. cElOaH9j4mS6AiIGR9oLqHlDn9jpvcNjqSgyRqfcmAE>","subject": "testuser01"}'
# Windows
curl.exe -X POST "https://us.authlete.com/api/<Service ID e.g. 10738933707579>/auth/authorization/issue" `
-H "Authorization: Bearer <Service Access Token e.g. Xg6jVpJCvsaXvy2ks8R5WzjdMYlvQqOym3slDX0wNhQ>" \
-H "Content-Type: application/json" `
-d '{ "ticket": "Ticket e.g. cElOaH9j4mS6AiIGR9oLqHlDn9jpvcNjqSgyRqfcmAE","subject": "testuser01"}'
リクエストが成功すると、Authlete は認可コードを発行します。
{
"action": "LOCATION",
"authorizationCode": "ILePyGjraVgeU_fzaQRfd0gv10pzxgcpHY_vHT2dsPI",
"idToken": null,
"jwtAccessToken": null,
"responseContent": "https://client.example.org/cb/example.com?code=tJlGEKt8y0DLpjIA_jweywRtJs2fh83ZGNiwFRmIwYI&iss=https%3A%2F%2Fauthlete.com",
"resultCode": "A040001",
"resultMessage": "[A040001] The authorization request was processed successfully.",
"ticketInfo": {
"context": null
}
}
認可サーバーがリダイレクトレスポンスをユーザーエージェントに送信し、ユーザーエージェントは次のような HTTP GET リクエストをクライアントに送信したと仮定します。
GET /cb/example.com?code=ILePyGjraVgeU_fzaQRfd0gv10pzxgcpHY_vHT2dsPI HTTP/1.1
Host: client.example.org
次の curl
コマンドを実行して、トークンリクエストを送信できます。<Service ID>
、<Service Access Token>
、<Client ID>
、<Code>
を適切な値に置き換えてください。
curl -v -X POST https://us.authlete.com/api/<Service ID>/auth/token \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer <Service Access Token>" \
-d '{ "parameters": "grant_type=authorization_code&code=<Code>&redirect_uri=https%3A%2F%2Fmy-client.example.com%2Fcb1&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk", "clientId": "<Client ID>" }'
指定した認可コードおよびコードベリファイアが有効である場合、次のような JSON 形式のアクセストークンが返されます。
{
"resultMessage" : "[A050001] The token request (grant_type=authorization_code) was processed successfully.",
"action" : "OK",
"clientIdAliasUsed" : false,
"subject" : "testuser01",
"resultCode" : "A050001",
"refreshTokenExpiresAt" : 1730552811449,
"grantType" : "AUTHORIZATION_CODE",
"accessToken" : "7FfwOnGjVHwxXhs2Wr67XV1-ZhQaoy3ctKcGkLyKxuY",
"idToken" : "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjEyODk4ODg0NTk2ODYzIl0sImlzcyI6Imh0dHBzOi8vYXV0aGxldGUuY29tIiwiZXhwIjoxNTU5MTA2ODE1LCJpYXQiOjE1NTkwMjA0MTUsIm5vbmNlIjoibi0wUzZfV3pBMk1qIn0.5uSFMTGnubyvtiExHc9l7HT9UsF8a_Qb0STtWzyclBk",
"responseContent" : "{\"access_token\":\"7FfwOnGjVHwxXhs2Wr67XV1-ZhQaoy3ctKcGkLyKxuY\",\"refresh_token\":\"T1h7fJ6k55CyipDtXNPbzN8ta3FgAAf4QKjo36OVfIE\",\"scope\":\"openid\",\"id_token\":\"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0dXNlcjAxIiwiYXVkIjpbIjEyODk4ODg0NTk2ODYzIl0sImlzcyI6Imh0dHBzOi8vYXV0aGxldGUuY29tIiwiZXhwIjoxNTU5MTA2ODE1LCJpYXQiOjE1NTkwMjA0MTUsIm5vbmNlIjoibi0wUzZfV3pBMk1qIn0.5uSFMTGnubyvtiExHc9l7HT9UsF8a_Qb0STtWzyclBk\",\"token_type\":\"Bearer\",\"expires_in\":86400}",
"scopes" : [
"openid"
],
"accessTokenDuration" : 86400,
"type" : "tokenResponse",
"refreshToken" : "T1h7fJ6k55CyipDtXNPbzN8ta3FgAAf4QKjo36OVfIE",
"accessTokenExpiresAt" : 1730552811449,
"refreshTokenDuration" : 864000,
"clientId" : 12898884596863
}
おめでとうございます! PKCE によって保護された認可コードフローを使用して、アクセストークンの取得に成功しました。
Authlete は PKCE のための設定項目を提供しています。PKCE はサービスまたはクライアントの設定で有効化できます。Authlete 管理コンソール にログインし、サービスを選択して 認可 タブを開くと、「認可コード交換用証明キー(PKCE)」という設定オプションが見つかります。
サービス設定で PKCE を有効にする方法:
PKCEを必須にする
と コードチャレンジメソッドに対してS256を必須にする
を有効化します。クライアント設定で PKCE を有効にする方法:
PKCEを必須にする
と コードチャレンジメソッドに対してS256を必須にする
を有効化します。認可コード交換用証明キー(PKCE) で PKCEを必須にする
が有効になっている場合、認可コードフローを使用する認可リクエストには code_challenge
パラメータが必ず必要になります。デフォルトでは 無効 になっています。
セキュリティを強化するために、認可コード交換用証明キー(PKCE) を有効にしてください。これにより、code_challenge
パラメータを含まない認可リクエストは認可サーバーによって拒否されるようになります。