使用Cognito的AWS Lambda API网关 - 如何使用IdentityId访问和更新UserPool属性?

Duk*_*gal 33 amazon-cognito aws-lambda aws-api-gateway

好吧,我现在已经进入了这个阶段并取得了重大进展,但仍然完全被基本面所困扰.

我的应用程序使用Cognito用户池来创建和管理用户 - 这些在S3上通过IdentityId标识.我的每个用户都有自己的S3文件夹,AWS会自动为他们提供一个等于用户IdentityId的文件夹名称.

我需要将IdentityId与其他Cognito用户信息相关联,但无法确定如何使用.

我需要的关键是能够识别用户名以及给定IdentityId的其他cognito用户属性 - 而且这非常困难.

因此,第一场战斗是在Cognito用户通过AWS API Gateway发出请求时,弄清楚如何获取IdentityId.最后我得到了解决方案,现在我有一个Cognito用户,他向API网关发出请求,而我后面的Lambda函数现在有了IdentityId.那一点有效.

但我完全不知道如何访问存储在用户池中的Cognito用户信息.我找不到任何明确的信息,当然也没有代码,它显示了如何使用IdentityId来获取Cognito用户的属性,用户名等.

看来,如果我使用"Cognito用户池"在API网关中授权我的方法,那么可以使用正文映射模板将Cognito用户信息(例如sub,用户名和电子邮件地址)放入上下文中,但我可以没有得到IdentityId.

但是如果我AWS_IAM在API网关中使用授权我的方法,那么身体映射模板会反过来 - 它为我提供了IdentityId而不是Cognito用户字段,例如sub和username以及email.

这让我发疯了 - 如何将IdentityId和所有Cognito用户字段和属性合并为一个数据结构?事实上,我似乎只能得到一个或另一个是没有意义的.

Duk*_*gal 37

事实证明,要使用AWS Lambda/Cognito/API Gateway同时获取IdentityId AND用户详细信息,您需要使用AWS_IAM(NOT COGNITO_USER_POOLS)进行身份验证的Lambda函数,您必须将您的请求发送到AWS API网关,但是它必须是一个签名请求,然后你必须修改集成请求体映射模板,以便在事件中给你IdentityId(也许上下文?不记得了).现在你有了IdentityId.唷.现在,您必须从前端到后端提交客户端的Cognito ID令牌.验证令牌非常重要 - 如果您不验证令牌,则无法相信它没有被篡改.要解码和验证令牌,您必须从用户池获取密钥,将它们放入脚本中,确保您的AWS lambda zipfile中包含jwt解码库和签名验证库.现在,您的脚本必须验证从前端提交的令牌,然后您可以从令牌中获取用户详细信息.瞧!现在您同时拥有IdentityId以及用户详细信息,例如他们的子用户名,用户名和电子邮件地址.太简单.

以上是使用AWS Cognito/Lambda/API Gateway获取与IdentityId关联的用户名所需的操作.这花了我几天才能开始工作.

我可以请任何漫无目的的亚马逊员工........很难获得与IdentityId相关的用户详细信息.你需要解决这个问题.让我感到愤怒的是,这太累了,烧得太多了.

解决方案:

我这样做是通过修改亚马逊员工自定义授权器来实现的:https: //s3.amazonaws.com/cup-resources/cup_custom_authorizer_lambda_function_blueprint.zip

在这里找到并描述:https: //aws.amazon.com/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/

use strict';
let util = require('util');

var jwt = require('jsonwebtoken'); 
var jwkToPem = require('jwk-to-pem');

var userPoolId = 'YOUR USERPOOL ID';
var region = 'YOUR REGION'; //e.g. us-east-1
var iss = 'https://cognito-idp.' + region + '.amazonaws.com/' + userPoolId;

//https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html
// DOWNLOAD FROM https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
let userPoolKeys = {PUT YOUR DOWNLOADED USER POOL KEYS JSON HERE};
var pems = {};

let convertKeysToPems = () => {
    var keys = userPoolKeys['keys'];
    for(var i = 0; i < keys.length; i++) {
        //Convert each key to PEM
        var key_id = keys[i].kid;
        var modulus = keys[i].n;
        var exponent = keys[i].e;
        var key_type = keys[i].kty;
        var jwk = { kty: key_type, n: modulus, e: exponent};
        var pem = jwkToPem(jwk);
        pems[key_id] = pem;
    }
}

exports.handler = function(event, context) {

    convertKeysToPems()
    console.log(event);
    let token = event['body-json'].cognitoUserToken;
    console.log(event['body-json'].cognitoUserToken);
    ValidateToken(pems, event, context, token);

};


let ValidateToken = (pems, event, context, token) => {

    //Fail if the token is not jwt
    var decodedJwt = jwt.decode(token, {complete: true});
        console.log(decodedJwt)
    if (!decodedJwt) {
        console.log("Not a valid JWT token");
        context.fail("Unauthorized");
        return;
    }

    //Fail if token is not from your UserPool
    if (decodedJwt.payload.iss != iss) {
        console.log("invalid issuer");
        context.fail("Unauthorized");
        return;
    }

    //Reject the jwt if it's not an 'Access Token'
    if (decodedJwt.payload.token_use != 'id') {
        console.log("Not an id token");
        context.fail("Unauthorized");
        return;
    }

    //Get the kid from the token and retrieve corresponding PEM
    var kid = decodedJwt.header.kid;
    var pem = pems[kid];
    if (!pem) {
        console.log(pems, 'pems');
        console.log(kid, 'kid');
        console.log('Invalid token');
        context.fail("Unauthorized");
        return;
    }

    //Verify the signature of the JWT token to ensure it's really coming from your User Pool

    jwt.verify(token, pem, { issuer: iss }, function(err, payload) {
      if(err) {
        context.fail("Unauthorized");
      } else {
        let x = decodedJwt.payload
        x.identityId = context.identity.cognitoIdentityId
        //let x = {'identityId': context['cognito-identity-id'], 'decodedJwt': decodedJwt}
        console.log(x);
        context.succeed(x);
      }
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 几年过去了,这仍然是一个问题。不敢相信。AWS,您年纪太大了并且很难移动吗? (4认同)
  • 我同意您的困难,您是否有机会尝试创建与提供的 sub 匹配的 IAM S3 策略? (2认同)
  • 绝对令人发指的是,AWS使其变得如此困难,但仍未提供解决该问题的真正方法。 (2认同)
  • 还在为此挖 (2认同)