Amplify Gen2 Lambda函数“No federated jwt”报错问题咨询
问题翻译
我有一个采用Cognito用户池认证的Amplify应用,用户完成注册并验证邮箱后,将进入自定义表单补充信息。提交表单时会触发Lambda函数,该函数需完成以下操作:
- 在Cognito中创建用户组;
- 将用户加入该组;
- 在DynamoDB表中创建记录,且记录的
writeGroups字段使用步骤1创建的组名(该字段在Schema中配置了allow.groupsDefinedIn('writeGroups'))。
Lambda函数已成功部署到沙箱,且已授予allow.resource(createAccount).to(["manageGroups", "addUserToGroup", "manageGroupMembership"])权限及DynamoDB数据修改权限。但在Lambda内调用CognitoIdentityProviderClient或client.models.User.create(user)时,GraphQL API返回“No federated jwt”错误。Amplify Gen2文档未覆盖该场景,请问遗漏了什么配置?
出现“No federated jwt”错误的核心原因是Lambda作为后端服务调用GraphQL/Cognito时,未使用合法的后端身份凭证,而是错误依赖前端用户JWT或未提供有效身份。以下是需要补充的关键配置:
1. 为GraphQL API启用IAM授权模式
你的GraphQL API当前可能仅启用了Cognito用户池授权,但Lambda需要通过IAM角色调用API。需在Amplify数据资源配置中添加IAM授权:
// amplify/data/resource.ts import { type ClientSchema, a, defineData } from '@aws-amplify/backend'; const schema = a.schema({ User: a.model({ // 你的模型字段定义 writeGroups: a.string(), }) .authorization([ a.allow.groupsDefinedIn('writeGroups'), a.allow.iam() // 添加IAM授权,允许Lambda通过角色访问 ]) }); export const data = defineData({ schema, authorizationModes: { defaultAuthorizationMode: 'userPool', // 启用IAM作为额外授权模式,指定允许的操作 iamAuthorizationMode: { allowedOperations: ['create', 'update'] } } });
2. 补全Lambda执行角色的Cognito权限
你配置的Amplify抽象权限可能未完全映射到底层IAM权限,需直接为Lambda的IAM执行角色添加以下权限:
cognito-idp:CreateGroupcognito-idp:AdminAddUserToGroup
注意:必须使用带Admin前缀的Cognito操作——Lambda是后端服务,需要绕过用户自身权限限制直接管理用户组。
3. 正确初始化Amplify后端客户端
在Lambda代码中,不要依赖前端用户的认证状态,而是使用Lambda执行角色的默认凭证链初始化Amplify:
import { Amplify } from 'aws-amplify'; import { data } from '../amplify/data/resource'; // 仅初始化后端所需配置,无需前端认证相关设置 Amplify.configure({ API: { GraphQL: { endpoint: data.resources.GraphQLAPI.url, region: process.env.AWS_REGION, defaultAuthMode: 'iam' // 指定使用IAM授权 } } });
如果直接调用CognitoIdentityProviderClient,无需手动传入凭证,AWS SDK会自动使用Lambda的执行角色凭证:
import { CognitoIdentityProviderClient, CreateGroupCommand, AdminAddUserToGroupCommand } from "@aws-sdk/client-cognito-identity-provider"; const client = new CognitoIdentityProviderClient({ region: process.env.AWS_REGION }); // 创建用户组 const createGroupCmd = new CreateGroupCommand({ GroupName: '目标组名', UserPoolId: process.env.USER_POOL_ID }); await client.send(createGroupCmd); // 将用户加入组 const addUserCmd = new AdminAddUserToGroupCommand({ GroupName: '目标组名', UserPoolId: process.env.USER_POOL_ID, Username: '用户ID' }); await client.send(addUserCmd);
4. 验证writeGroups字段的权限逻辑
由于writeGroups字段配置了allow.groupsDefinedIn('writeGroups'),需确保IAM权限优先级足够覆盖字段级组限制,可单独为该字段添加IAM授权:
.writeGroups: a.string().authorization([ a.allow.groupsDefinedIn('writeGroups'), a.allow.iam() // 为字段单独添加IAM授权 ])
内容的提问来源于stack exchange,提问作者Jonny

