この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
いわさです。
ここ最近Azure ADのOIDC周りを少し触っています。
- Azure AD OIDCでUserInfoエンドポイントにアクセスする | DevelopersIO
- Azure ADのIDトークンを取得し、クレームを確認する | DevelopersIO
- Azure ADのIDトークンの署名を検証する | DevelopersIO
上記では自前で検証などしていたのですが、今回はAmazon API Gatewayとオーソライザーを使ったIDトークンの検証を行ってみたいと思います。
といっても、API GatewayにはJWTオーソライザーが提供されており、簡単に検証を行うことが出来ます。
JWTオーソライザーでは以下のようなJWTの基本的な検証機能を有しています。
- デコード
- 発行者のパブリックキーを使った署名の確認
- クレームの検証(kid, iss, aud, exp, nbf, iat, scope)
API Gateway + Lambda
組み込み対象のAPIを作成します。
バックエンド部分は一旦初期作成状態のLambda関数(Node14)とします。
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Hello from Lambda!'),
};
return response;
};
API Gatewayと統合し、Postmanで呼び出してみます。
Lambdaのレスポンスを表示できていますね。
JWTオーソライザーを登録
では、オーソライザーを登録しましょう。
Lambdaオーソライザーでカスタム処理を作ることも出来ますが、JWT検証のみであればJWTオーソライザーを使うと車輪のなんとかをせずに済むってところなのでしょうか。
JWTオーソライザーの登録にあたって、以下を登録します。
- 発行者URL
- アプリケーションID(クライアントID)
ドキュメントのIssueからフォーマットを取得し、テナントIDを置き換えます。
https://login.microsoftonline.com/common/.well-known/openid-configuration
{
"token_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/token",
"token_endpoint_auth_methods_supported": [
"client_secret_post",
"private_key_jwt",
"client_secret_basic"
],
"jwks_uri": "https://login.microsoftonline.com/common/discovery/v2.0/keys",
"response_modes_supported": [
"query",
"fragment",
"form_post"
],
"subject_types_supported": [
"pairwise"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"response_types_supported": [
"code",
"id_token",
"code id_token",
"id_token token"
],
"scopes_supported": [
"openid",
"profile",
"email",
"offline_access"
],
"issuer": "https://login.microsoftonline.com/{tenantid}/v2.0",
"request_uri_parameter_supported": false,
"userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo",
"authorization_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
"device_authorization_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/devicecode",
"http_logout_supported": true,
"frontchannel_logout_supported": true,
"end_session_endpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/logout",
"claims_supported": [
"sub",
"iss",
"cloud_instance_name",
"cloud_instance_host_name",
"cloud_graph_host_name",
"msgraph_host",
"aud",
"exp",
"iat",
"auth_time",
"acr",
"nonce",
"preferred_username",
"name",
"tid",
"ver",
"at_hash",
"c_hash",
"email"
],
"kerberos_endpoint": "https://login.microsoftonline.com/common/kerberos",
"tenant_region_scope": null,
"cloud_instance_name": "microsoftonline.com",
"cloud_graph_host_name": "graph.windows.net",
"msgraph_host": "graph.microsoft.com",
"rbac_url": "https://pas.windows.net"
}
登録に必要なテナントIDとアプリケーションIDは以下より取得可能です。
テナントIDを専用のものに変更した発行者URLをオーソライザーへ登録します。
https://login.microsoftonline.com/9b9e2fc6-dc1a-4d7f-97ff-e86600ac5b48/v2.0
先程と同じようにアクセスしてみます。
認証エラーになりました!
IDトークンを渡す
では、IDトークンを使って作成したAPIへアクセスしてみましょう。
IDトークンの取得方法は以下の記事を参照してください。
JWT検証後、Lambdaバックエンドでクレームへアクセスすることが出来ます。(参考)
nameを取得してみましょう。
API Gateway は JWT を検証した後、トークン内のクレームを API ルートの統合に渡します。JWT クレームには、Lambda 関数などのバックエンドリソースがアクセスできます。
exports.handler = async (event) => {
const response = {
statusCode: 200,
body: JSON.stringify(event.requestContext.authorizer.jwt.claims.name),
};
return response;
};
AuthorizationヘッダーにベアラートークンとしてIDトークンをセットしてリクエストを送信します。
検証を通過し、クレーム情報の取得に成功しました!
なお、不正なトークン(クライアントIDやテナントが異なるIDトークン、有効期限が切れたトークンなど)は401 Unauthorized
エラーとなることも確認出来ます。
まとめ
Azure ADに登録したアプリ情報を使って、JWTオーソライザーを構築してIDトークンの検証を行うことが出来ました。
カスタムLambdaでデコードして検証して、など行わなくて良いので楽ですね。