aws-sdk-java-v2 icon indicating copy to clipboard operation
aws-sdk-java-v2 copied to clipboard

Cognito user pool (with device tracking ON): Session refresh fails with error - "Invalid Refresh Token"

Open wye220 opened this issue 2 years ago • 6 comments

Describe the bug

I am trying to retrieve a new access token using the Cognito refresh token through the InitiateAuth API. The user pool has device tracking enabled. As per the documentation. I added the DEVICE_KEY parameter for REFRESH_TOKEN_AUTH auth flow, but I am keep getting Invalid Refresh Token error. If I turn off the device tracking, it will work fine.

Initiating refresh request: { "AuthFlow" : "REFRESH_TOKEN_AUTH", "AuthParameters" : { "DEVICE_KEY" : "us-east-1_6e3cb5cf-6c22-4110-97cc-fa43e3b13280", "REFRESH_TOKEN" : "eyJjdHkiOiJKV1QiLC..." }, "ClientId" : "28bt9dfokuqqcn6g68k10gjr6h" }

Expected Behavior

Return access and id token

Current Behavior

NotAuthorizedException - Invalid Refresh Token

Reproduction Steps

It's exact same issue similar to https://github.com/aws/aws-sdk-cpp/discussions/1903 and https://github.com/aws/aws-sdk-cpp/issues/851

Possible Solution

No response

Additional Information/Context

No response

AWS Java SDK version used

cognitoIdentityprovider 2.17.258

JDK version used

openjdk version "17.0.3" 2022-04-19

Operating System and version

macOS Monterey 12.5.1

wye220 avatar Sep 09 '22 03:09 wye220

NotAuthorizedException usually means the aws credential or role used to make the request does not have permission to perform the action. Can this be the case? How often do you see the error, sometimes or every time you make a REFRESH_TOKEN_AUTH call?

Can you provide the full stacktrace with the error?

debora-ito avatar Sep 09 '22 21:09 debora-ito

@debora-ito I got the same error every time if I disable the device tracking. It will work with the same refresh token.

wye220 avatar Sep 13 '22 13:09 wye220

Can you show a full stacktrace?

debora-ito avatar Sep 13 '22 21:09 debora-ito

software.amazon.awssdk.services.cognitoidentityprovider.model.NotAuthorizedException: Invalid Refresh Token. (Service: CognitoIdentityProvider, Status Code: 400, Request ID: 8b328158-a9a6-47dc-b53c-3d69e68109f4) at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleErrorResponse(CombinedResponseHandler.java:125) at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handleResponse(CombinedResponseHandler.java:82) at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:60) at software.amazon.awssdk.core.internal.http.CombinedResponseHandler.handle(CombinedResponseHandler.java:41) at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:40) at software.amazon.awssdk.core.internal.http.pipeline.stages.HandleResponseStage.execute(HandleResponseStage.java:30) at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206) at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:73) at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptTimeoutTrackingStage.execute(ApiCallAttemptTimeoutTrackingStage.java:42) at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:78) at software.amazon.awssdk.core.internal.http.pipeline.stages.TimeoutExceptionHandlingStage.execute(TimeoutExceptionHandlingStage.java:40) at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:50) at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallAttemptMetricCollectionStage.execute(ApiCallAttemptMetricCollectionStage.java:36) at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:81) at software.amazon.awssdk.core.internal.http.pipeline.stages.RetryableStage.execute(RetryableStage.java:36) at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206) at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:56) at software.amazon.awssdk.core.internal.http.StreamManagingStage.execute(StreamManagingStage.java:36) at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.executeWithTimer(ApiCallTimeoutTrackingStage.java:80) at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:60) at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallTimeoutTrackingStage.execute(ApiCallTimeoutTrackingStage.java:42) at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:48) at software.amazon.awssdk.core.internal.http.pipeline.stages.ApiCallMetricCollectionStage.execute(ApiCallMetricCollectionStage.java:31) at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206) at software.amazon.awssdk.core.internal.http.pipeline.RequestPipelineBuilder$ComposingRequestPipelineStage.execute(RequestPipelineBuilder.java:206) at software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage.execute(ExecutionFailureExceptionReportingStage.java:37) at software.amazon.awssdk.core.internal.http.pipeline.stages.ExecutionFailureExceptionReportingStage.execute(ExecutionFailureExceptionReportingStage.java:26) at software.amazon.awssdk.core.internal.http.AmazonSyncHttpClient$RequestExecutionBuilderImpl.execute(AmazonSyncHttpClient.java:193) at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.invoke(BaseSyncClientHandler.java:103) at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.doExecute(BaseSyncClientHandler.java:167) at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.lambda$execute$1(BaseSyncClientHandler.java:82) at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.measureApiCallSuccess(BaseSyncClientHandler.java:175) at software.amazon.awssdk.core.internal.handler.BaseSyncClientHandler.execute(BaseSyncClientHandler.java:76) at software.amazon.awssdk.core.client.handler.SdkSyncClientHandler.execute(SdkSyncClientHandler.java:45) at software.amazon.awssdk.awscore.client.handler.AwsSyncClientHandler.execute(AwsSyncClientHandler.java:56) at software.amazon.awssdk.services.cognitoidentityprovider.DefaultCognitoIdentityProviderClient.initiateAuth(DefaultCognitoIdentityProviderClient.java:5498) at software.amazon.awssdk.services.cognitoidentityprovider.CognitoIdentityProviderClient.initiateAuth(CognitoIdentityProviderClient.java:7691) at com.paywithextend.auth.service.CognitoService.renewAuth(CognitoService.kt:237) at com.paywithextend.auth.api.AuthController.renewAuth(AuthController.kt:256) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1070) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) at javax.servlet.http.HttpServlet.service(HttpServlet.java:681) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at com.paywithextend.common.logging.LogbackDiagnosticContext.doFilter(LogbackDiagnosticContext.kt:34) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.web.filter.AbstractRequestLoggingFilter.doFilterInternal(AbstractRequestLoggingFilter.java:289) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:337) at org.springframework.security.web.access.intercept.AuthorizationFilter.doFilterInternal(AuthorizationFilter.java:73) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:122) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:116) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:126) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:81) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:109) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:149) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:198) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90) at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:112) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:82) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:55) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:346) at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:221) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:186) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:354) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:96) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:687) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.base/java.lang.Thread.run(Thread.java:833)

wye220 avatar Sep 14 '22 22:09 wye220

Same error if I make the call with oauth2 endpoint. curl --location --request POST 'https://auth-staging-stage.auth.us-east-1.amazoncognito.com/oauth2/token' Getting 400 invalid grant error if the user pool has device tracking enabled.

{ "eventVersion": "1.08", "userIdentity": { "accountId": "949075974776" }, "eventTime": "2022-09-14T22:47:23Z", "eventSource": "cognito-idp.amazonaws.com", "eventName": "Token_POST", "awsRegion": "us-east-1", "sourceIPAddress": "71.190.59.27", "userAgent": "curl/7.79.1", "errorCode": "400", "requestParameters": null, "responseElements": null, "additionalEventData": { "responseParameters": { "status": 400 }, "requestParameters": { "refresh_token": [ "HIDDEN_DUE_TO_SECURITY_REASONS" ], "device_key": [ "us-east-1_e5aa0983-759e-478c-bf4b-6fa73b2af7a5" ], "grant_type": [ "refresh_token" ], "client_id": [ "28bt9dfokuqqcn6g68k10gjr6h" ] }, "userPoolDomain": "auth-staging-stage.auth.us-east-1.amazoncognito.com", "userPoolId": "us-east-1_UQwd7UCJb" }, "requestID": "956f5629-1456-4c07-87c7-d7cda4c0b76b", "eventID": "2179c3cc-21ca-4638-90de-c6da567245c7", "readOnly": false, "eventType": "AwsServiceEvent", "managementEvent": true, "recipientAccountId": "949075974776", "serviceEventDetails": { "serviceAccountId": "745623467555" }, "eventCategory": "Management" }

Same request will go through and get 200 ok response if I turn off the device tracking. user same refresh token from previous steps.

{ "eventVersion": "1.08", "userIdentity": { "accountId": "949075974776" }, "eventTime": "2022-09-14T22:47:59Z", "eventSource": "cognito-idp.amazonaws.com", "eventName": "Token_POST", "awsRegion": "us-east-1", "sourceIPAddress": "71.190.59.27", "userAgent": "curl/7.79.1", "requestParameters": null, "responseElements": null, "additionalEventData": { "responseParameters": { "status": 200 }, "requestParameters": { "refresh_token": [ "HIDDEN_DUE_TO_SECURITY_REASONS" ], "device_key": [ "us-east-1_e5aa0983-759e-478c-bf4b-6fa73b2af7a5" ], "grant_type": [ "refresh_token" ], "client_id": [ "28bt9dfokuqqcn6g68k10gjr6h" ] }, "userPoolDomain": "auth-staging-stage.auth.us-east-1.amazoncognito.com", "userPoolId": "us-east-1_UQwd7UCJb" }, "requestID": "4045cb79-7ac9-4fa3-bb24-5be071a76e5e", "eventID": "7c5929b6-9c0e-41bf-a8db-14c1ba4344bd", "readOnly": false, "eventType": "AwsServiceEvent", "managementEvent": true, "recipientAccountId": "949075974776", "serviceEventDetails": { "serviceAccountId": "745623467555" }, "eventCategory": "Management" }

wye220 avatar Sep 14 '22 22:09 wye220

This looks like a validation on the service side related to that device tracking. I don't have expertise in Cognito so I'll relay this to the Cognito team and wait for their reply.

debora-ito avatar Sep 16 '22 18:09 debora-ito

Here's the Cognito team response, and I quote:


Investigation Details: Please note, if “remember devices" feature is turned on (Either to "Always" or "User Opt In") for the user pool, then the device needs to be confirmed first with the help of ConfirmDevice API call before refreshing the tokens. Hence, after USER_PASSWORD_AUTH we have to confirm the device and then perform the REFRESH_TOKEN_AUTH, else will observe the error Invalid Refresh Token.

So, the detailed flow will be as follows:

Perform USER_PASSWORD_AUTH using the InitiatAuth API, which will return following output:

== OUTPUT ==

{
  "ChallengeParameters": {},
  "AuthenticationResult": {
      "AccessToken": "----ACCESS_TOKEN----",
      "ExpiresIn": 3600,
      "TokenType": "Bearer",
      "RefreshToken": "----REFRESH_TOKEN----",
      "IdToken": "----ID_TOKEN----",
      "NewDeviceMetadata": {
          "DeviceKey": "----DEVICE_KEY----",
          "DeviceGroupKey": "----DEVICE_GROUP----"
      }
  }
}

Next, perform ConfirmDevice API call with below parameters:

== INPUT ==

ACCESS_TOKEN - access token that you received in the initiate auth output
DEVICE_KEY - device key that you received in the initiate auth output
DeviceSecretVerifierConfigType - This parameter has 2 sub value as shown below 
"DeviceSecretVerifierConfig": { 
   "PasswordVerifier": "string",
   "Salt": "string"
} 

To generate the “DeviceSecretVerifierConfig” parameters please refer the “Call ConfirmDevice” section in LINK

For more information on ConfirmDevice API call please refer LINK

== OUTPUT ==

{
    "UserConfirmationNecessary": false
}

Finally, perform the REFRESH_TOKEN_AUTH with below parameters:

== INPUT ==

REFRESH_TOKEN - taken from the output of USER_PASSWORD_AUTH, 
SECRET_HASH - [OPTINAL] If client secret is configured for the App cleint
DEVICE_KEY - taken from the output of USER_PASSWORD_AUTH.

For more information about initiateAuth please refer LINK

== OUTPUT ==

 {
   "ChallengeParameters": {},
   "AuthenticationResult": {
       "AccessToken": "----ACCESS_TOKEN----",
       "ExpiresIn": 3600,
       "TokenType": "Bearer",
       "IdToken": "----ID_TOKEN----"
   }
}

The customer is missing the ConfirmDevice step, which is causing the issue.


Let us know if this helps.

debora-ito avatar Sep 22 '22 17:09 debora-ito

Thanks will try it out

wye0220 avatar Sep 27 '22 06:09 wye0220

@debora-ito

This suggested flow is a bit problematic if you have a lot of users logging in as the ConfirmDevice call utilizes the UserResourceUpdate quota which is low and not adjustable..

I've tried to defer the confirm device call to be done lazily (before token refresh) and I occasionally get an invalid device key error. This makes me think the confirm device call has a window of validity for each device key.

How would you suggest working around these scalability limitations?

kceb avatar Oct 10 '23 21:10 kceb