You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Lambda扮演Cognito用户角色调用带IAM授权的REST接口?

解决方案:让Lambda扮演Cognito用户调用带IAM Authorizer的API

我来帮你搞定这个需求,核心思路是让调用方Lambda临时「变身」成发起请求的Cognito用户——也就是获取该用户对应的IAM角色临时凭证,再用这个凭证签名调用目标API Gateway。具体步骤拆解如下:

1. 确保调用方Lambda能拿到用户的Cognito身份凭证

因为前端是通过Amplify+Cognito调用这个Lambda的,你需要让前端把用户的Cognito ID Token传递给Lambda(比如放在请求的Authorization header里,格式一般是Bearer {id-token})。同时,Lambda的事件上下文里也能拿到用户的Cognito身份ID(event.requestContext.identity.cognitoIdentityId),不过ID Token是后续获取临时角色凭证的关键。

2. 给调用方Lambda的执行角色添加权限

需要允许调用方Lambda调用STS的AssumeRoleWithWebIdentity接口,用来获取用户对应的Identity Pool角色的临时凭证。给Lambda的IAM执行角色添加如下政策:

{
    "Effect": "Allow",
    "Action": "sts:AssumeRoleWithWebIdentity",
    "Resource": "arn:aws:iam::你的AWS账号ID:role/你的IdentityPool认证角色ARN"
}

这里的Resource要替换成你在Cognito Identity Pool里配置的Authenticated Role(如果是未登录用户则用Unauthenticated Role)的ARN,也就是前端调用API时使用的那个角色。

3. 在Lambda中实现角色切换与API调用

用AWS SDK调用STS获取临时凭证,再用凭证签名请求目标API。以下是Node.js环境的代码示例:

const { STSClient, AssumeRoleWithWebIdentityCommand } = require("@aws-sdk/client-sts");
const { SignatureV4 } = require("@aws-sdk/signature-v4");
const { HttpRequest } = require("@aws-sdk/protocol-http");
const fetch = require("node-fetch");

exports.handler = async (event) => {
    // 从请求头中提取Cognito ID Token
    const authHeader = event.headers.Authorization;
    if (!authHeader) throw new Error("Missing authorization token");
    
    const idToken = authHeader.split(' ')[1];
    const stsClient = new STSClient({ region: "你的AWS区域" });

    // 构造STS调用参数
    const assumeRoleParams = {
        RoleArn: "arn:aws:iam::你的账号ID:role/IdentityPool-AuthenticatedRole", // 替换为你的认证角色ARN
        RoleSessionName: `cognito-user-${Date.now()}`, // 唯一会话名称,可自定义
        WebIdentityToken: idToken,
        DurationSeconds: 3600 // 临时凭证有效期,最长1小时
    };

    // 获取用户角色的临时凭证
    const assumeRoleResult = await stsClient.send(
        new AssumeRoleWithWebIdentityCommand(assumeRoleParams)
    );
    const { AccessKeyId, SecretAccessKey, SessionToken } = assumeRoleResult.Credentials;

    // 构造目标API请求并签名(IAM Authorizer要求请求必须用SigV4签名)
    const apiHost = "你的API Gateway域名(比如xxxx.execute-api.us-east-1.amazonaws.com)";
    const apiPath = "/你的API阶段/目标路径";
    const request = new HttpRequest({
        method: "GET", // 根据你的API调整请求方法
        hostname: apiHost,
        path: apiPath,
        headers: {
            "Content-Type": "application/json",
            host: apiHost
        }
    });

    // 用临时凭证签名请求
    const signer = new SignatureV4({
        credentials: { accessKeyId: AccessKeyId, secretAccessKey: SecretAccessKey, sessionToken: SessionToken },
        region: "你的AWS区域",
        service: "execute-api"
    });
    const signedRequest = await signer.sign(request);

    // 发送请求并返回结果
    const apiResponse = await fetch(`https://${apiHost}${apiPath}`, {
        method: signedRequest.method,
        headers: signedRequest.headers,
        body: signedRequest.body
    });
    const responseData = await apiResponse.json();

    return {
        statusCode: apiResponse.status,
        body: JSON.stringify(responseData)
    };
};

4. 确保目标API允许用户角色调用

给Identity Pool的Authenticated Role添加允许调用目标API的政策,这样临时凭证才有权限访问:

{
    "Effect": "Allow",
    "Action": "execute-api:Invoke",
    "Resource": "arn:aws:execute-api:你的区域:你的账号ID:你的API ID/*/*/目标路径"
}

额外注意事项

  • 建议在Lambda中验证ID Token的有效性(比如用Cognito的JWKS公钥验证签名),防止伪造的Token被用来获取角色凭证。
  • 临时凭证的有效期遵循最小必要原则,不要设置超过实际需要的时长。
  • 如果你的API和Lambda在同一账号下,不要图省事直接允许Lambda角色调用API——那样就不是以用户身份调用了,不符合你的需求。

内容的提问来源于stack exchange,提问作者Eitan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 18:40:39