Cognito用户池:如何使用刷新令牌刷新访问令牌

Har*_*hah 38 amazon-web-services amazon-cognito aws-lambda

我正在使用Cognito用户池来验证系统中的用户.成功的身份验证提供ID令牌(JWT),访问令牌(JWT)和刷新令牌.这里的文档http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html明确提到刷新令牌可以是用于刷新访问令牌,但没有提到如何.我的问题是,一旦我的访问令牌过期,我如何使用存储的刷新令牌再次刷新我的访问令牌?

我搜索了javascript sdk,找不到任何方法来做同样的事情.我绝对错过了什么.

此外,我通过Lambda函数考虑这一点,该函数接收访问令牌并刷新令牌并使用刷新的访问令牌进行响应.如果有人能对此有所启发,那将会很棒.

谢谢

afi*_*ert 33

如果您处于Cognito Javascript SDK不能用于您的目的的情况下,您仍然可以看到它如何处理SDK源中的刷新过程:

您可以看到refreshSession,Cognito InitiateAuth端点是使用REFRESH_TOKEN_AUTHset的AuthFlow值调用的,而对象是作为AuthParameters值传入的.

需要配置该对象以满足用户池的需要.具体而言,SECRET_HASH如果您的目标App客户端ID具有关联的App客户端密钥,则可能必须传入.创建用于Javascript SDK的用户池客户端应用程序当前不能包含客户端密钥,因此SECRET_HASH不需要连接它们.

另一个可能引发循环的警告是,如果您的用户池设置为记住设备,并且您没有传入DEVICE_KEY您的REFRESH_TOKEN.Cognito API当前返回"无效刷新令牌"错误,如果您传入的是RefreshToken没有传入您的DeviceKey.即使您传入有效内容,也会返回此错误RefreshToken.上面链接的线程说明了这一点,尽管我希望AWS更新其错误处理,以便在将来不那么神秘.

由于在该线程的讨论,如果你正在使用AdminInitiateAuth沿ADMIN_NO_SRP_AUTH,你的成功认证的响应有效负荷当前不包含NewDeviceMetadata; 这意味着DeviceKey当您尝试刷新令牌时,您将无法传入任何内容.

我的应用程序要求在Python中实现,所以这里有一个对我有用的示例:

def refresh_token(self, username, refresh_token):
    try:
        return client.initiate_auth(
            ClientId=self.client_id,
            AuthFlow='REFRESH_TOKEN_AUTH',
            AuthParameters={
                'REFRESH_TOKEN': refresh_token,
                'SECRET_HASH': self.get_secret_hash(username)
                # Note that SECRET_HASH is missing from JSDK
                # Note also that DEVICE_KEY is missing from my example
            }
        )
    except botocore.exceptions.ClientError as e:
        return e.response
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢@afilbert提供的信息.我没有在DEVICE_KEY中传递,而且我收到了"无效刷新令牌"错误,这在AWS端是一个非常糟糕的错误处理. (4认同)
  • @nueverest如果已经使用"App client secret"定义了用户池应用程序,那么`SECRET_HASH`是*必需*,但它们不是同一个东西.boto3文档将`SecretHash`描述如下:"使用用户池客户端的密钥和用户名加上消息中的客户端ID计算的密钥哈希消息认证码(HMAC)." http://boto3.readthedocs.io/en/latest/reference/services/cognito-idp.html#CognitoIdentityProvider.Client.sign_up如果您在SO上发布关于如何创建SECRET_HASH的问题,我会非常高兴分享我的解决方案作为答案. (3认同)
  • 不错的答案,@ afilbert-赞成。(不幸的是,几年前,SO用户开始像个人花钱一样对待票。;) (2认同)
  • 非常感谢您提供有关设备密钥的指针!(我禁用了设备跟踪,它再次正常工作)。 (2认同)

小智 20

Javascript sdk在内部处理令牌的刷新.当您调用"getSession"获取令牌时,如果没有任何有效的缓存访问权限和ID令牌,SDK将使用刷新令牌获取新的访问权限和ID令牌.它调用用户身份验证,只有当刷新令牌也过期时,才需要用户提供用户名和密码.

此致,马赫什

  • Mahesh,你能在那里给出代码示例吗? (2认同)

Gau*_*ain 12

如果您有刷新令牌,那么您只需向 Cognito 发出这个简单的 POST 请求即可获取新的访问令牌和 id 令牌:

POST https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/token >
Content-Type='application/x-www-form-urlencoded'
Authorization=Basic base64(client_id + ':' + client_secret)

grant_type=refresh_token&
client_id=YOUR_CLIENT_ID&
refresh_token=YOUR_REFRESH_TOKEN
Run Code Online (Sandbox Code Playgroud)

您将收到以下回复:

HTTP/1.1 200 OK
Content-Type: application/json

{
   "access_token":"eyJz9sdfsdfsdfsd", 
   "id_token":"dmcxd329ujdmkemkd349r",
   "token_type":"Bearer", 
   "expires_in":3600
}
Run Code Online (Sandbox Code Playgroud)

请记住,授权标头应包含上述计算出的 base64。

  • 如果它确实返回“refresh_token”,这将是一个简洁的解决方案,但事实并非如此。您提供的示例来自 AWS 文档 (https://docs.aws.amazon.com/cognito/latest/developerguide/token-endpoint.html),但他们还提供了注释: **刷新令牌在规范,但当前尚未实现从令牌端点返回。** (3认同)
  • 认为已经改变了:)仅当 grant_type 为authorization_code 时,令牌端点才返回refresh_token。 (2认同)

pis*_*ado 7

使用amazon-cognito-identity-js浏览器SDK刷新会话; 它主要是为你做的,除非你做一些不寻常的事情,否则你不需要直接处理刷新令牌.这是你需要知道的:

假设您已经像这样实例化了用户池:

const userPool = new AmazonCognitoIdentity.CognitoUserPool({
  UserPoolId: USER_POOL_ID,
  ClientId: USER_POOL_CLIENT_ID
});
Run Code Online (Sandbox Code Playgroud)

要查找经过身份验证的最后一个用户名,您可以这样做:

const cognitoUser = cognitoUserPool.getCurrentUser();
Run Code Online (Sandbox Code Playgroud)

如果找到一个,cognitoUser将为非null,您可以执行此操作,如果需要,将在幕后刷新您的令牌:

cognitoUser.getSession(function(err, data) {
  if (err) {
    // Prompt the user to reauthenticate by hand...
  } else {
    const cognitoUserSession = data;
    const yourIdToken = cognitoUserSession.getIdToken().jwtToken;
    const yourAccessToken = cognitoUserSession.getAccessToken().jwtToken;
  }
});
Run Code Online (Sandbox Code Playgroud)

如果您不希望这些令牌持久存储在本地存储中,您可以:

cognitoUser.signOut();
Run Code Online (Sandbox Code Playgroud)

它的工作方式是,在成功验证后,浏览器将存储您的JWT令牌,包括该刷新令牌.默认情况下,它会将这些存储在浏览器的本地存储中,但您可以根据需要提供自己的存储对象.默认情况下,刷新令牌在30d内有效,但它是UserPoolClient的属性(RefreshTokenValidity),您可以更改该属性.当你执行上述操作时,getSession()将首先查看存储中的令牌是否存在且仍然有效; 如果没有,它将尝试使用它在那里找到的任何refreshToken来验证你进入一个新的会话.

文档http://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html表示iOS和Android SDK将执行此操作你,虽然我没有使用那些,所以不能担保.


Gru*_*Man 6

我在 Javascript 中也一直在努力解决这个问题。这是我的解决方案,它基于https://github.com/aws/amazon-cognito-identity-js但它不依赖于存储,因此您可以根据需要在 lambda 函数中使用它。编辑:固定代码,感谢蜡笔

const userPool = new AWSCognito.CognitoUserPool({
  UserPoolId: <COGNITO_USER_POOL>,
  ClientId: <COGNITO_APP_ID>
})

userPool.client.makeUnauthenticatedRequest('initiateAuth', {
  ClientId: <COGNITO_APP_ID>,
  AuthFlow: 'REFRESH_TOKEN_AUTH',
  AuthParameters: {
    'REFRESH_TOKEN': <REFRESH_TOKEN> // client refresh JWT
  }
}, (err, authResult) => {
  if (err) {
     throw err
  }
  console.log(authResult) // contains new session
})
Run Code Online (Sandbox Code Playgroud)


Ric*_*ick 5

以下是如何使用 Node.js 在服务器端使用 JavaScript 来完成此操作的示例。

const AccessToken = new CognitoAccessToken({ AccessToken: tokens.accessToken });
const IdToken = new CognitoIdToken({ IdToken: tokens.idToken });
const RefreshToken = new CognitoRefreshToken({ RefreshToken: tokens.refreshToken });

const sessionData = {
  IdToken: IdToken,
  AccessToken: AccessToken,
  RefreshToken: RefreshToken
};
const userSession = new CognitoUserSession(sessionData);

const userData = {
  Username: email,
  Pool: this.userPool
};

const cognitoUser = new CognitoUser(userData);
cognitoUser.setSignInUserSession(userSession);

cognitoUser.getSession(function (err, session) { // You must run this to verify that session (internally)
  if (session.isValid()) {
    // Update attributes or whatever else you want to do
  } else {
    // TODO: What to do if session is invalid?
  }
});
Run Code Online (Sandbox Code Playgroud)

您可以在我的博客文章如何使用 Cognito 使用令牌对用户进行身份验证中查看完整的工作示例。