- Newest
- Most votes
- Most comments
The issue you're experiencing with the SecretHash not matching during the refresh token flow, despite working correctly during sign-in, is likely due to how you're calculating the SecretHash for the refresh token request.
In your refresh_token function, you're calculating the SecretHash using only the email and client ID. However, for the REFRESH_TOKEN_AUTH flow, the SecretHash should be calculated differently.
For the refresh token flow, you should use the USERNAME parameter in place of the email when calculating the SecretHash. The USERNAME in this case should be the actual username of the user, which might be different from their email address depending on how your user pool is configured.
To fix this, you should modify your refresh_token function to calculate the SecretHash using the username instead of the email. You may need to retrieve the username associated with the refresh token before making the refresh token request.
Additionally, make sure that you're including the CLIENT_ID in your AuthParameters for the refresh token request. Your current implementation doesn't include it, which might also contribute to the error.
Here's a suggested modification to your refresh_token function:
async def refresh_token(self, username: str, refresh_token: str): try: secret_hash = self.calculate_secret_hash(username) response = self.cognito_client.initiate_auth( AuthFlow='REFRESH_TOKEN_AUTH', AuthParameters={ 'REFRESH_TOKEN': refresh_token, 'SECRET_HASH': secret_hash, 'USERNAME': username, 'CLIENT_ID': settings.cognito_client_id }, ClientId=settings.cognito_client_id, ) return { "access_token": response["AuthenticationResult"]["AccessToken"], "id_token": response["AuthenticationResult"]["IdToken"] } except ClientError as refresh_error: return refresh_error
Note that the refresh token flow typically doesn't return a new refresh token, so you may want to remove that from your return statement.
By making these changes, you should be able to resolve the SecretHash mismatch error during the refresh token flow.
Sources
Unable to sign-in (SecretHash does not match for the client) | AWS re:Post
Understanding the refresh token - Amazon Cognito
answered 2 years ago
Currently, in my sign-in request, I return the AccessToken, RefreshToken, and IDToken to the frontend. I assumed that when the AccessToken expires, the frontend would send me the RefreshToken, and I could generate a new AccessToken using the RefreshToken and the email address.
From your response, it seems that I also need the username/sub for the refresh token flow to work correctly. Does this mean I need to include the username/sub in the response to the frontend during the sign-in flow so it can send it back to me during the refresh process like code below?
async def signin(self, data: SignInRequest):
try:
secret_hash = self.calculate_secret_hash(data.email)
response = self.cognito_client.initiate_auth(
AuthFlow="USER_PASSWORD_AUTH",
AuthParameters={
"USERNAME": data.email,
"PASSWORD": data.password,
"SECRET_HASH": secret_hash
},
ClientId=settings.cognito_client_id
)
access_token = response["AuthenticationResult"]["AccessToken"]
id_token = response["AuthenticationResult"]["IdToken"]
refresh_token = response["AuthenticationResult"]["RefreshToken"]
user_sub = self.get_user_sub(access_token)
return {
"access_token": access_token,
"id_token": id_token,
"refresh_token": refresh_token,
"sub": user_sub
}
except ClientError as e:
raise HTTPException(status_code=401, detail=f"Authentication failed: {str(e)}")
Or is there another way to retrieve the username/sub during the refresh token flow without requiring the frontend to store and resend it?
answered 2 years ago
Relevant content
asked 3 years ago
- AWS OFFICIALUpdated 4 years ago
- AWS OFFICIALUpdated 4 months ago
