有没有办法在AWS Lambda中获取Cognito用户名?

时间:2017-02-21 06:16:52

标签: javascript amazon-web-services aws-lambda amazon-cognito

据我所知,AWS Lambda函数无法查找我的Cognito用户的用户名(我正在使用UserPools)。

这看起来非常奇怪,因为我认为各地的应用程序几乎总是依赖于操纵用户名。

我成功获得了Cognito IdentityId,但我无法找到任何方法将IdentityId与查找IdentityId所涉及的Cognito用户的任何内容联系起来。

有没有办法获取用户名? IdentityId和用户名之间有什么关系?

6 个答案:

答案 0 :(得分:2)

您可以从Authorization标头获取JWT令牌,然后使用适合您语言的库对其进行解码。

在JWT的有效载荷中是用户名。

或者,您可以使用listUsersCognitoIdentityServiceProvider的过滤器,在subhttp://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#listUsers-property)上致电{...}authorizer.claims.sub

答案 1 :(得分:1)

一段时间以来,我一直在努力寻找这个问题的答案,因为在线上的这些线程都没有简洁的答案。

听起来好像您在用户使用自定义属性针对您的Cognito用户池拥有Authorization的凭据后,正在尝试制定有效的Authenticated策略。

我创建了一个库,该库用于导出一些函数,这些函数可以让我捕获已验证用户的UserPoolIdUsername,以便捕获custom:<attribute>我需要在lambda内使用,以便实现的条件可以将API消耗给我需要为我的应用程序已认证的每个用户提供授权的其余AWS服务。

这是我的图书馆:

import AWS from "aws-sdk";
// ensure correct AWS region is set
AWS.config.update({
    region: "us-east-2"
});

// function will parse the user pool id from a string
export function parseUserPoolId(str) {
    let regex = /[^[/]+(?=,)/g;
    let match = regex.exec(str)[0].toString();

    console.log("Here is the user pool id: ", match);

    return match.toString();
}

// function will parse the username from a string
export function parseUserName(str) {
    let regex = /[a-z,A-Z,0-9,-]+(?![^:]*:)/g;
    let match = regex.exec(str)[0].toString();

    console.log("Here is the username: ", match);

    return match.toString();
}

// function retries UserAttributes array from cognito
export function getCustomUserAttributes(upid, un) {
    // instantiate the cognito IdP
    const cognito = new AWS.CognitoIdentityServiceProvider({
        apiVersion: "2016-04-18"
    });

    const params = {
        UserPoolId: upid,
        Username: un
    };

    console.log("UserPoolId....: ", params.UserPoolId);
    console.log("Username....: ", params.Username);

    try {
        const getUser = cognito.adminGetUser(params).promise();
        console.log("GET USER....: ", getUser);
        // return all of the attributes from cognito
        return getUser;
    } catch (err) {
        console.log("ERROR in getCustomUserAttributes....: ", err.message);
        return err;
    }
}

实施此库后,现在您可以为其创建授权策略的任何lambda都使用它。

在您的lambda里面,您需要导入上面的库(我在下面省略了import语句,您将需要添加这些以便可以访问导出的函数),并且可以实现它们的用法:

export async function main(event, context) {
  const upId = parseUserPoolId(
    event.requestContext.identity.cognitoAuthenticationProvider
  );
  // Step 2 --> Get the UserName from the requestContext
  const usrnm = parseUserName(
    event.requestContext.identity.cognitoAuthenticationProvider
  );
  // Request body is passed to a json encoded string in
  // the 'event.body'
  const data = JSON.parse(event.body);

  try {
    // TODO: Make separate lambda for AUTHORIZATION
    let res = await getCustomUserAttributes(upId, usrnm);

    console.log("THIS IS THE custom:primaryAccountId: ", res.UserAttributes[4].Value);
    console.log("THIS IS THE custom:ROLE: ", res.UserAttributes[3].Value);
    console.log("THIS IS THE custom:userName: ", res.UserAttributes[1].Value);

    const primaryAccountId = res.UserAttributes[4].Value;

  } catch (err) {
    // eslint-disable-next-line
    console.log("This call failed to getattributes");
    return failure({
      status: false
    });
  }
}


Cognito的响应将为数组提供所需的自定义属性。 Console.log使用console.log("THIS IS THE Cognito response: ", res.UserAttributes);记录Cognito的响应,并在CloudWatch日志中检查所需属性的索引号,并使用以下方法调整所需的索引:

res.UserAttributes[n]

现在,您拥有一种authorization机制,可以在lambda中以不同条件使用该机制,以允许用户POST到DynamoDB,或使用您的应用程序中的任何其他AWS服务,并为每个经过身份验证的用户提供正确的授权。

res.UserAttributes[n]中可以看到的响应中,您将看到所需的 sub 属性。

答案 2 :(得分:0)

如果您使用API​​网关支持Lambda函数,则可以使用Cognito Authorizer直接验证您的用户池令牌,并通过 $ context.authorizer.claims.preferred_username 传递从令牌中提取的用户名。

有关此集成的更多详细信息,请访问:http://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html

答案 3 :(得分:0)

详细说明@ doorstuck的答案,如果您正在使用由APIG调用的Lambda和AWS_IAM授权。然后,您可以获得用户名和其他属性,如下所示:

event.requestContext.identity.cognitoAuthenticationProvider是一个看起来像

的字符串

“cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxxxx,cognito-idp.ap-northeast-1.amazonaws.com/ap-northeast-1_xxxxxx:CognitoSignIn:SSSSSSSS”

SSSSSSSS是用户池中用户的子。您可以轻松解码字符串以获取sub并在listUsers的过滤器中使用它。

示例:

const provider = 
event.requestContext.identity.cognitoAuthenticationProvider;
const sub=provider.split(':')[2];
const Params = {
     UserPoolId: 'xxxxxxxxx', /* required */
     Filter: "sub=\""+ sub + "\"",
     Limit: 1
};
cognitoidentityserviceprovider.listUsers(Params, function(err, data) {
      if (err) console.log(err, err.stack); // an error occurred
      else   console.log(data.Users[0].Attributes);       
});

数据包含有关返回用户的有用信息,其中data.Users [0] .Attributes具有您的所有用户属性。 结果是

[ { Username: 'xxxxx',
Attributes: [Object],
UserCreateDate: 2017-09-12T04:52:50.589Z,
UserLastModifiedDate: 2017-10-24T01:50:00.109Z,
Enabled: true,
UserStatus: 'CONFIRMED' } ] }

data.Users [0] .Attributes是

[ { Name: 'sub', Value: 'SSSSSSS' },
{ Name: 'address', Value: 'xxxxxxxxi' },
{ Name: 'email_verified', Value: 'true' },
..... ]

请注意,您还可以使用

过滤返回的属性
AttributesToGet: [
    'STRING_VALUE',
    /* more items */
  ],
Params中的

答案 4 :(得分:0)

我们可以操纵身体映射模板中的上下文来获取子(用户名),它对我来说很好。试试这个,而不是拆分你的lamda函数。

 #set($sub = $context.identity.cognitoAuthenticationProvider.split(':')[2])
{
"tenantId": "$sub"
} 

答案 5 :(得分:0)

在Api网关中添加Cognito Authorizer后,我在lambda中获得了用户详细信息,该代码提供了经过解码的Authorization令牌,该令牌通过event.requestContext.authorizer.claims对象的标头传递。