Closed LoopIssuer closed 1 year ago
Hi @TomaszWozniakMosina,
Good morning.
Please have a look at the code in comment https://github.com/aws/aws-sdk-net-extensions-cognito/issues/35#issuecomment-712406376 for guidance. The _cognitoCredentials.Secret
in your code should be pointing to the value of secret configured in App Client.
(Just FYI, I do not see you using secretHash
, so that might be redundant)
Thanks, Ashish
Hi @ashishdhingra Good morning. Thanks for your reply. However, when I use the code form https://github.com/aws/aws-sdk-net-extensions-cognito/issues/35#issuecomment-712406376 I still get error: SecretHash does not match for the client: xxxxxxxxxxxxxxxxxxx.
I tried use SecretHash computed and not computed with the below method - always get same error.
private string GetSecretHash(string value)
{
var key = _cognitoCredentials.Secret;
using (var hmacsha256 = new HMACSHA256(Encoding.UTF8.GetBytes(key)))
{
var hash = hmacsha256.ComputeHash(Encoding.UTF8.GetBytes(value));
return Convert.ToBase64String(hash);
}
}
@TomaszWozniakMosina I'm unsure what you are doing wrong. The below customized code works properly (using Amazon.Extensions.CognitoAuthentication 2.2.3
on .NET Framework 4.8
):
NOTE: The code below uses FallbackRegionFactory.GetRegionEndpoint()
to determine region. You might want to set region value instead if the region is not configured in the default profile chain.
using Amazon;
using Amazon.CognitoIdentityProvider;
using Amazon.Extensions.CognitoAuthentication;
using Amazon.Runtime;
using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace CognitoRefreshTokenTest
{
internal class Program
{
private static string userPoolId;
private static string clientId;
private static string clientSecret;
const int BufferSize = 10000;
static void Main(string[] args)
{
Console.SetIn(new StreamReader(Console.OpenStandardInput(), Encoding.UTF8, false, BufferSize));
Console.Write("Enter User Pool ID: ");
userPoolId = Console.ReadLine();
Console.Write("Enter Client ID: ");
clientId = Console.ReadLine();
Console.Write("Enter Client Secret: ");
clientSecret = Console.ReadLine();
bool reexecuteFlow = false;
do
{
Console.Write("User Name: ");
string userName = Console.ReadLine();
while (string.IsNullOrWhiteSpace(userName))
{
Console.Write("Please enter a valid User Name: ");
userName = Console.ReadLine();
}
Console.Write("Do you have a Refresh Token (Y/N): ");
char hasRefreshTokenResponse = Convert.ToChar(Console.ReadLine());
bool hasRefreshToken = (char.ToLower(hasRefreshTokenResponse) == 'y');
Console.WriteLine();
string passwordOrRefreshToken;
if (!hasRefreshToken)
{
Console.Write("Password: ");
passwordOrRefreshToken = Console.ReadLine();
while (string.IsNullOrWhiteSpace(passwordOrRefreshToken))
{
Console.Write("Please enter a valid Password: ");
passwordOrRefreshToken = Console.ReadLine();
}
}
else
{
Console.Write("Existing Refresh Token: ");
passwordOrRefreshToken = Console.ReadLine();
while (string.IsNullOrWhiteSpace(passwordOrRefreshToken))
{
Console.Write("Please enter a valid Refresh Token: ");
passwordOrRefreshToken = Console.ReadLine();
}
}
Console.WriteLine("\nExecuting {0} auth flow.", (hasRefreshToken ? "Refresh Token" : "Username/Password"));
AuthFlowResponse authFlowResponse = (hasRefreshToken ? GetCredsFromRefreshAsync(userName, passwordOrRefreshToken).GetAwaiter().GetResult() : GetCredentials(userName, passwordOrRefreshToken).GetAwaiter().GetResult());
Console.WriteLine("ID Token: {0}\nAccess Token {1}\nRefresh Token: {2}", authFlowResponse.AuthenticationResult.IdToken, authFlowResponse.AuthenticationResult.AccessToken, authFlowResponse.AuthenticationResult.RefreshToken);
Console.Write("\n\nRe-execute Flow (Y/N): ");
char reexecuteFlowResponse = Convert.ToChar(Console.ReadLine());
reexecuteFlow = (char.ToLower(reexecuteFlowResponse) == 'y');
} while (reexecuteFlow);
}
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, clientSecret);
var user = new CognitoUser(userName, clientId, userPool, provider, clientSecret);
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, clientSecret);
CognitoUser user = new CognitoUser(userName, clientId, userPool, provider, clientSecret);
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);
}
}
}
Output:
Enter User Pool ID: us-east-2_<<removed>>
Enter Client ID: 22<<removed>>
Enter Client Secret: gu8m<<removed>>
User Name: testuser
Do you have a Refresh Token (Y/N): n
Password: 14@Dec@1983
Executing Username/Password auth flow.
ID Token: eyJraWQiOiJ6cG9HODdOOHQ4XC9mMFp6cE<<removed>>
Access Token eyJraWQiOiI5Z0I4dzRUNFdrMWRMdThcL2U0<<removed>>
Refresh Token: eyJjdHkiOiJKV1QiLCJlbmMiOiJB<<removed>>
Re-execute Flow (Y/N):
y
User Name: testuser
Do you have a Refresh Token (Y/N): y
Existing Refresh Token: eyJjdHkiOiJKV1QiLCJlbmMiOiJB<<removed>>
Executing Refresh Token auth flow.
ID Token: eyJraWQiOiJ6cG9HODdOOHQ4XC9mMFp6cEJySVFXa<<removed>>
Access Token eyJraWQiOiI5Z0I4dzRUNFdrMWRMdThcL2U0THJsVGN<<removed>>
Refresh Token: eyJjdHkiOiJKV1QiLCJlbmMiOiJB<<removed>>
Re-execute Flow (Y/N):
You need to use the value of client secret configured in App Client from Cognito user pool console (refer below as an example):
Thanks, Ashish
This issue has not received a response in 5 days. If you want to keep this issue open, please just leave a comment below and auto-close will be canceled.
Describe the bug
Hi, I had an issue when trying to use RefreshToken flow. I get error: NotAuthorizedException: SecretHash does not match for the client: xxxxxxxxxxxxxxxxxxx I tried: -using secret directly -using GetSecretHash with userName, userEmail, USerID, User Sub Id Always the same issue.
I'm trying:
Also tried with the same result:
Please help.
Expected Behavior
Get Refresh Token without error: NotAuthorizedException: SecretHash does not match for the client
Current Behavior
Cannot get Refresh Token, error occurs: NotAuthorizedException: SecretHash does not match for the client
Reproduction Steps
Use this code:
Possible Solution
Please give me information, what is wrong with my code, or maybe there is some bug?
Additional Information/Context
No response
AWS .NET SDK and/or Package version used
Amazon.Extensions.CognitoAuthentication 2.2.1 Unity 2021.3.9f1
Targeted .NET Platform
.Net 4.x
Operating System and version
Windows 11