如何在AWS Lambda中获取Cognito Identity ID

Ren*_*nan 21 amazon-web-services amazon-cognito aws-lambda

如何获取调用AWS Lambda函数的用户的身份ID(由AWS Cognito登录)?我是否必须在Lambda函数上使用SDK来获取身份标识?

小智 11

在lambda函数里面的AWS javascript SDK中,只需使用context.identity.cognitoIdentityId它对我有用

  • 我爱你,user966391. (3认同)
  • 我这样做,但在java函数中,所以它是context.getIdentity().getIdentityId(),它只返回一个空字符串.如果我记录context.getIdentity(),则返回'lambdainternal.api.LambdaCognitoIdentity@42f48531'.有任何想法吗? (3认同)
  • 在我的例子中 `context.identity.cognitoIdentityId` 为 null (2认同)

小智 8

如果您通过API网关,您可以将cognito id(以及用户arn和其他有用信息)传递给Lambda.这解决了我的问题.

http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html

  • API网关我们添加了认知认证.在api方法中添加了"$ context.identity.cognitoIdentityPoolId",但是当我们在JAVA lambda函数中访问它时它是空的.我们使用postman作为客户端并设置授权令牌.缺什么 ? (2认同)

Vic*_*rra 7

如果其他人偶然发现了这一点,我认为这会对您有很大帮助。

请注意,这仅适用于您使用 Cognito 用户池授权器的情况。如果您想将 AWS_IAM 与 Cognito 身份一起使用,请查看我的 github 示例https://github.com/VictorioBerra/js-cognito-auth-example(阅读下面的编辑区域)

如果您选中了“使用 Lambda 代理集成”,那么您将无权访问请求模板映射。但是您可以在 lambda 函数中访问令牌内的声明:

exports.handler = (event, context, callback) => {
    //create a response
    const response = {
      statusCode: 200,
      body: JSON.stringify({
          "user email": event.requestContext.authorizer.claims.email,
      }),
    };
    callback(null, response);    
};
Run Code Online (Sandbox Code Playgroud)

编辑 - 有关使用 AWS_IAM 作为 APIG 授权方的更多信息

基本上,您需要使用 AWS_IAM 保护您的 APIG,并且您必须通过 Cognito 联合身份进行身份验证,该身份将使用用户池返回 sessionToken示例。这就是使 AWS IAM 凭证成为临时凭证的原因。现在,您拥有了对 APIG 进行身份验证所需的一切。

要对此进行测试,请下载postman的桌面版本,输入您的 API URI(从阶段区域获取),然后在授权下填写 Sig4 签名所需的 5 个字段。您将看到 lambda 函数中的“event.identity”对象加载了该user对象等属性。

如果你想使用APIG自动生成的SDK它配备内置有一个工厂,需要的accessKeysecret以及token和体征一切都是为了你。与 aws-sdk 相同。您可以使用这三个项目初始化凭据,它会自动使用这些临时凭据为您签署所有请求。如果您想直接使用 window.fetch、request、curl 直接手动点击您的 API(在此处插入 http 客户端),您可以计算自己的 Sig4(请注意它可能有点复杂,或者使用现代库为您完成)

同样作为记录,在进行研究时,我注意到如果您不想使用 AWS_IAM 作为 APIG 授权方,并且您想使用“Cognito Identity Pool Authorizer”,这是 APIG 下拉列表中的一个新选项,您仍然可以获得如果您只是将从成功的 Cognito popl身份验证中获得的 JWT 作为授权标头传递给 APIG ,则 lambda 事件中的大量用户信息。在 JWT 内部有很多属性,您可以在池设置中自定义这些属性。

IMO 专业意见我认为使用 AWS_IAM temp creds 授权器是首选。这样,您可以在 Cognito 身份(Facebook、Twitter、池等)中使用任意数量的不同 IdP。



Wil*_*ena 6

对于仍在努力在 Lambda 函数中获取 Cognito 用户的 IdentityId 的其他人,经过多个小时的探索,我发现可以通过以下方式在 Lambda 函数中获取 IdentityId,具体取决于您用来调用 Lambda 的方法功能:

使用Cognito 用户池授权程序通过 API 网关触发器进行调用

IdentityId可以通过以下方式获取:

const IDENTITY_POOL_ID = "us-west-2:7y812k8a-1w26-8dk4-84iw-2kdi849sku72"
const USER_POOL_ID = "cognito-idp.us-west-2.amazonaws.com/us-west-2_an976DxVk"
const { CognitoIdentityClient } = require("@aws-sdk/client-cognito-identity");
const { fromCognitoIdentityPool } = require("@aws-sdk/credential-provider-cognito-identity");

exports.handler = async (event,context) => {
        const cognitoidentity = new CognitoIdentityClient({
             credentials:  fromCognitoIdentityPool({
             client: new CognitoIdentityClient(),
             identityPoolId: IDENTITY_POOL_ID,
                 logins: {
                     [USER_POOL_ID]:event.headers.Authorization
                 }
             }),
        });

        var credentials = await cognitoidentity.config.credentials()
        console.log(credentials)
        // {
        //    identityId: 'us-west-2:d393294b-ff23-43t6-d8s5-59876321457d',
        //    accessKeyId: 'ALALA2RZ7KTS7STD3VXLM',
        //    secretAccessKey: '/AldkSdt67saAddb6vddRIrs32adQCAo99XM6',
        //    sessionToken: 'IQoJb3JpZ2luX2VjEJj//////////...', // sessionToken cut for brevity 
        //    expiration: 2022-07-17T08:58:10.000Z
        //  }
        var identity_ID =  credentials.identityId
        console.log(identity_ID)
        // us-west-2:d393294b-ff23-43t6-d8s5-59876321457d

        const response = {
            statusCode: 200,
            headers: {
                "Access-Control-Allow-Headers": "*",
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods" : "OPTIONS,POST,GET,PUT"
             }, 
             body:JSON.stringify(identity_ID)
        };
        return response;
}
Run Code Online (Sandbox Code Playgroud)

为什么?

使用具有Cognito 用户池授权程序的 API 网关触发器调用 Lambda 函数将导致以下字段(为了简洁起见已删除的其他字段)在event调用中可用:

{
    "resource": "/{proxy+}",
    "path": "/_",
    "httpMethod": "POST",
    "headers": {
        "Authorization": "eyJrmlaod8(kyC9zdspo0jZIYjRENFlCNVBidnksl89DNm9USDJrT25MSDhjXC9EYkIzMzQ8389iYWxnIjoiUlMyNTYifQ.eyJzdWIiOiI8389yNDg4Ny0wYTRdkiuiOGQtODA4My1kNmIyYzZhYWNhN2YiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiaXNzIjoiaHR0cHM6XC9cL2NvZ25pdG8taWRwLnVzLXdlc3QtMi5hbWF6b25hd3MuY29tXC91cy13ZXN0LTJfZ3dPMjlMckR4IiwiY3VzdG9tOmZpcnN0X2tleSI6ImZhbHNlIiwiY29nbml0bzp1c2VybmFtZSI6IjJjNjI0ODg3LTBhNGItNGE4ZC04MDgzLWQ2YjJjNmFhY2E3ZiIsIm9yaWdpbl9qdGkiOiI0ODEzYzk1Ni01MDM0LTQzNmItYjE5OS00MWZjN2U1ZTQ0ODciLCJhdWQiOiJyNjdwOGdxNnQ5cHJrc2JyYmtxMDVoM2NuIiwiZXZlbnRfaWQiOiJmOWRlNWMxOC0yMTNlLTQ2NDgtOGY4MC1mODdhYWJhNWM4NGUiLCJjdXN0b206YXBpX2tleV9JRCI6Imhoa2hpMmw5cTkiLCJjdXN0b206YXBpX2tleSI6InVzLXdlc3QtMjplOTBkYmUzZC0wN2FhLTRjODQtOGQ0Ny04NjJmZDJhNzQ1MGZfcm5Zalk2YmhaT0lkWXhDcDBDcjNYZWVaYzFuT3ViZnkzdEs5aEtFRFVIZ3FJd1BSTVJuQ2pyWlJYdGNBSVpqWTVnMFFyejN3ek1keGoiLCJ0b2tlbl91c2UiOiJpZCIsImF1dGhfdGltZSI6MTY1ODA0ODg1OSwiZXhwIjoxNjU4MTM2MTk3LCJpYXQiOjE2NTgxMzI1OTcsImp0aSI6IjdmNTdiYWZlLTA1ZGUtNDgwZC1hMDgzLWY1MjlhN2YzNmI2YiIsImVtYWlsIjoidHJldmVuYXc3QGdtYWlsLmNvbSJ9.hk-8ajGP2jO0RQvzwZWp2d5T1BLiWL9q6vvrbXemLBbd2kb1kkBSvklfC_7WWvJoy1ukwNoq8Cx63U2hQfjJB077AHrHfN2PkJu4DG86vSdtSzrZVDQmle331UxopLQvzDZ1mejfmSFbo6x1ZeTbo39PRpox4pzsfeUAM1Rf8H6y8OrdPZa7Gh6gRkiN2IcwdBnXI4-Q6HX5QqiVzr2O4zEnNsqMFfsFA3aO05hnp7EYRWHgS6EgaQjfBirCoyerBkjFJTXynl76Jj4fK3-3KY4tw5EHplxkgAih7a9QTxy8SbRee8kh7fwrIGEO6CtgkM9v0XL7jBPtNtGTpqBRzw"
    },
    "requestContext": {
        "authorizer": {
            "claims": {
                "sub": "231df9d7-0aab-4dsd-8389-d315d9daca7f",
                "email_verified": "true",
                "iss": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_an976DxVk",
                "custom:first_key": "false",
                "cognito:username": "231df9d7-0aab-4dsd-8389-d315d9daca7f",
                "origin_jti": "8131rlpo-5123-436b-b199-41315d9d4487",
                "aud": "r6315d9dt9sdls315d9d5h3cn",
                "event_id": "f3dsp9d8-213e-4648-8f80-f8315d9dc84e",
                "custom:name": "my_name",
                "token_use": "id",
                "auth_time": "1658148859",
                "exp": "Mon Jul 18 09:23:17 UTC 2022",
                "iat": "Mon Jul 18 08:23:17 UTC 2022",
                "jti": "982sdafe-97rs-996l-i899-k315d9d09n7n",
                "email": "jeff@amazon.com"
            }
        },
        "extendedRequestId": "dSiT_dLdJdad9oP=",
        "requestTime": "18/Jul/2022:08:23:27 +0000",
        "requestTimeEpoch": 1658132607750,
        "requestId": "387ss00s3-add0-62i9-l9s0-9a8dj8976dfa",
        "identity": {
            "cognitoIdentityPoolId": null,
            "accountId": null,
            "cognitoIdentityId": null,
            "caller": null,
            "sourceIp": "91.83.769.200",
            "principalOrgId": null,
            "accessKey": null,
            "cognitoAuthenticationType": null,
            "cognitoAuthenticationProvider": null,
            "userArn": null,
            "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0",
            "user": null
        },
        "domainName": "mskd8fpni2.execute-api.us-west-2.amazonaws.com",
        "apiId": "mskds98ni2"
    },
    "body": "{\"name\":\"my_name\"}",
    "isBase64Encoded": false
}
Run Code Online (Sandbox Code Playgroud)

context并且以下字段在调用中可用:

{
    "callbackWaitsForEmptyEventLoop": true,
    "functionVersion": "$LATEST",
    "functionName": "hello-world-jsHelloWorldFunction-kTdLswTRrkdS",
    "memoryLimitInMB": "512",
    "logGroupName": "/aws/lambda/hello-world-jsHelloWorldFunction-kTdLswTRrkdS",
    "logStreamName": "2022/07/15/[$LATEST]95edi84719944bdi84a6cdi8451di849",
    "invokedFunctionArn": "arn:aws:lambda:us-west-2:598763214571:function:hello-world-jsHelloWorldFunction-kTdLswTRrkdS",
    "awsRequestId": "d8s57juq-3g39-49sk-8625-5849sk9be44I"
}
Run Code Online (Sandbox Code Playgroud)

请注意以下事项:

  • Cognito 用户的IdentityIdevent在或context
  • 有关 Cognito 用户的其他信息可在(电子邮件、子、自定义属性等)中找到。event
  • 请求调用时间event(调用 lambda 函数的时间可在event.requestContext.requestTime和中获得event.requestContext.requestTimeEpoch

注意:如果您在为 Lambda 函数使用 Cognito 用户池授权程序设置 API 网关触发器时遇到困难,请发表评论,如果人们感兴趣,我将添加有关如何完成此操作的说明。

使用 Cognito 用户凭证和适用于 JavaScript v3 的 AWS 开发工具包直接调用

IdentityId可以通过以下方式获取:

exports.handler = async (event,context) => {
        var identity_ID =  context.identity.cognitoIdentityId
        console.log(identity_ID)
        // us-west-2:d393294b-ff23-43t6-d8s5-59876321457d

        const response = {
            statusCode: 200,
            headers: {
                "Access-Control-Allow-Headers": "*",
                "Access-Control-Allow-Origin": "*",
                "Access-Control-Allow-Methods" : "OPTIONS,POST,GET,PUT"
             }, 
             body:JSON.stringify(identity_ID)
        };
        return response;
}
Run Code Online (Sandbox Code Playgroud)

为什么?

使用适用于 Javascript v3 的 AWS 开发工具包和 Cognito 用户凭证直接调用 Lambda 函数将导致调用中提供任何其他信息:event

{
    "name": "my_name"
}
Run Code Online (Sandbox Code Playgroud)

但是,IdentityId在调用中可用:context

{
    "callbackWaitsForEmptyEventLoop": true,
    "functionVersion": "$LATEST",
    "functionName": "hello-world-jsHelloWorldFunction-kTdLswTRrkdS",
    "memoryLimitInMB": "512",
    "logGroupName": "/aws/lambda/hello-world-jsHelloWorldFunction-kTdLswTRrkdS",
    "logStreamName": "2022/07/15/[$LATEST]95edi84719944bdi84a6cdi8451di849",
    "identity": {
        "cognitoIdentityId": "us-west-2:d393294b-ff23-43t6-d8s5-59876321457d",
        "cognitoIdentityPoolId": "us-west-2:7y812k8a-1w26-8dk4-84iw-2kdi849sku72"
    },
    "invokedFunctionArn": "arn:aws:lambda:us-west-2:598763214571:function:hello-world-jsHelloWorldFunction-kTdLswTRrkdS",
    "awsRequestId": "d8s57juq-3g39-49sk-8625-5849sk9be44I"
}
Run Code Online (Sandbox Code Playgroud)

请注意以下事项:

  • Cognito 用户的 IdentityIdcontext.identity.cognitoIdentityId
  • 有关 Cognito 用户的其他信息在或(电子邮件、子、自定义属性等)中不可用。eventcontext
  • 请求调用时间在 或 中均不可用eventcontext

注意:要使用 Cognito 用户的凭证和适用于 JavaScript v3 的 AWS 开发工具包直接调用 Lambda 函数,您需要将自定义 IAM 权限添加到 Cognito 用户池中经过身份验证的用户所承担的 IAM 角色。去做这个:

  1. 转到 IAM -> 角色,然后找到您的用户池的角色,例如amplify-myapp-prod-12987-authRole
  2. 点击“添加权限”
  3. 单击“创建内联策略”
  4. 单击“JSON”
  5. 插入以下策略并将函数 ARN 替换为您的 Lambda 函数的 ARN:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunctionUrl",
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "arn:aws:lambda:*:598763214571:function:hello-world-jsHelloWorldFunction-kTdLswTRrkdS"
            ]
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)
  1. 点击“查看政策”
  2. 保存政策

当前不支持对 Cognito 用户池中的用户进行身份验证的调用方法:

  1. 使用调用者凭证进行调用(仅当您使用 AWS_IAM 身份验证而不是Cognito 用户池授权者时才有效)
  2. 通过函数 URL 调用(也仅支持 AWS_IAM 身份验证)


Wil*_*aul 4

根据文档,有关身份提供者的信息似乎只能通过 Mobile SDK 进行调用。

为了解决这个问题,一种选择是将身份 ID 作为事件的一部分手动传递给函数。假设您正在做类似的事情AWS.config.credentials = new AWS.CognitoIdentityCredentials(...),那么您应该能够通过AWS.config.credentials.identityId(刷新凭据后)获取ID。

编辑:身份验证的更好选择是让 Cognito/IAM 处理它,并假设如果用户可以成功调用 Lambda 函数,则意味着他们被允许这样做。在这种情况下,要管理每个用户的验证,请查看白名单

  • 是的,这可行,但恐怕我无法验证 Lambda 函数中的身份,并且无法保证调用该函数的用户与他所说的相同。我应该担心这个问题吗?有办法解决吗? (3认同)
  • 例如:如果我想调用一个函数来创建/编辑/删除某些内容,例如在 DynamoDB 上,但我必须验证用户以确保他有权执行此操作。 (2认同)
  • @WilliamGaul 不幸的是,在这种情况下,文档略有误导。无论使用什么 SDK,只要凭证来自 Amazon Cognito authflow,身份就应该可用。 (2认同)