AWS AppSync で GraphQL リクエストを実行すると、「Unauthorized」エラーが表示されます。このエラーのトラブルシューティング方法を教えてください。
簡単な説明
レスポンスで返される HTTP ステータスコードによって定義される Unauthorized エラーには、次の 2 種類があります。
- 401 Unauthorized: 認証情報がないか無効であるため、リクエストは AWS AppSync または認証モードのいずれかによって拒否されました。
- Unauthorized タイプのエラーを伴う200 OK レスポンス:リゾルバーレベル以上の問題により、リクエストが拒否されました。
不正なエラーの原因を特定するには、ウェブブラウザで問題を再現してみます。次に、ブラウザのネットワークツールを使用して、HTTP 要求メッセージとレスポンスメッセージをキャプチャします。メッセージを分析して、エラーが発生した場所を特定します。オフラインで分析するには、これらのメッセージを HTTP アーカイブ (HAR) ファイルに保存します。
解決方法
401 Unauthorized レスポンス
401 Unauthorized レスポンスの場合、GraphQL ペイロードを送信するネットワークリクエストをチェックして、以下を確認します。
- Authorization または x-api-key ヘッダーが存在し、操作またはフィールドが必要とする認証モードの正しい認証情報が含まれています。ヘッダーに正しい認証情報がない場合、認証モードは要求を拒否します。
- JSON Web トークン (JWT) の場合、認証ヘッダーに (GitHub Web サイトの)「Bearer」というテキストは含まれません。
- JWT は正しい Amazon Cognito ユーザープールまたは OIDC プロバイダーからのものです。
- 認証情報は有効で、期限切れではありません。
200 OK レスポンス
200 OK レスポンスの未承認エラーの原因の詳細を確認するには、 AWS AppSync API で Amazon CloudWatch Logs をオンにします。トラブルシューティングのベストプラクティスとして、フィールドレベルログを [すべて] に設定し、詳細な内容を含めます。
エラータイプが Unauthorized で 200 OK レスポンスを受け取り、タイプ Y で X にアクセスする権限がないというメッセージを受け取るリクエストは、Apache Velocity Template Language (VTL) リゾルバマッピングのロジックテンプレートによって拒否されます。この問題を解決するには、使用する認証モードについて、次のトラブルシューティングステップを実行します。
Amazon Cognito と OIDC 認証
グループ、email_verified、クライアント ID またはオーディエンスなどのユーザーのトークン要求を、VTL リゾルバマッピングテンプレートの認証チェックと比較します。サードパーティツールjwt.io (AuthO) を使用して、トークンのクレームを確認できます。AWS Amplify を使用している場合は、トークンクレームがモデルスキーマタイプの認証ルール要件をサポートしていることを確認します。
たとえば、Amplify の次のリゾルバーマッピングテンプレートは、AWS AppSync が行う予備認証チェックから渡されたデータをチェックします。
#if( $util.authType() == "User Pool Authorization" )
#if( !$isAuthorized )
#set( $staticGroupRoles = [{"claim":"cognito:groups","entity":"Admin","allowedFields":xxxxx,yyyyy}] )
#foreach( $groupRole in $staticGroupRoles )
#set( $groupsInToken = $util.defaultIfNull($ctx.identity.claims.get($groupRole.claim), []) )
#if( $groupsInToken.contains($groupRole.entity) )
#if( $groupRole.isAuthorizedOnAllFields )
#set( $isAuthorized = true )
#break
#else
$util.qr($allowedFields.addAll($groupRole.allowedFields))
#end
#end
#end
#end
#end
また、Amplify を使用している場合は、スキーマの認証ルールが作成、読み取り、更新、または削除操作を許可していることを確認します。
IAM 認証
AWS AppSync へのリクエストに署名する AWS ID およびアクセス管理 (IAM) ユーザーまたはロールに適用されるポリシーを確認します。ユーザーがアクセスする各フィールドの Action ブロックで appsync:GraphQL が付与されていることを確認します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"appsync:GraphQL"
],
"Resource": [
"arn:aws:appsync:us-east-1:111122223333:apis/graphql-api-id/types/Query/fields/field-1",
"arn:aws:appsync:us-east-1:111122223333:apis/graphql-api-id/types/Mutation/fields/field-2"
]
}
]
}
注: graphql-api-id を GraphQL API の ID に置き換え、フィールド-1 とフィールド-2 をお客様のフィールドに置き換えます。
Amplify を使用してリゾルバマッピングテンプレートを生成している場合は、次を確認します。
- IAM 認証情報が発行されるロールセッション名は、CognitoIdentityCredentials と等しくなります。
- IAM 認証情報は、Amplify が生成する auth または unauth ロールと同じです。
ロールセッション名が文字列と一致しない場合、フィールドまたは操作へのアクセスは拒否されます。
Lambda 認証
- isAuthorized が発行された Lambda 関数コードに記述したカスタムロジックをチェックして、true に設定されていることを確認します。
- DeniedFields 配列に、要求されたフィールドまたは操作が含まれていないことを確認します。
- CloudWatch ログを確認するか、デバッグステートメントを追加して、ユーザー認証を決定するロジックフローを検証します。
複数の認証モードを使用する
AWS AppSync API に複数の認証モードがある場合、API は設定されたデフォルトの認証モードを使用します。他の認証モードのいずれかを必要とするタイプまたはフィールドには、そのモードの認証ディレクティブも設定する必要があります。詳細については、「AWS AppSync GraphQL API での複数の認証タイプの使用」を参照してください。
たとえば、AWS AppSync API では、デフォルトの認証モードとして API_KEY が設定され、追加の認証モードとして AMAZON_COGNITO_USER_POOLS が設定されています。両方のモードを使用する場合は、@aws_api_key と @aws_cognito_user_pools の認証ディレクティブを設定する必要があります。
type Post @aws_api_key @aws_cognito_user_pools {
id: ID!
author: String
title: String
}
注: デフォルトの API_KEY 認証モードは、次の理由でリクエストを拒否します。
- Amazon Cognito JWT がリクエストヘッダーで送信されます。
- ディレクティブが GraphQL スキーマにありません。