-
Notifications
You must be signed in to change notification settings - Fork 50
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
Comments
Thanks for letting us know. I'll take a look at what the code is doing. |
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
|
@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? |
Same problem here, I need to update the RefreshToken, but after doing |
Same problem for me. After |
any update on this? |
Amazon doesn't seem to give a single s* on that problem submitted 2.5 years ago |
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. |
Reproducible using the following code (examine 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> |
This is the root cause for aws/aws-aspnet-cognito-identity-provider#144 |
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.. |
|
|
Given following code example:
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 theAuthenticationResult
does not return any RefreshToken.The text was updated successfully, but these errors were encountered: