[アップデート] Amazon Cognito に GetClientToken API が追加され、ドメインなしで M2M のアクセストークンを取得できるようになりました
いわさです。
Amazon Cognito ユーザープールには、ユーザー認証とは別に、アプリケーション同士を認可する M2M(machine-to-machine)の仕組みがあります。
これまで M2M のアクセストークンを取得するには、ユーザープールにドメインを設定して、そのドメインの /oauth2/token エンドポイントに HTTP リクエストを投げる必要がありました。
サービス間通信のためだけにホスト UI 用のドメインを用意して管理する構成になるので、M2M だけを使いたい場合は少し手間でした。
先日のアップデートで、GetClientToken という API 操作が追加されました。
これを使うと、ドメインを設定しなくても AWS SDK / CLI / API から直接 M2M 用のアクセストークンを取得できます。
今回こちらを確認してみたので紹介します。
実際に確認してみる
では早速 CLI から試してみます。
検証は aws-cli/2.36.34、東京リージョンで行いました。
事前に M2M 用のユーザープールとリソースサーバーを作成します。カスタムスコープは適当に定義しておきます。
aws cognito-idp create-user-pool \
--pool-name "m2m-getclienttoken-verify"
aws cognito-idp create-resource-server \
--user-pool-id ap-northeast-1_xxxxxxxxx \
--identifier "https://api.example.com" \
--name "example-api" \
--scopes ScopeName=read,ScopeDescription="read access" \
ScopeName=write,ScopeDescription="write access"
続いて M2M 用のアプリクライアントを作成するのですがここで気をつける点がありまして、新しいGetClientToken を使うための条件は 2 つあります。
クライアントシークレットを持つこと(--generate-secret)と、認証フローに ALLOW_CLIENT_TOKEN_AUTH を有効にすることです。そこだけ忘れないようにしましょう。

ではシークレットを取り出して、get-client-token を呼んでみましょう。なお、ユーザープールにドメインは設定していません。
SECRET=$(aws cognito-idp describe-user-pool-client \
--user-pool-id ap-northeast-1_xxxxxxxxx \
--client-id 12uivtjolt5208e5medm110lfr \
--query 'UserPoolClient.ClientSecret' --output text)
aws cognito-idp get-client-token \
--client-id 12uivtjolt5208e5medm110lfr \
--secret "$SECRET" \
--scopes "https://api.example.com/read"
お、ドメインなしでアクセストークンが返ってきましたね。
{
"ClientAuthenticationResult": {
"AccessToken": "eyJraWQiOiJvZ0hBWmZ...(省略)...IsAHEg",
"ExpiresIn": 3600,
"TokenType": "Bearer"
}
}
Token エンドポイントで返ってくるレスポンスともしかして違うのかなともちょっと思っていたのですが、同じ形式ですね。互換性あって使いやすそうで良い。
スコープも一応見てみます。JWT のペイロード部分をデコードして中身も確認してみましょう。
{
"sub": "12uivtjolt5208e5medm110lfr",
"token_use": "access",
"scope": "https://api.example.com/read",
"iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxxxxxx",
"version": 2,
"client_id": "12uivtjolt5208e5medm110lfr",
"exp": 1788210941,
"iat": 1788207341
}
token_use は access、scope にはリクエストで指定したスコープが入っています。
sub と client_id がアプリクライアント ID になっていて、ユーザー個人を表すクレームは含まれていません。
iss(発行者)は https://cognito-idp.<リージョン>.amazonaws.com/<ユーザープールID> です。
検証の流れも従来のドメインベースのトークンと同じでいけそうですね。
先ほどはget-client-token呼び出し時にscopesを付けました。 --scopes を指定しない呼び方もしてみます。
aws cognito-idp get-client-token \
--client-id 12uivtjolt5208e5medm110lfr \
--secret "$SECRET"
この場合はアプリクライアントに設定されているスコープがすべて付与されました。まぁ予想どおりか。
scope= https://api.example.com/write https://api.example.com/read
さいごに
本日は Amazon Cognito に追加された GetClientToken API を確認してみました。
ドメインを設定していないユーザープールでも、CLI からそのままアクセストークンを取得できました。
発行されるのは従来の client credentials grant と同等のアクセストークンで、スコープやトークンの検証方法もこれまでと変わりません。
従来のドメインベースの client credentials フローも引き続き使えるので、今回のアップデートは選択肢がひとつ増えたという位置づけですね。
なお、/oauth2/token のトークンエンドポイントはユーザープールにドメインを追加すると公開されるものなので、こちらの経路を使う場合は引き続きドメインが必要です。
The token endpoint becomes publicly available when you add a domain to your user pool.
GetClientToken は AWS SDK / CLI と統合でき、WAF や PrivateLink にも対応するとのことなので、ドメインの管理や DNS の伝播を待たずに AWS 環境内で完結する M2M 認可を組みたい場面では扱いやすそうです。
Cognito の M2M 認可を CDK で組む方法は以前 DevelopersIO でも紹介されています。







