Amplify GraphQL联合身份未授权用户访问权限报错排查
问题
使用Amplify开发Web应用(应用A),同时有一个无前端的Node.js应用(应用B)需要向DynamoDB表写入数据,需为应用B配置未授权访问或后端认证方式。
已执行以下操作:
- 初始化Amplify
- 配置Cognito身份池
- 为
team-provider-info.json中列出的未授权角色配置多种策略 - 将未授权角色附加到联合身份策略
- 尝试设置
aws_appsync_authenticationType为AMAZON_COGNITO_USER_POOLS和IAM - 将模型的认证规则设置为公开
- 运行
amplify update auth开启未授权访问
但在Amplify CLI和AppSync控制台执行查询时,仍报错:Not Authorized to access listPersonalInfos on type Query
Auth Resolver VTL代码
## [Start] Authorization Steps. ** $util.qr($ctx.stash.put("hasAuth", true)) #set( $isAuthorized = false ) #set( $primaryFieldMap = {} ) #if( $util.authType() == "API Key Authorization" ) #end #if( $util.authType() == "IAM Authorization" ) #set( $adminRoles = ["ap-southeast-2_YNRFmtdr2_Full-access/CognitoIdentityCredentials","ap-southeast-2_YNRFmtdr2_Manage-only/CognitoIdentityCredentials"] ) #foreach( $adminRole in $adminRoles ) #if( $ctx.identity.userArn.contains($adminRole) && $ctx.identity.userArn != $ctx.stash.authRole && $ctx.identity.userArn != $ctx.stash.unauthRole ) #return($util.toJson({})) #end #end $util.unauthorized() #end #if( $util.authType() == "User Pool Authorization" ) #if( !$isAuthorized ) #set( $staticGroupRoles = [{"claim":"cognito:groups","entity":"GoThriveAdmin"}] ) #foreach( $groupRole in $staticGroupRoles ) #set( $groupsInToken = $util.defaultIfNull($ctx.identity.claims.get($groupRole.claim), []) ) #if( $groupsInToken.contains($groupRole.entity) ) #set( $isAuthorized = true ) #break #end #end #end #if( !$isAuthorized ) #set( $authFilter = [] ) #set( $ownerClaim0 = $util.defaultIfNull($ctx.identity.claims.get("sub"), null) ) #set( $currentClaim1 = $util.defaultIfNull($ctx.identity.claims.get("username"), $util.defaultIfNull($ctx.identity.claims.get("cognito:username"), null)) ) #if( !$util.isNull($ownerClaim0) && !$util.isNull($currentClaim1) ) #set( $ownerClaim0 = "$ownerClaim0::$currentClaim1" ) #if( !$util.isNull($ownerClaim0) ) $util.qr($authFilter.add({"owner": { "eq": $ownerClaim0 }})) #end #end #set( $role0_0 = $util.defaultIfNull($ctx.identity.claims.get("sub"), null) ) #if( !$util.isNull($role0_0) ) $util.qr($authFilter.add({"owner": { "eq": $role0_0 }})) #end #set( $role0_1 = $util.defaultIfNull($ctx.identity.claims.get("username"), $util.defaultIfNull($ctx.identity.claims.get("cognito:username"), null)) ) #if( !$util.isNull($role0_1) ) $util.qr($authFilter.add({"owner": { "eq": $role0_1 }})) #end #if( !$authFilter.isEmpty() ) $util.qr($ctx.stash.put("authFilter", { "or": $authFilter })) #end #end #end #if( !$isAuthorized && $util.isNull($ctx.stash.authFilter) ) $util.unauthorized() #end $util.toJson({"version":"2018-05-29","payload":{}}) ## [End] Authorization Steps. **
CloudWatch日志
{ "logType": "RequestMapping", "path": [ "listPersonalInfos" ], "fieldName": "listPersonalInfos", "resolverArn": "arn:aws:appsync:ap-southeast-2:771661204178:apis/6pu5wf3wvfcr7dh3zribqhp6ua/types/Query/resolvers/listPersonalInfos", "functionName": "QuerygetPersonalInfoauth0Function", "requestId": "1817ebd7-80d3-48da-93d3-471f37aa665a", "context": { "arguments": {}, "prev": { "result": {} }, "stash": { "authRole": "arn:aws:sts::771661204178:assumed-role/amplify-talentui-dev-122653-authRole/CognitoIdentityCredentials", "conditions": [], "connectionAttributes": {}, "fieldName": "listPersonalInfos", "hasAuth": true, "metadata": { "dataSourceType": "AMAZON_DYNAMODB", "apiId": "6pu5wf3wvfcr7dh3zribqhp6ua" }, "tableName": "PersonalInfo-6pu5wf3wvfcr7dh3zribqhp6ua-dev", "typeName": "Query", "unauthRole": "arn:aws:sts::771661204178:assumed-role/amplify-talentui-dev-122653-unauthRole/CognitoIdentityCredentials" }, "outErrors": [] }, "fieldInError": true, "errors": [ "Not Authorized to access listPersonalInfos on type Query" ], "parentType": "Query", "graphQLAPIId": "6pu5wf3wvfcr7dh3zribqhp6ua", "functionArn": "arn:aws:appsync:ap-southeast-2:771661204178:apis/6pu5wf3wvfcr7dh3zribqhp6ua/functions/2zc46rgvzjgn3osvltkfuz4g3y" }
解决方案
1. 修复Auth Resolver的IAM授权逻辑
从日志可见,请求使用的是Cognito身份池的未授权角色,但现有VTL代码的IAM授权块仅允许指定的adminRoles,还直接排除了unauthRole,导致未授权请求被直接拒绝。
修改VTL中的IAM授权块,添加允许未授权角色访问的逻辑:
#if( $util.authType() == "IAM Authorization" ) #set( $adminRoles = ["ap-southeast-2_YNRFmtdr2_Full-access/CognitoIdentityCredentials","ap-southeast-2_YNRFmtdr2_Manage-only/CognitoIdentityCredentials"] ) #set( $isIamAuthorized = false ) #foreach( $adminRole in $adminRoles ) #if( $ctx.identity.userArn.contains($adminRole) ) #set( $isIamAuthorized = true ) #break #end #end #if( $ctx.identity.userArn == $ctx.stash.unauthRole ) #set( $isIamAuthorized = true ) #end #if( !$isIamAuthorized ) $util.unauthorized() #end #end
2. 确认模型的认证规则配置
确保GraphQL模型正确设置了允许未授权访问的规则,示例如下:
type PersonalInfo @model @auth(rules: [ { allow: public }, // 允许所有未授权用户访问 { allow: private, operations: [read, update, delete] }, // 可选:已授权用户的权限 { allow: groups, groups: ["GoThriveAdmin"], operations: [create, update, delete] } ]) { id: ID! // 其他字段定义 }
3. 验证未授权角色的IAM策略
检查Cognito身份池的未授权角色是否包含AppSync访问权限,策略需包含类似内容:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "appsync:GraphQL" ], "Resource": [ "arn:aws:appsync:ap-southeast-2:771661204178:apis/6pu5wf3wvfcr7dh3zribqhp6ua/types/Query/fields/listPersonalInfos", "arn:aws:appsync:ap-southeast-2:771661204178:apis/6pu5wf3wvfcr7dh3zribqhp6ua/types/Mutation/fields/createPersonalInfo" ] } ] }
4. 确认AppSync API启用IAM认证
在AppSync控制台的设置页面,确保IAM已添加到认证类型列表中;若需要,可将其设置为默认认证类型(或在请求中明确指定IAM认证方式)。
内容的提问来源于stack exchange,提问作者Andy Vennells
相关产品推荐
相关产品推荐

