在 DynamoDB 中保存 AWS Cognito 用户

Posted

技术标签:

【中文标题】在 DynamoDB 中保存 AWS Cognito 用户【英文标题】:Save AWS Cognito Users in DynamoDB 【发布时间】:2018-05-31 18:54:46 【问题描述】:

我最近开始尝试使用 AWS AppSync,但我对 AWS Cognito 有一些疑问。

我希望用户能够通过 Facebook 进行身份验证,但我需要他们的个人资料照片、姓名和电子邮件作为我的应用程序中公开用户个人资料的数据。到目前为止,我注意到 Cognito 与 Facebook Auth 集成,但它不允许访问用户信息,并且此信息不会保存在 DynamoDB 表中。

我的问题是,当 Cognito 收到新的登录信息时,如何在 DynamoDB 中创建新用户,或者当用户已经存在于数据库中时返回现有用户/ID。

【问题讨论】:

【参考方案1】:

几周前我试图实现同样的目标。

在阅读了几个小时的文档后,我意识到 Cognito 可能无法帮助我们处理从 FB 返回的数据或如何保存它。

我最终做了以下事情:

(1) 使用FB-SDK,拉取用户数据。

(2) 调用了一个 Lambda 函数,将该数据(如 FB_id 等)保存到 DynamoDB。

(3) 如果用户再次登录,他们的 FB_id(或电子邮件)用于检查 DynamoDB 条目以检索他们的数据。

如果 Cognito 能够帮助我们并且我以某种方式错过了它,我很想知道。

编码愉快!

【讨论】:

但是你怎么做来授权未来的 api 请求呢? Cognito 返回一个 jwt,您可以将其添加为标头,但我猜想用 dynamo 很难模仿这种行为? 据我了解,Cognito 仍然会通过 FB 检查提供的令牌是否有效等的整个过程。如果 Cognito 回来并说它有效并给我一个 jwt,然后我会采取用户详细信息并在 DDB 中自行处理。 你有一些我可以查看的代码 sn-ps 吗?这将极大地帮助我。谢谢你的回复! 2019,这仍然是最好的方法。更重要的是,如果您需要在用户之间共享信息,例如社交应用程序,如果数据存储在 Cognito 用户池中,则很难让其他用户信息被发现。【参考方案2】:

您可以在您的用户池中使用custom attributes 和federating user from Facebook 来实现此目的。以下是执行此操作的高级步骤。

您首先必须为要保存在每个用户配置文件中的配置文件信息定义自定义属性。 定义 attribute mapping 以将自定义属性链接到您要保存的 Facebook 属性。 使用Cognito hosted pages 和联合构建您的应用程序,以允许您的用户使用Facebook 登录。

之后,在您的应用程序中的每个新用户登录时,都会在您的用户池中创建一个新用户,其中包含在属性映射中定义的所有属性以及 Cognito 在 Facebook 令牌中获取的值。您的应用会在身份验证后颁发的 IDToken 中获取这些属性值,您的应用可以使用这些属性值。

此外,如果您想将这些属性值存储在 Cognito 用户池配置文件之外,例如您自己的 DynamoDB 表,您可以在池中配置一个 PreSignUp trigger,它将在所有新用户创建时调用。您可以将此触发器中的用户属性导出到您选择的任何数据库。

希望这会有所帮助。

【讨论】:

【参考方案3】:

AWS AppSync 允许您访问 GraphQL 解析器中的信息,您可以选择将这些信息存储在 DynamoDB 表中。对于来自 Facebook 个人资料的数据,您可以将其作为参数传递给 GraphQL 突变或在标头中传递给 AppSync,然后您可以通过 $ctx.request.headers.NAME 在解析器中访问,其中 NAME 是您的标头名称。然后,您可以简单地选择要为该用户写入 DynamoDB 的哪些属性作为突变的一部分。更多信息在参考指南中:https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html

由于您还要求先检查用户是否已在 DDB 中,因此您可以先进行存在性检查:


  "version": "2017-02-28",
  "operation": "PutItem",
  "key": 
    "userId": $util.dynamodb.toDynamoDBJson($ctx.identity.username),
  ,
  "attributeValues": $util.dynamodb.toMapValuesJson($ctx.args.input),
  "condition": 
    "expression": "attribute_not_exists(userId)"
  ,

这会根据 Cognito 用户池中的用户名进行检查。如果您使用的是 Cognito Federated Identities 功能,它将是 ctx.identity.cognitoIdentityId。如果记录已经存在,则返回的响应将告诉您这意味着用户已经存在。您还可以通过使用条件语句查看 $ctx.result 并从头构建 JSON 响应或使用上述指南中的 $util.error() 方法之一来转换响应映射模板中返回的消息。

最后,正如您提到的,您将拥有公开的个人资料数据,您可能希望在某些记录上对此进行标记以进行控制。在 AWS AppSync 中,您可以过滤有关授权元数据的 GraphQL 响应,例如。您只需在 DynamoDB 记录上拥有一个标记为“公共”或“私有”的属性(即列)。那么您的响应模板将如下所示:

#if($context.result.public == 'yes')
    $utils.toJson($context.result)
#else
    $utils.unauthorized()
#end

您可以在此处查看更多示例:https://docs.aws.amazon.com/appsync/latest/devguide/security-authorization-use-cases.html#public-and-private-records

【讨论】:

以上是关于在 DynamoDB 中保存 AWS Cognito 用户的主要内容,如果未能解决你的问题,请参考以下文章

在AWS s3中保存图像

如何检查然后更新node.js中的AWS dynamoDB项?

DynamoDB 如何使用 AWS KMS

将dynamoDB表复制到另一个没有S3的aws帐户

使用 Data Pipeline 在 AWS 中进行批处理文件

如何使用Lambda从Amazon AWS中提取和转换单个dynamodb元素