Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cognito StartWithRefreshTokenAuthAsync Deletes RefreshToken #22

Closed
mmlac opened this issue Oct 19, 2017 · 14 comments · Fixed by #63
Closed

Cognito StartWithRefreshTokenAuthAsync Deletes RefreshToken #22

mmlac opened this issue Oct 19, 2017 · 14 comments · Fixed by #63
Assignees
Labels

Comments

@mmlac
Copy link

mmlac commented Oct 19, 2017

Given following code example:

            usr = new CognitoUser(username, AWS_CLIENT_ID, AwsUserPool, AwsIdpClient)
            {
                SessionTokens = new CognitoUserSession(
                                               null, null, refreshToken, 
                                              DateTime.Now, DateTime.Now.AddDays(3))
            };

                AuthFlowResponse context = await usr.StartWithRefreshTokenAuthAsync(
                    new InitiateRefreshTokenAuthRequest() { AuthFlowType = AuthFlowType.REFRESH_TOKEN }
                    ).ConfigureAwait(false);

Expected Outcome:
usr.SessionTokens is fully populated, including the (still valid) Refresh Token.

Actual Outcome:
usr.SesisonTokens is populated with new accessToken, ExpirationTime, IdToken and IssuedTime, but the RefreshToken is null. It needs to keep the Refresh Token supplied as the AuthenticationResult does not return any RefreshToken.

@normj
Copy link
Member

normj commented Oct 23, 2017

Thanks for letting us know. I'll take a look at what the code is doing.

@mmlac
Copy link
Author

mmlac commented Oct 26, 2017

The response does not contain a refresh token, but the code sets the SessionTokens object with every value returned from Cognito, so the refresh token will be set to null. Either the request needs to return the supplied refresh token / a new refresh token, or the Auth Flow needs to be taken into account and another check has to be added, like

if (AuthFlowType != REFRESH_TOKEN && 
    AuthFlowType != REFRESH_TOKEN_AUTH) 
{
    SessionTokens.RefreshToken = response.refreshToken
} else
{
    SessionTokens.RefreshToken = request.SessionTokens.RefreshToken
}

@sstevenkang sstevenkang self-assigned this Feb 2, 2018
@berniezhao11
Copy link

@mmlac But even with this conditional check, the refresh token was not updated, it still returns the token from the request? Does that mean it will expire in 30 days no matter what?

@normj normj transferred this issue from aws/aws-sdk-net Jan 3, 2019
@daniel-rck
Copy link

Same problem here, I need to update the RefreshToken, but after doing user.StartWithRefreshTokenAuthAsync(request) the RefreshToken is null.

@iTKerry
Copy link

iTKerry commented Jun 24, 2019

Same problem for me. After user.StartWithRefreshTokenAuthAsync(request) the RefreshToken is null

@ezexe
Copy link

ezexe commented Sep 5, 2019

any update on this?

@chingham
Copy link

Amazon doesn't seem to give a single s* on that problem submitted 2.5 years ago

@NGL321 NGL321 added bug This issue is a bug. module/cognito-ext needs-triage This issue or PR still needs to be triaged. labels Aug 7, 2020
@dcolclazier
Copy link

From my experience using these services, the reason it is null is because it does not change. Yes, they could return the same refresh key that was given, but this isn't necessarily required. The only time a refresh token is created/refreshed is when logging in via username and password. As such, when calling StartWithSrpAuthAsync and providing valid credentials, you do get a valid refresh token back.

@ashishdhingra
Copy link
Contributor

ashishdhingra commented Oct 13, 2020

Reproducible using the following code (examine user object before returning from GetCredsFromRefreshAsync, RefreshToken is set to null):

using System;
using System.Threading.Tasks;
using Amazon;
using Amazon.CognitoIdentityProvider;
using Amazon.Extensions.CognitoAuthentication;
using Amazon.Runtime;

namespace CognitoStartWithRefreshTokenAuthAsync
{
    class Program
    {
        private static string userPoolId = "<UserPoolID>";
        private static string clientId = "<AppClientID>";
        private static RegionEndpoint regionEndpoint = RegionEndpoint.USEast2; // Set it as per User Pool region.

        static void Main(string[] args)
        {
            Console.WriteLine("User Name: ");
            string userName = Console.ReadLine();
            while (string.IsNullOrWhiteSpace(userName))
            {
                Console.WriteLine("Please enter a valid User Name.");
                userName = Console.ReadLine();
            }

            Console.WriteLine("Do you have a Refresh Token (Y/N): ");
            char hasRefreshTokenResponse = Convert.ToChar(Console.Read());
            bool hasRefreshToken = (char.ToLower(hasRefreshTokenResponse) == 'y');
            Console.WriteLine();

            Console.WriteLine("Password: ");
            string password = Console.ReadLine();
            while (string.IsNullOrWhiteSpace(password) && !hasRefreshToken)
            {
                Console.WriteLine("Please enter a valid Password.");
                password = Console.ReadLine();
            }

            Console.WriteLine("Existing Refresh Token: ");
            string refreshToken = Console.ReadLine();
            while (string.IsNullOrWhiteSpace(refreshToken) && hasRefreshToken)
            {
                Console.WriteLine("Please enter a valid Refresh Token.");
                refreshToken = Console.ReadLine();
            }

            AuthFlowResponse authFlowResponse = (!string.IsNullOrWhiteSpace(refreshToken) ? GetCredsFromRefreshAsync(userName, refreshToken).GetAwaiter().GetResult() : GetCredentials(userName, password).GetAwaiter().GetResult());
        }

        public static async Task<AuthFlowResponse> GetCredentials(string userName, string password)
        {
            var provider = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), FallbackRegionFactory.GetRegionEndpoint());
            var userPool = new CognitoUserPool(userPoolId, clientId, provider);
            var user = new CognitoUser(userName, clientId, userPool, provider);

            AuthFlowResponse authResponse = await user.StartWithSrpAuthAsync(new InitiateSrpAuthRequest()
            {
                Password = password
            }).ConfigureAwait(false);

            while (authResponse.AuthenticationResult == null)
            {
                if (authResponse.ChallengeName == ChallengeNameType.NEW_PASSWORD_REQUIRED)
                {
                    Console.WriteLine("Enter your desired new password: ");
                    string newPassword = Console.ReadLine();

                    authResponse = await user.RespondToNewPasswordRequiredAsync(new RespondToNewPasswordRequiredRequest()
                    {
                        SessionID = authResponse.SessionID,
                        NewPassword = newPassword
                    });
                }
                else if (authResponse.ChallengeName == ChallengeNameType.SMS_MFA)
                {
                    Console.WriteLine("Enter the MFA Code sent to your device: ");
                    string mfaCode = Console.ReadLine();

                    authResponse = await user.RespondToSmsMfaAuthAsync(new RespondToSmsMfaRequest()
                    {
                        SessionID = authResponse.SessionID,
                        MfaCode = mfaCode

                    }).ConfigureAwait(false);
                }
                else
                {
                    Console.WriteLine("Unrecognized authentication challenge.");
                    return null;
                }
            }

            return authResponse;
        }

        public static async Task<AuthFlowResponse> GetCredsFromRefreshAsync(string userName, string refreshToken)
        {
            AmazonCognitoIdentityProviderClient provider = new AmazonCognitoIdentityProviderClient(new AnonymousAWSCredentials(), FallbackRegionFactory.GetRegionEndpoint());
            CognitoUserPool userPool = new CognitoUserPool(userPoolId, clientId, provider);

            CognitoUser user = new CognitoUser(userName, clientId, userPool, provider);

            user.SessionTokens = new CognitoUserSession(null, null, refreshToken, DateTime.Now, DateTime.Now.AddHours(1));

            InitiateRefreshTokenAuthRequest refreshRequest = new InitiateRefreshTokenAuthRequest()
            {
                AuthFlowType = AuthFlowType.REFRESH_TOKEN_AUTH
            };

            return await user.StartWithRefreshTokenAuthAsync(refreshRequest).ConfigureAwait(false);
        }
    }
}

Contents of .csproj:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="AWSSDK.Extensions.CognitoAuthentication" Version="0.9.4" />
  </ItemGroup>
</Project>

@ashishdhingra
Copy link
Contributor

This is the root cause for aws/aws-aspnet-cognito-identity-provider#144

@ashishdhingra
Copy link
Contributor

As per Amazon Cognito User Pools Auth API Reference > TOKEN Endpoint, there is a NOTE that The token endpoint returns refresh_token only when the grant_type is authorization_code..

@github-actions
Copy link

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

@ashishdhingra ashishdhingra reopened this Dec 28, 2020
@ashishdhingra
Copy link
Contributor

@github-actions
Copy link

⚠️COMMENT VISIBILITY WARNING⚠️

Comments on closed issues are hard for our team to see.
If you need more assistance, please either tag a team member or open a new issue that references this one.
If you wish to keep having a conversation with other community members under this issue feel free to do so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet