Repository navigation
fix(ios): keep the app running while credentials are renewed - #1711
Anzormumladze wants to merge 1 commit into
Conversation
A Credentials Manager call can exchange the refresh token. With refresh token rotation, Auth0 replaces the refresh token when it handles the exchange. If iOS suspends the app after that, but before the response arrives and the new refresh token is stored, the app keeps the old refresh token. After the rotation overlap period the next renewal sends that old token, Auth0's reuse detection revokes the token family, and the user has to log in again. Wrap getCredentials (including forceRefresh), getSSOCredentials and getApiCredentials in a UIKit background task, so iOS keeps the app running until the request finishes and the result is stored, within the normal background time limit. UIApplication is looked up at runtime so the pod still builds for app extensions. Related to auth0#1374
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Background task wrapper ios/CredentialsBackgroundTask.swift |
Adds a UIKit background-task wrapper. It checks for an available application, ends the task on expiration, and resets the task identifier after ending. |
Credential request integration ios/NativeBridge.swift |
getCredentials, getSSOCredentials, and getApiCredentials start a background task before their requests and end it when their completion handlers run. |
Priority:
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix
Suggested reviewers: pmathew92, subhankarmaiti
Merge Risk: 
Minimal · up to 60e64
-
No actionable issue is established by the available evidence. The change is mergeable after normal validation.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passed-
Full details: Title check
-
Explanation
The title names the main change: iOS credential calls now run in a background task so renewal can finish. It uses the conventional fix(ios) prefix and is specific. Its scope is accurate and it does not describe unrelated work.
Full details: Description check
-
Explanation
The description states the change: iOS getCredentials (with forceRefresh), getSSOCredentials, and getApiCredentials now run inside a UIKit background task. It gives the rotation-related reason, the new internal file, the limits, and the test results. It matches the changeset closely.
-
-
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
|
@subhankarmaiti @NandanPrabhu could you please review this when you have time? It is a small iOS-only change for one cause of #1374. The A/B test is in the description. |
|
Hi @Anzormumladze thanks for raising the PR! We always love contributions from the community. |
@NandanPrabhu done: auth0/Auth0.swift#1321 It is the same fix, now in
Should I close this PR now, or keep it open until the Auth0.swift PR is merged? |
|
Hi @Anzormumladze |
Changes
On iOS, these calls now run inside a UIKit background task (
beginBackgroundTask/endBackgroundTask):getCredentials(also withforceRefresh)getSSOCredentialsgetApiCredentialsThe task ends in the Credentials Manager callback. Auth0.swift stores the new credentials before it calls that callback, so the task covers the request and the store.
ios/CredentialsBackgroundTask.swift.UIApplicationis looked up at runtime (the same way Auth0.swift does it), so the pod still builds for app extensions.Why: with refresh token rotation, Auth0 replaces the refresh token as soon as it handles the exchange. If iOS suspends the app after that, and the app is terminated before it stores the response, the app keeps the old refresh token. After the rotation overlap period, the next renewal sends the old token. Reuse detection then revokes the token family, and the user must log in again.
maxRetriescannot help in this case, because the app is not running when the response arrives.Limits (best effort):
iOS may keep the app running a few seconds longer in the background while one of these calls is in progress.
This could also live in Auth0.swift's
CredentialsManager. I kept it in the bridge because it is iOS-only, small, and needs no API change. I'm happy to move it, or to open a backport for the v5 line.References
Testing
yarn typecheck: pass.yarn lint: 0 errors. The 6 warnings are already onmaster.yarn test: 805 of 805 pass.Manual A/B test on an iOS 18.3 Simulator, with the example app built from this branch with and without the change. It ran against an Auth0 tenant with refresh token rotation and a 180 s overlap. The app was launched without the debugger. Steps:
getCredentials(). The proxy holds the/oauth/tokenresponse for 20 s. Auth0 has already rotated the token at this point.getCredentials().invalid_grant, logged outinvalid_grant, logged outThis repo has no iOS unit test target, so I could not add a unit test. Not tested on a physical device, and not on the iOS 27 Simulator.
Checklist