Amazon Cognito の GetClientToken でドメインなしの M2M トークン取得を試してみた

Amazon Cognito の GetClientToken でドメインなしの M2M トークン取得を試してみた

Amazon Cognito に M2M 用のアクセストークンを発行する GetClientToken API が追加されました。M2M だけが目的なら、ユーザープールドメインを作らずに済みます。ドメインの調達や、証明書の発行、DNS の設定も不要です。AWS CLI でトークンの発行から JWT の署名検証まで確認しました。
2026.09.02

はじめに

2026年8月31日、Amazon Cognito ユーザープールに GetClientToken API が追加されました。この API を使うと、ユーザープールドメインを作成せずに、AWS SDK、AWS CLI、API から M2M 用のアクセストークンを取得できます。

https://aws.amazon.com/about-aws/whats-new/2026/08/amazon-cognito-get-client-token/

開発者ガイドの Scopes, M2M, and resource servers は、トークンエンドポイントと GetClientToken の違いを次のように説明しています。

They differ in setup: the token endpoint requires a user pool domain and suits applications that use an OIDC library, while GetClientToken requires no domain and works through the AWS SDK, AWS CLI, or API.

検証内容

ユーザープールドメインを1つも作らないまま、M2M 用のアクセストークンの発行と JWT の署名検証まで完結できるかを AWS CLI で確認しました。使用した AWS CLI は aws-cli/2.36.36 で、get-client-token サブコマンドが利用できました。リージョンは ap-northeast-1 です。

ユーザープール、リソースサーバー、M2M 専用アプリクライアントを作成し、GetClientToken で取得したトークンを検証します。

ドメインなしのプール作成

ドメインを指定せずにユーザープールを作成し、カスタムスコープを持つリソースサーバーを追加しました。

aws cognito-idp create-user-pool \
    --pool-name m2m-domainless-20260901151058

aws cognito-idp create-resource-server \
    --user-pool-id "$user_pool_id" \
    --identifier urn:example:m2m-domainless-20260901151058 \
    --name "M2M domainless resource server 20260901151058" \
    --scopes ScopeName=read,ScopeDescription="Read access"

作成したユーザープールを describe-user-pool で確認した結果です(抜粋)。

{
    "UserPool": {
        "Id": "ap-northeast-1_xxxxxxxxx",
        "Name": "m2m-domainless-20260901151058",
        "EstimatedNumberOfUsers": 0,
        "Arn": "arn:aws:cognito-idp:ap-northeast-1:123456789012:userpool/ap-northeast-1_xxxxxxxxx",
        "UserPoolTier": "ESSENTIALS",
        "KeyConfiguration": {
            "KeyType": "AWS_OWNED_KEY"
        },
        "IssuerConfiguration": {
            "Type": "ORIGINAL"
        }
    }
}

レスポンスに Domain フィールドは含まれていませんでした。トークンを取得したあと、同じプールに対して再度 describe-user-pool を実行しても、内容は同じでした。ドメイン、ACM 証明書、DNS レコードは、いずれも作成していません。

リソースサーバーの作成レスポンスは次のとおりです。

{
    "ResourceServer": {
        "UserPoolId": "ap-northeast-1_xxxxxxxxx",
        "Identifier": "urn:example:m2m-domainless-20260901151058",
        "Name": "M2M domainless resource server 20260901151058",
        "Scopes": [
            {
                "ScopeName": "read",
                "ScopeDescription": "Read access"
            }
        ]
    }
}

ここで定義した read スコープが、後で取得するアクセストークンに載ります。

M2M 専用アプリクライアント

トークンを取得するアプリクライアントを作成しました。認証フローには ALLOW_CLIENT_TOKEN_AUTH を指定し、クライアントシークレットも生成しました。トークン取得時に指定できるスコープは、--allowed-o-auth-scopes で登録しました。

aws cognito-idp create-user-pool-client \
    --user-pool-id "$user_pool_id" \
    --client-name m2m-client-20260901151058 \
    --generate-secret \
    --explicit-auth-flows ALLOW_CLIENT_TOKEN_AUTH \
    --allowed-o-auth-flows client_credentials \
    --allowed-o-auth-scopes urn:example:m2m-domainless-20260901151058/read \
    --allowed-o-auth-flows-user-pool-client
アプリクライアント作成レスポンス(全文)
{
  "UserPoolClient": {
    "UserPoolId": "ap-northeast-1_xxxxxxxxx",
    "ClientName": "m2m-client-20260901151058",
    "ClientId": "<REDACTED>",
    "ClientSecret": "<REDACTED>",
    "RefreshTokenValidity": 30,
    "TokenValidityUnits": {},
    "ExplicitAuthFlows": [
      "ALLOW_CLIENT_TOKEN_AUTH"
    ],
    "AllowedOAuthFlows": [
      "client_credentials"
    ],
    "AllowedOAuthScopes": [
      "urn:example:m2m-domainless-20260901151058/read"
    ],
    "AllowedOAuthFlowsUserPoolClient": true,
    "EnableTokenRevocation": true,
    "EnablePropagateAdditionalUserContextData": false,
    "AuthSessionValidity": 3
  }
}

ALLOW_CLIENT_TOKEN_AUTH は、ユーザー認証フローと同時に指定できません。ALLOW_USER_SRP_AUTH と同時に指定してアプリクライアントを作成しようとすると、次のエラーが返りました。

An error occurred (InvalidParameterException) when calling the CreateUserPoolClient operation: ALLOW_CLIENT_TOKEN_AUTH is not a permitted ExplicitAuthFlow when user auth-flows are enabled.

ALLOW_USER_SRP_AUTH だけを持つ既存のアプリクライアントに対して、update-user-pool-client を実行しました。ALLOW_CLIENT_TOKEN_AUTH を後付けしようとすると、同じエラーが返りました。

An error occurred (InvalidParameterException) when calling the UpdateUserPoolClient operation: ALLOW_CLIENT_TOKEN_AUTH is not a permitted ExplicitAuthFlow when user auth-flows are enabled.

ユーザー認証フローを持つアプリクライアントは流用できないため、M2M 専用のアプリクライアントを新規に作る必要があります。

トークン取得

作成したアプリクライアントでアクセストークンを取得しました。クライアントシークレットをコマンドライン引数とシェル履歴に残さないため、一時ファイルを --cli-input-json で渡しています。umask 077 を設定してこのファイルを作成したため、パーミッションは 600 です。

umask 077
cat > request.json <<EOF
{
  "ClientId": "$client_id",
  "Secret": "$client_secret",
  "Scopes": ["urn:example:m2m-domainless-20260901151058/read"]
}
EOF

aws cognito-idp get-client-token --cli-input-json file://request.json

rm -f request.json

指定したのは ClientId、Secret、Scopes の3つだけで、UserPoolId は渡していません。ユーザープールは ClientId から特定されます。

{
  "ClientAuthenticationResult": {
    "AccessToken": "<REDACTED>",
    "ExpiresIn": 3600,
    "TokenType": "Bearer"
  }
}

トークンは ClientAuthenticationResult に含まれており、有効期間は 3600 秒、トークンタイプは Bearer でした。

JWT 署名検証

取得したアクセストークンをデコードし、JWKS の公開鍵で署名を検証しました。検証スクリプトの出力は次のとおりです。

{
  "algorithm": "RS256",
  "keyId": "<kid>",
  "claims": {
    "token_use": "access",
    "client_id": "<REDACTED>",
    "scope": "urn:example:m2m-domainless-20260901151058/read",
    "iss": "https://cognito-idp.ap-northeast-1.amazonaws.com/<user-pool-id>",
    "exp": 1788279066
  },
  "expiresInFromResponse": 3600,
  "jwksUrl": "https://cognito-idp.ap-northeast-1.amazonaws.com/<user-pool-id>/.well-known/jwks.json",
  "signatureVerification": {
    "originalJwtRs256Valid": true,
    "tamperedPayloadJwtRs256Valid": false
  }
}

JWT ヘッダの kid と一致する鍵が JWKS に含まれており、その鍵で RS256 署名の検証が成功しました。ペイロードを1文字だけ変更した JWT を同じ鍵で検証したところ、失敗しました。

トークンの iss は、リージョンとユーザープール ID で構成された URL でした。JWKS の URL もその配下にあり、いずれにもユーザープールドメインは現れませんでした。開発者ガイドの Verifying JSON web tokens が示す形式も、ユーザープール単位です。

You can find the JWKS URI for your user pool at https://cognito-idp.<Region>.amazonaws.com/<userPoolId>/.well-known/jwks.json.

トークンを検証する側の issuer と JWKS の設定は、ドメインの有無で変わりません。

IAM 認可の不在

GetClientToken の呼び出しは IAM で認可されません。API リファレンスの GetClientToken に明記されています。

Amazon Cognito doesn't evaluate AWS Identity and Access Management (IAM) policies in requests for this API operation. For this operation, you can't use IAM credentials to authorize requests, and you can't grant IAM permissions in policies.

リクエストの署名を省く --no-sign-request を付けて呼び出しても、トークンは発行されました。検証時に記録した終了ステータスとレスポンスは、次のとおりです。

{
  "exitStatus": 0,
  "response": {
    "ClientAuthenticationResult": {
      "AccessToken": "<REDACTED>",
      "ExpiresIn": 3600,
      "TokenType": "Bearer"
    }
  },
  "stderr": ""
}

一方、誤ったクライアントシークレットを渡した場合はトークンが発行されませんでした。

An error occurred (NotAuthorizedException) when calling the GetClientToken operation: Invalid client or secret

この API のリクエストを認可するのはクライアントシークレットだけで、シークレットの保護がトークンを発行できるかどうかを決めます。呼び出しを受け付ける前に制限する手段として、API リファレンスでは AWS WAF が挙げられています。ForbiddenException の説明は次のとおりです。

This exception is thrown when AWS WAF doesn't allow your request based on a web ACL that's associated with your user pool.

まとめ

GetClientToken では、ドメインを1つも作らずに、M2M 用のアクセストークンの発行から署名検証まで完結しました。取得できたのは、RS256 で署名された JWT です。iss と JWKS の URL にユーザープールドメインは現れませんでした。どちらもユーザープール単位の形式なので、トークンを検証する側の issuer と JWKS の設定は変更なしで済みます。

新規に M2M を構成し、Cognito 以外の用途でカスタムドメインを使う予定がない場合は、GetClientToken を活用できます。

既存構成でも、ドメインの維持管理が課題で、M2M 専用アプリクライアントの新設と呼び出し側の切り替えが可能な場合は、GetClientToken への切り替えを検討してください。

この記事をシェアする

AWSのお困り事はクラスメソッドへ

関連記事