はじめに
GraphQL API を実行する場合、API_KEY を使う場合は API Key 認証として具体的なリクエスト方法が示されている。
$ $ curl -XPOST -H "Content-Type:application/graphql" -H "x-api-key:ABC123" -d '{ "query": "query { movies { id } }" }' https://YOURAPPSYNCENDPOINT/graphql
一方、Cognito UserPools で認証を行っている場合は、どのような情報が必要かの具体例が少なかったので、本記事で説明する。
回答
手順の概要は以下の通り。
- ログイン可能な Cognito UserPools を作成する (この用途であれば Cognito フェデレーティットアイデンティティは不要)
- GraphQL API と作成した Cognito UserPools を紐づける
- Cognito UserPools にログインして ID トークンを取得する
- GraphQL API にアクセスする際の Authorization ヘッダに ID トークンを載せてアクセスする。
- 公式の説明では Authorization ヘッダには Amazon Cognito ユーザープールによって提供される OIDC トークンが使用されます、と説明されている が、Cognito UserPools を利用する場合は ID トークンが OIDC トークンに該当する
- Cognito に保存されているユーザー情報による制御を行いたい場合、Resolver 内で ID トークンの内容が参照できるため、これを使って解決する
デフォルトの認証モードとして Cognito UserPools を紐づける場合、マネジメントコンソールであれば 設定 > デフォルトの認証モードから設定できる。
Cognito UserPools にログインして以下の結果が得られたとする(これは cognito-idp admin_initiate_auth
を実行して得られた結果)。 この記事では Cognito UserPools の設定やログイン方法については説明しない。
{
"ChallengeParameters": {},
"AuthenticationResult": {
"AccessToken": "eyJraWQiOiJpSlp........",
"ExpiresIn": 3600,
"TokenType": "Bearer",
"RefreshToken": "eyJjdHkiOiJKV1QiLCJlbm......",
"IdToken": "eyJraWQiOiJ3RU9......"
},
"ResponseMetadata": {
"RequestId": "ed5aaa19-92a4-439f-b686-8a0525818e99",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"date": "Wed, 20 Oct 2021 00:26:58 GMT",
"content-type": "application/x-amz-json-1.1",
"content-length": "4098",
"connection": "keep-alive",
"x-amzn-requestid": "ed5aaa19-92a4-439f-b686-8a0525818e99"
},
"RetryAttempts": 0
}
}
この時、得られた AuthenticationResult.IdToken
をリクエスト時の Authorization ヘッダに設定してアクセスする。 具体的には以下の通り。
$ curl -s -X POST -H "Context-Type: application/graphql" -d '{"query": "{ hello }"}' -H "Authorization: eyJraWQiOiJ3RU9......" https://********.appsync-api.ap-northeast-1.amazonaws.com/graphql
# {"data":{"hello":"This is a fixed string!"}}
初期設定では Cognito にログインして正常な ID トークンさえ持っていればアクセスが可能だが、ユーザー毎にアクセスを制限したい場合、リゾルバー内で $context.identity
としてアクセスして ID トークンに含まれる情報を取得し、利用できる。
例えば、$context.identity.claims.get("cognito:groups")
によって、ユーザーが所属しているグループ一覧が取得できるため、これを使って「Administratorグループに属していれば PutItem が可能」と言ったリゾルバーマッピングテンプレートを記載できる。
より詳細なユースケースは以下を参照。