2

我正在处理用户在使用后没有明确退出 Web 应用程序的问题,这对于用例来说不够安全。它是一个带有 AWS Amplify 和 Cognito 的 React 应用程序。

我计划通过跟踪数据库中的会话来做到这一点(我可以使用在 PostAuthentication_Authentication 或 TokenGeneration_RefreshTokens 事件上用 Go 编写的 Cognito Lambda 触发器捕获会话的开始或刷新),并在一段时间不活动后使用 GlobalSignOut 使会话到期,但在为了在会话放弃时使用户刷新令牌无效,我需要访问令牌,它似乎只对客户端可用。

我可以在从 Web 客户端登录时显式获取此信息,然后使用 GraphQL 将其发布回数据库进行记录,但令我惊讶的是,它在发送到 Lambda 事件触发器的 Cognito 有效负载中不可用。如果在持续使用应用程序一小时后刷新,我也不确定如何在客户端上获取刷新的令牌,而不会增加应用程序中的每次更改的开销。

如果您在客户端上使用 Amplify 进行身份验证流程,是否可以从服务器端进程(如 Lambda 函数)请求 Cognito 用户的当前访问令牌?我在 cognitoidentityprovider 中看不到任何允许我检索访问令牌的内容,但显然需要使用 GlobalSignOut。

4

2 回答 2

2

您可以将授权代码流与 PKCE 一起使用,以便客户端仅暴露于代码,然后使用 cognito 用户池/id 令牌、访问令牌和刷新令牌的令牌端点在服务器端交换该代码。您可以将用户池令牌返回给客户端,因为它将在一小时后过期,同时将刷新令牌保留在服务器端的会话管理器中,允许您根据需要获取新令牌或根据您的要求使会话无效。

https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html

于 2020-07-23T03:18:02.083 回答
1

我找到了一个不涉及获取访问令牌服务器端的可行解决方案。我们使用 AppSync for GraphQL - 访问令牌作为授权标头与每个 GraphQL 请求一起传递,并且可以在请求模板中访问,如下所示:

#set( $myMap = {
    "field": "${field}",
    "user_id": $context.identity.sub,
    "source_ip": $context.identity.sourceIp,
    "arguments":  $context.arguments,
    "access_token": $context.request.headers.authorization
} )
{
    "version" : "2017-02-28",
    "operation": "Invoke",
    "payload": $util.toJson($myMap)
}

在每个 Lambda 解析器中,我只是在遇到访问令牌时缓存访问令牌,以便我始终拥有当前用户的最新访问令牌。然后,我的计划会话管理器功能从缓存中检索它检测到的任何用户的访问令牌,并可以将其用作 GlobalSignOut 的输入。

于 2020-07-21T22:44:56.013 回答