MQTT5Client disconnects and does not reconnect when connecting with authenticated Cognito Identity #609
Replies: 7 comments
-
This looks like a serious API defect; there is no way to dynamically modify the login key value pairs over time. I'm not sure what the right change would be -- possibly a callback to let you add pairs every time the cognito http request is made, in that case you'd move the first few lines into the callback and have it inject your provider-token pair there. I'll try to get some traction on this internally, but I can't give a timeline yet. |
Beta Was this translation helpful? Give feedback.
-
Current tentative proposal is that we will add a new configuration option that allows you to set a callback function that will be invoked right before credentials are fetched from cognito:
If this callback is set, then the credential fetch will be deferred until the returned future completes. The pairs in the future's result will be added to the cognito API call to fetch credentials. In your case, you'd leave the login token pairs empty in the provider constructor (since the only pair you want is session-limited) and you'd implement your callback to asynchronously fetch the token pair you need and complete the returned future with it. You would also need to wrap the cognito provider with a caching provider (https://github.com/awslabs/aws-crt-java/blob/main/src/main/java/software/amazon/awssdk/crt/auth/credentials/CachedCredentialsProvider.java), where the CachedCredentialsProvider's caching duration is a value comfortably less than your sourced token's expiration time. |
Beta Was this translation helpful? Give feedback.
-
@bretambrose Thank you for taking the time to answer this. Can you give us a rough idea of when this callback feature might be available? We rely heavily on authenticated Cognito identities, which is really important. In the meantime, is there any manual workaround without an API to force a token refresh? We're looking for a way to ensure that offline devices can reconnect properly using persistent sessions. |
Beta Was this translation helpful? Give feedback.
-
I cannot give a time estimate at this time. For a workaround: The CRT provides a generic credentials provider that will source credentials from whatever method you would like: https://github.com/awslabs/aws-crt-java/blob/main/src/main/java/software/amazon/awssdk/crt/auth/credentials/DelegateCredentialsProvider.java So you could use this provider and in your callback, you could source the session credentials directly from cognito using GetCredentialsForIdentity: https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html Before calling GetCredentialsForIdentity, you would source your id provider token and configure the Logins key-value set appropriately. The downside of this solution is that it will block the event loop the connection is seated on, since the DelegateProvider's API is not asynchronous. |
Beta Was this translation helpful? Give feedback.
-
Hi @bretambrose We implemented the workaround, the MQTT client is unable to reconnect to the IoT broker especially when the machine on which this code runs comes back online after being disconnected for few minutes. What are we doing wrong here ? For testing purposes, we've set the cognito token expiration is 60 seconds and cache_duration to 58 seconds. Code for your reference - `Callback -public class CognitoCredentialsCallBack implements DelegateCredentialsHandler {
} IOT CLient codeCognitoCredentialsCallBack cognitoCredentialsCallBack = new CognitoCredentialsCallBack();
` |
Beta Was this translation helpful? Give feedback.
-
Honestly, this is something you're going to have to debug yourself. Logs can be helpful in seeing what's going on. You can enable CRT logging via system properties using the instructions here: https://github.com/awslabs/aws-crt-java?tab=readme-ov-file#system-properties |
Beta Was this translation helpful? Give feedback.
-
@bretambrose Within the credentials callback, we invoke the following Cognito and IoT APIs:
We have observed that reconnection does not occur immediately upon losing the internet connection. Instead, there is a variable time interval after which the MQTT5Client attempts to reconnect to the IoT broker by calling the getCredentials() callback. Because the internet is disconnected, the call to GetOpenIdTokenForDeveloperIdentity fails and is retried three times before the MQTT5Client stops attempting to reconnect. How can we ensure that the MQTT5Client keeps calling the getCredentials() callback until the device is back online? To enforce this reconnection in a loop, we added the following to the onConnectionFailure() and onDisconnection() LifeCycleEvent's callback method, but this is not enforcing the MQTT5Client to keep trying the reconnection until the device comes back online or the client reconnects successfully. //code added to onDisconnection() and onConnection() lifeCycleEvents callback class -
Cognito callback failing while calling the GetOpenIdTokenForDeveloperIdentity AWS CRT logs |
Beta Was this translation helpful? Give feedback.
-
We connect to AWS IOT broker using authenticated access via AWS COgnito . we use the custom developer identity provider to authenticate our identities.
The overall process is done in 3 steps -
But we see that after connecting once the IoT client disconnects from the broker with error code - 1051 after roughly 15-20 mins. The client fails with errorcode 6146 everytime it attempts reconnection.
The MQTT5Client reconnected successfully when we connected using Cognito guess access.
We suspect that the OpenID token we get from Cognito System expires due to which the MQTT5Client is unable to reconnect to the IOT broker endpoint.
How can we achieve successful reconnection?
Beta Was this translation helpful? Give feedback.
All reactions