Token are not refreshed automatically and causing unauthorised user using amplify v2
Opened this issue · 15 comments
Before opening, please confirm:
- I have searched for duplicate or closed issues and discussions.
Language and Async Model
Kotlin
Amplify Categories
Authentication
Gradle script dependencies
// Put output below this line
amplifyframeworkVersion = '2.21.1'
implementation "com.amplifyframework:core:$amplifyframeworkVersion"
implementation "com.amplifyframework:aws-auth-cognito:$amplifyframeworkVersion"
implementation "com.amplifyframework:aws-storage-s3:$amplifyframeworkVersion"
implementation "com.amazonaws:aws-android-sdk-appsync:$awsappsyncVersion"
Environment information
# Put output below this line
Please include any relevant guides or documentation you're referencing
Amplify v2 documentation
Describe the bug
We have setup following settings for our android client app in AWS
access token - 5 min
Id token - 5 min
Refresh token - 365 days
Reproduction steps (if applicable)
- Install the app
- Login into app using Amplify v2 signIn
- Wait for expiry of 5 min and keep app in foreground
- Refresh call from AWS amplify library is not happening. We are getting getting unauthorised exception as token refresh is not happening automatically
Code Snippet
No response
Log output
--------- beginning of crash
2024-09-19 18:51:19.762 21950-22003 amplify:aw...AuthPlugin V Auth State Change: NotConfigured(id=)
2024-09-19 18:51:19.768 21950-22032 amplify:aw...AuthPlugin V Auth State Change: ConfiguringAuth(id=)
2024-09-19 18:51:19.769 21950-22005 amplify:aw...AuthPlugin V InitAuthConfig Starting execution
2024-09-19 18:51:19.773 21950-22005 amplify:aw...AuthPlugin V Credential Store State Change: NotConfigured(id=)
2024-09-19 18:51:19.774 21950-22036 amplify:aw...AuthPlugin V Credential Store State Change: MigratingLegacyStore(id=)
2024-09-19 18:51:19.775 21950-22005 amplify:aw...AuthPlugin V MigrateLegacyCredentials Starting execution
2024-09-19 18:51:19.849 21950-22005 amplify:aw...AuthPlugin V MigrateLegacyCredentials Sending event LoadCredentialStore
2024-09-19 18:51:19.851 21950-22036 amplify:aw...AuthPlugin V Credential Store State Change: LoadingStoredCredentials(id=)
2024-09-19 18:51:19.852 21950-22005 amplify:aw...AuthPlugin V LoadCredentialStore Starting execution
2024-09-19 18:51:20.169 21950-22005 amplify:aw...AuthPlugin V LoadCredentialStore Sending event CompletedOperation
2024-09-19 18:51:20.193 21950-22036 amplify:aw...AuthPlugin V Credential Store State Change: Success(storedCredentials=UserAndIdentityPool(signedInData=SignedInData(userId=, username=, signedInDate=Thu Sep 19 18:42:30 GMT+05:30 2024, signInMethod=ApiBased(authType=USER_SRP_AUTH), cognitoUserPoolTokens=CognitoUserPoolTokens(idToken = eyJra***, accessToken = eyJra***, refreshToken = eyJjd***)), identityId=, credentials=AWSCredentials(accessKeyId =, secretAccessKey =, sessionToken =, expiration = 1726755640)))
2024-09-19 18:51:20.198 21950-22005 amplify:aw...AuthPlugin V MoveToIdleState Starting execution
2024-09-19 18:51:20.199 21950-22005 amplify:aw...AuthPlugin V MoveToIdleState Sending event MoveToIdleState
2024-09-19 18:51:20.200 21950-22036 amplify:aw...AuthPlugin V Credential Store State Change: Idle(id=)
2024-09-19 18:51:20.202 21950-22005 amplify:aw...AuthPlugin V InitAuthConfig Sending event ConfigureAuthentication
2024-09-19 18:51:20.204 21950-22032 amplify:aw...AuthPlugin V Auth State Change: ConfiguringAuthentication(authNState=NotConfigured(id=))
2024-09-19 18:51:20.206 21950-22005 amplify:aw...AuthPlugin V InitAuthNConfig Starting execution
2024-09-19 18:51:20.207 21950-22005 amplify:aw...AuthPlugin V InitAuthNConfig Sending event Configure
2024-09-19 18:51:20.209 21950-22032 amplify:aw...AuthPlugin V Auth State Change: ConfiguringAuthentication(authNState=Configured(id=))
2024-09-19 18:51:20.211 21950-22005 amplify:aw...AuthPlugin V ConfigureAuthN Starting execution
2024-09-19 18:51:20.213 21950-22005 amplify:aw...AuthPlugin V Credential Store State Change: Idle(id=)
2024-09-19 18:51:20.214 21950-22036 amplify:aw...AuthPlugin V Credential Store State Change: LoadingStoredCredentials(id=)
2024-09-19 18:51:20.215 21950-22005 amplify:aw...AuthPlugin V LoadCredentialStore Starting execution
2024-09-19 18:51:20.224 21950-22005 amplify:aw...AuthPlugin V LoadCredentialStore Sending event CompletedOperation
2024-09-19 18:51:20.225 21950-22036 amplify:aw...AuthPlugin V Credential Store State Change: Success(storedCredentials=DeviceData(deviceMetadata=com.amplifyframework.statemachine.codegen.data.DeviceMetadata$Empty@e38942f))
2024-09-19 18:51:20.226 21950-22005 amplify:aw...AuthPlugin V MoveToIdleState Starting execution
2024-09-19 18:51:20.227 21950-22005 amplify:aw...AuthPlugin V MoveToIdleState Sending event MoveToIdleState
2024-09-19 18:51:20.228 21950-22036 amplify:aw...AuthPlugin V Credential Store State Change: Idle(id=)
2024-09-19 18:51:20.230 21950-22005 amplify:aw...AuthPlugin V ConfigureAuthN Sending event InitializedSignedIn
2024-09-19 18:51:20.231 21950-22005 amplify:aw...AuthPlugin V ConfigureAuthN Sending event ConfiguredAuthentication
2024-09-19 18:51:20.232 21950-22032 amplify:aw...AuthPlugin V Auth State Change: ConfiguringAuthentication(authNState=SignedIn(signedInData=SignedInData(userId=, username=, signedInDate=Thu Sep 19 18:42:30 GMT+05:30 2024, signInMethod=ApiBased(authType=USER_SRP_AUTH), cognitoUserPoolTokens=CognitoUserPoolTokens(idToken = eyJra***, accessToken = eyJra***, refreshToken = eyJjd***)), deviceMetadata=com.amplifyframework.statemachine.codegen.data.DeviceMetadata$Empty@e38942f))
2024-09-19 18:51:20.235 21950-22032 amplify:aw...AuthPlugin V Auth State Change: ConfiguringAuthorization(authNState=SignedIn(signedInData=SignedInData(userId=, username=, signedInDate=Thu Sep 19 18:42:30 GMT+05:30 2024, signInMethod=ApiBased(authType=USER_SRP_AUTH), cognitoUserPoolTokens=CognitoUserPoolTokens(idToken = eyJra***, accessToken = eyJra***, refreshToken = eyJjd***)), deviceMetadata=com.amplifyframework.statemachine.codegen.data.DeviceMetadata$Empty@e38942f), authZState=NotConfigured(id=))
2024-09-19 18:51:20.236 21950-22005 amplify:aw...AuthPlugin V InitAuthZConfig Starting execution
2024-09-19 18:51:20.237 21950-22005 amplify:aw...AuthPlugin V InitAuthZConfig Sending event CachedCredentialsAvailable
2024-09-19 18:51:20.241 21950-22032 amplify:aw...AuthPlugin V Auth State Change: ConfiguringAuthorization(authNState=SignedIn(signedInData=SignedInData(userId=, username=, signedInDate=Thu Sep 19 18:42:30 GMT+05:30 2024, signInMethod=ApiBased(authType=USER_SRP_AUTH), cognitoUserPoolTokens=CognitoUserPoolTokens(idToken = eyJra***, accessToken = eyJra***, refreshToken = eyJjd***)), deviceMetadata=com.amplifyframework.statemachine.codegen.data.DeviceMetadata$Empty@e38942f), authZState=SessionEstablished(amplifyCredential=UserAndIdentityPool(signedInData=SignedInData(userId=3e69e6d1-5b03-4402-8698-9508cb9be45a, username=, signedInDate=Thu Sep 19 18:42:30 GMT+05:30 2024, signInMethod=ApiBased(authType=USER_SRP_AUTH), cognitoUserPoolTokens=CognitoUserPoolTokens(idToken = eyJra**, accessToken = eyJra***, refreshToken = eyJjd***)), identityId=, credentials=AWSCredentials(accessKeyId =, secretAccessKey =, sessionToken =, expiration = 1726755640))))
2024-09-19 18:51:20.242 21950-22005 amplify:aw...AuthPlugin V ConfigureAuthZ Starting execution
2024-09-19 18:51:20.242 21950-22005 amplify:aw...AuthPlugin V ConfigureAuthZ Sending event ConfiguredAuthorization
2024-09-19 18:51:20.245 21950-22032 amplify:aw...AuthPlugin V Auth State Change: Configured(authNState=SignedIn(signedInData=SignedInData(userId=, username=, signedInDate=Thu Sep 19 18:42:30 GMT+05:30 2024, signInMethod=ApiBased(authType=USER_SRP_AUTH), cognitoUserPoolTokens=CognitoUserPoolTokens(idToken = eyJra***, accessToken = eyJra***, refreshToken = eyJjd***)), deviceMetadata=com.amplifyframework.statemachine.codegen.data.DeviceMetadata$Empty@e38942f), authZState=SessionEstablished(amplifyCredential=UserAndIdentityPool(signedInData=SignedInData(userId=, username=, signedInDate=Thu Sep 19 18:42:30 GMT+05:30 2024, signInMethod=ApiBased(authType=USER_SRP_AUTH), cognitoUserPoolTokens=CognitoUserPoolTokens(idToken = eyJra***, accessToken = eyJra***, refreshToken = eyJjd***)), identityId=, credentials=AWSCredentials(accessKeyId =, secretAccessKey =, sessionToken =**, expiration = 1726755640))))
amplifyconfiguration.json
No response
GraphQL Schema
// Put your schema below this line
Additional information and screenshots
No response
@sharadsmhaske Thanks for submitting your issue, we'll work on reproducing the issue.
@sharadsmhaske is the token getting refreshed if you call Amplify.Auth.fetchAuthSession
?
@phantumcode Yes if we call it explicitly. Also logs attached here are when user is logged in, after 5 minute expiry, nothing happened.
@phantumcode FYI Same issue is there in iOS amplify version as well. Token are not refreshing automatically.
@sharadsmhaske Can you provide your amplify configuration file with sensitive details redacted as well a sample app/code that demonstrates your usage?
Also, what happens if you call fetchAuthSession with forceRefresh
option set to true?
@phantumcode I will provide it tomorrow the config file.
Also, what happens if you call fetchAuthSession with forceRefresh option set to true? - Same token is return after the expiry even if we set the force refresh when user sign in. We havent called after expiry as if we call after expiry with normal fetchauthsession also give fresh id token.
@phantumcode Adding the content of amplify configuration.json file below
{
"auth": {
"plugins": {
"awsCognitoAuthPlugin": {
"IdentityManager": {
"Default": {}
},
"CredentialsProvider": {
"CognitoIdentity": {
"Default": {
"PoolId": "",
"Region": ""
}
}
},
"CognitoUserPool": {
"Default": {
"PoolId": "",
"AppClientId": "",
"Region": ""
}
},
"S3TransferUtility": {
"Default": {
"Bucket": "",
"Region": ""
}
},
"Auth": {
"Default": {
"OAuth": {
"WebDomain": “”,
"AppClientId": "",
"SignInRedirectURI": “”,
"SignOutRedirectURI": "",
"Scopes": [
"phone",
"email",
"openid",
"profile",
"aws.cognito.signin.user.admin"
]
},
"authenticationFlowType": "USER_SRP_AUTH"
}
}
}
}
},
"storage": {
"plugins": {
"awsS3StoragePlugin": {
"bucket": "",
"region": “”
}
}
}
}
We are using below API for user login
Amplify.Auth.signIn(
username, password,
{ authResult ->
validateSignInConfirmation(authResult, restCallBack)
},
{ error ->
val errorData = ErrorCode(null, error.message)
restCallBack.onError(errorData, null)
}
)
For fetching user session
Amplify.Auth.fetchAuthSession(
{ authSession ->
val cognitoSession = authSession as AWSCognitoAuthSession
restCallBack.onSuccess(cognitoSession)
},
{
val errorData = ErrorCode(null, it.message)
restCallBack.onError(errorData, null)
}
)
For reading idtoken we are using authsession object returned in fetchSession api
authSession?.tokensResult?.value?.idToken.toString()
Thanks, we'll work work on reproducing the issue.
As a clarification, the tokens does not refresh automatically if there are no api calls. The tokens are refreshed when an Amplify api is executed and the executed api internally calls fetchAuthSession
.
@sharadsmhaske I'm not seeing any issues with expired session getting refreshed. Once the tokens are expired, the tokens will be refreshed upon calling fetchAuthSession
or any any other Amplify api that executes fetchAuthSession
internally. The tokens will not be refreshed automatically by itself while the app is in idle state.
@phantumcode We are using authsession object to get id token that is used as authorization header for all the apis through aws api gateway. As you are saying it wont auto refresh, then we might need to call this api each time when we need refresh the token. This is contracting to facts that aws amplify auto manage token refresh. How to handle this scenario? Also there is no way to know whether token is about to expire. I think SDK should provide some mechanism to let the client to know so that only one call can be made to refresh it.
@sharadsmhaske You can listen to the Amplify Hub Event for when a session has expired or handle a SessionExpiredException
and call fetchAuthSession to refresh
@phantumcode We have some api which might get failed because of token is expired. Can you please elaborate how we will get sessionexpiredexception when reading the idtoken only in amplify.
@sharadsmhaske Are the APIs you're calling Amplify APIs or your custom APIs? Amplify Auth apis will call fetchAuthSession internally, so any expired tokens will be automatically refreshed. Otherwise you'll need to check the service exception being returned and check the exception type and determine if it's a not authorized exception or the cause of the exception is due to session expiration and then call fetchAuthSession to refresh the tokens as a result of the service exception. Alternatively, you can call fetchAuthSession ahead of time to ensure that your sessions are always fresh before your service call.
Can you check your dependencies? I think your usage of the AWS AppSync SDK with Amplify v2 is likely problematic. I believe the AppSync SDK will attempt to use AWS Android SDK's MobileClient which is incompatible with Amplify v2 as it wipes Amplify v2 credentials stored on device (which would cause the loss of tokens).
If you want to use AWS AppSync SDK with Amplify v2, you will need to use a custom credentials provider and pass that in.
See this page https://docs.amplify.aws/gen1/android/sdk/configuration/amplify-compatibility/ for instructions on how to create a CredentialsProvider that uses Amplify v2.