Mitigating Missed Responses from Refresh Token Requests with the Auth0.swift SDK
Last Updated:
Overview
This article provides troubleshooting steps to take when a mobile app implementation with the Swift SDK and CredentialsManager fails to receive the response from refresh token exchange requests to the /oauth/token endpoint due to connectivity issues, or if the user puts the app in the background immediately after the request is made.
Adding additional logging, following the guidance in Initializer | Auth0.swift v2 Migration Guide and Logging Keychain Errors can help surface this issue.
Applies To
- Auth0.Swift SDK
Cause
Failure of the app to capture the response from /oauth/token may be observed when:
- Connectivity issues led to client-side timeouts despite
- The user put the app in the background immediately after the request was made
In both cases, internal logs showed that the endpoint returned a 200, and a "Successful Refresh Token exchange" tenant log was emitted.
Solution
If the response never reaches the app because the networking layer reports a failure (e.g., lost connection) or because the app goes into the background, nothing can be done from the SDK side. The SDK defaults to the shared iOS URLSession singleton per the Apple Developer shared documentation, but supports specifying a custom one as explained in the Use a custom URLSession instance GitHub guide.
There are a few things that can be done to improve the situation:
- Configure a URLSession to be more resilient to changes between cellular and WiFi using Multipath TCP, using the Apple Article Improving network reliability using Multipath TCPlink as a guide.
- Configure a URLSession with a shorter timeout than the iOS default (60 seconds) so the retry falls within the Refresh Token Rotation leeway period.
- Wrap the
credentials()call in a background task, so that iOS gives it a few more seconds to finish before the app gets suspended.
See beginBackgroundTask(expirationHandler:).
To pass a custom URLSession to the Credentials Manager, they must first create a new instance of the Authentication API client with the custom URLSession, then pass this to the Credential Manager’s initializer. See Auth0 Credentials Manager Initializer for more details.
E.g.:
var configuration = URL SessionConfiguration.default
// configure it...
let customURLSession = URLSession(configuration: configuration)
let auth = Auth0.authentication(session: customURLSession)
let credentialsManager = CredentialsManager(authentication: auth)