Refresh user cookie ticket in ASP.Net Core Identity

后端 未结 2 765
日久生厌
日久生厌 2020-12-05 12:11

In a controller in an ASP.NET Core web application I want to refresh the user and claims in the cookie ticket stored on the client.

The client is authenticated and a

2条回答
  •  北荒
    北荒 (楼主)
    2020-12-05 12:46

    This is also possible if the user is already logged out (their access token has expired but their refresh token is still valid).

    Important note: the following only works if you have "Do you want to remember your user's devices?" set to "No" in the cognito config. If anyone knows how to get it to work with it on, please let me know.

    We use the following flow (js client app connecting to .NET Core API):

    1. User signs in using username/password (CognitoSignInManager.PasswordSignInAsync)
    2. The client receives the token, userID, and refreshToken and stores them in localStorage.
    3. When the original token expires (1 hour), the client gets a 401 error from the API.
    4. The client calls another API endpoint with the userID and refreshToken which then in turn calls the code below on our user service.
    5. If the refresh result is successful, we return the new token (AuthenticationResult.IdToken).
    6. The client the repeats the call that originally errored in a 401 with the new token.

    Here is the code we added to the User Service:

    public async Task SignInRefreshAsync(string uid, string refreshToken)
    {
        try
        {
            var result = await _cognitoIdentityProvider.InitiateAuthAsync(
                new InitiateAuthRequest
                {
                    AuthFlow = AuthFlowType.REFRESH_TOKEN_AUTH,
                    ClientId = _pool.ClientID,
                    AuthParameters = new Dictionary
                    {
                        { "REFRESH_TOKEN", refreshToken },
                        { "SECRET_HASH", HmacSHA256(uid + _pool.ClientID, _options.UserPoolClientSecret) }
                    }
                });
    
            if (!result.HttpStatusCode.Successful() || string.IsNullOrEmpty(result.AuthenticationResult?.IdToken))
                return new UserLoginResult(UserLoginStatus.Failed);
    
            return new UserLoginResult(UserLoginStatus.Success, uid, null, null, result.AuthenticationResult.IdToken, null);
        }
        catch
        {
            return new UserLoginResult(UserLoginStatus.Failed);
        }
    }
    
    private static string HmacSHA256(string data, string key)
    {
        using (var sha = new System.Security.Cryptography.HMACSHA256(System.Text.Encoding.UTF8.GetBytes(key)))
        {
            var result = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(data));
            return Convert.ToBase64String(result);
        }
    }
    

    IAmazonCognitoIdentityProvider _cognitoIdentityProvider is resolved from DI.

    AWSCognitoClientOptions _options = configuration.GetAWSCognitoClientOptions(); and IConfiguration configuration is also resolved from DI.

    UserLoginResult is our class to hold the token and refresh token. Obviously, adjust accordingly.

    Please note that setting SECRET_HASH may not be required based on your config is Cognito.

提交回复
热议问题