認可コードと PKCE デベロッパ
最終更新:2026年8月16日
認可コードと PKCE
ポータルで作成したアプリは Authorization Code + PKCE(S256) フローを使います。ブラウザが受け取るのは短命な認可コード code だけです。code_verifier は信頼できる環境に保存し、トークン交換に使います。機密クライアントはさらにバックエンドで client_secret を使います。JWT アサーションクライアントはさらにバックエンドで client_assertion に署名します。
本番 Issuer の例:
ISSUER=https://api-passport.swaymoon.com
実際のエンドポイントは {ISSUER}/.well-known/openid-configuration のディスカバリ文書に従ってください。
1. PKCE を生成する
- 高エントロピーの
code_verifierを生成します(43–128 の URL 安全文字)。 code_challenge = BASE64URL(SHA256(code_verifier))(パディングなし)。code_challenge_method = S256。
code_verifier と state はサーバーセッション、暗号化 Cookie、または非機密クライアントが使える安全なセッション保存に置いてください。第三者スクリプトへ漏らさないでください。
2. ユーザーを認可へ案内する
認可エンドポイントを組み立ててリダイレクトします。例:
GET /oauth2/authorize?
response_type=code
&client_id=swm_xxxxxxxx
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
&scope=openid%20name%20picture%20email
&state=RANDOM_STATE
&code_challenge=CHALLENGE
&code_challenge_method=S256
Host: api-passport.swaymoon.com
| パラメータ | 要件 |
|---|---|
response_type | 常に code |
client_id | デベロッパポータルが発行 |
redirect_uri | 登録済みで完全一致が必須 |
scope | 空白区切り。少なくとも openid |
state | CSRF 防止。コールバック時に元の値と一致するか検証 |
code_challenge / code_challenge_method | 必須、S256 |
ユーザーは必要なら passport.swaymoon.com でサインインし、認可を確認します。成功後、ブラウザは次へ遷移します:
https://app.example.com/callback?code=...&state=...
ユーザーが認可をキャンセルした場合、アプリは通常使える code を受け取りません。返されたエラーやキャンセルパラメータに従って処理してください。
3. 認可コードをトークンに交換する
トークンエンドポイントへ POST します(application/x-www-form-urlencoded)。
機密クライアント
バックエンドで HTTP Basic を使います:
POST /oauth2/token
Host: api-passport.swaymoon.com
Authorization: Basic BASE64(urlencode(client_id):urlencode(client_secret))
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=https://app.example.com/callback
&code_verifier=VERIFIER
非機密クライアント
Basic も client_secret も送らないでください。フォームに client_id を含めます:
POST /oauth2/token
Host: api-passport.swaymoon.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=https://app.example.com/callback
&client_id=swm_xxxxxxxx
&code_verifier=VERIFIER
JWT アサーションクライアント
Basic も client_secret も送らないでください。バックエンドで、登録した公開鍵に対応する秘密鍵で client_assertion に署名し、フォームに含めます:
POST /oauth2/token
Host: api-passport.swaymoon.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=AUTHORIZATION_CODE
&redirect_uri=https://app.example.com/callback
&client_id=swm_xxxxxxxx
&code_verifier=VERIFIER
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=SIGNED_JWT
client_assertion は ES256 で署名した JWT です。JWS ヘッダの kid はポータルに登録した公開鍵と一致させてください。ペイロードのクレーム:
| クレーム | 値 |
|---|---|
iss | あなたの client_id |
sub | あなたの client_id(iss と同じ) |
aud | ディスカバリ文書の token_endpoint(本番は通常 https://api-passport.swaymoon.com/oauth2/token) |
jti | リクエストごとに新しい一意の値 |
iat | 発行時刻 |
exp | 有効期限(数分以内を推奨。未来であること) |
秘密鍵はサーバーにだけ置きます。ポータルは秘密鍵 JWK を受け付けません。実行できる curl / Python 断片は「例とトラブルシューティング」を参照してください。
補足:
redirect_uriは認可リクエストの値と一致させる必要があります。code_verifierは認可時に送ったcode_challengeに対応している必要があります。- 認可コードは一度きりで、有効期間は短いです。
成功レスポンスの例(フィールドは実際の応答に従います):
{
"access_token": "...",
"refresh_token": "...",
"id_token": "...",
"token_type": "Bearer",
"expires_in": 300,
"scope": "openid name picture email"
}
- 機密クライアントと JWT アサーションクライアントは通常
refresh_tokenを受け取ります。トークンはすべて安全に保管し、client_secret、秘密鍵、Refresh Token を信頼できないフロントへ渡さないでください。 - 非機密クライアントの応答に
refresh_tokenはありません。Access Token が切れたら、認可コード + PKCE をやり直してください。
4. アクセストークンの更新(機密と JWT アサーション)
Access Token の期限切れ後、機密クライアント:
POST /oauth2/token
Authorization: Basic ...
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&refresh_token=REFRESH_TOKEN
JWT アサーションクライアントの更新でも Basic は使いません。新しい client_assertion を署名して送ります:
POST /oauth2/token
Host: api-passport.swaymoon.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&refresh_token=REFRESH_TOKEN
&client_id=swm_xxxxxxxx
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=SIGNED_JWT
更新が成功したら、新しい access_token と、応答でローテーションされる可能性のある refresh_token を使ってください。トークンローテーションでは古い Refresh Token がすぐ無効になることがあります。常に最新の応答を正としてください。
非機密クライアントはこの手順をサポートしません。
5. UX の要点
- 未サインインのユーザーは先にアカウントのサインインページへ行き、その後認可確認に進みます。
- 機微な操作では再サインイン(step-up authentication)が求められることがあります。想定どおりのセキュリティです。
- 同意ページの文言と任意権限のチェックは「権限と同意」を参照してください。
6. セキュリティチェックリスト
- 常に
code_verifierとstateを保存して検証する。 - 機密クライアント:
client_secretでのトークン交換はバックエンドのみ。 - JWT アサーションクライアント:
client_assertionの署名はバックエンドのみ。秘密鍵とkidはポータルに登録した公開鍵と対応させる。 - 非機密クライアント:
client_secretを捏造・ハードコードしない。PKCE と登録済み Redirect URI に依存する。 - コールバックと通信は HTTPS。
scopeは必要最小限。invalid_grant、invalid_client、invalid_requestなどのエラーを適切に扱う。
次のステップ:「トークンとユーザー情報」を読み、トークン検証とローカルユーザー作成を完了してください。