You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Parallel token refreshes reuse the same refresh token, causing logouts with IdPs that rotate refresh tokens #235
Use the app normally (browsing with thumbnails, sync, available offline) until the access token needs refreshing.
Expected behavior
One refresh request is sent, and every other caller waits for it and uses the new tokens.
Actual behavior
Every few days the app sends a burst of refresh requests with the same refresh token. The first reuse makes the IdP revoke the session, and the app asks me to log in again. From my Pocket ID logs for one logout: 1 successful refresh, then 30 failed refreshes (HTTP 400) within 10 seconds, then a new login.
Looking at the v1.2.5 source, I think this is a race in AccountAuthenticator:
getAuthToken refreshes whenever peekAuthToken returns null (AccountAuthenticator.java#L175). Callers include SingleSessionManager.getClientFor, ConnectionValidator.checkUnauthorizedAccess after a 401, and the Coil thumbnail interceptor on every image request.
refreshToken() reads the refresh token (L325), does the network call, and only then stores the new one (L441). Nothing locks or deduplicates this, so two callers can send the same token.
After a failed refresh (L420), the old refresh token stays stored and the access token stays empty, so each following caller tries again with the same dead token. I believe that explains the 30 requests.
Every refresh failure (network error, 5xx, or invalid_grant) goes down the same path to the login screen.
With IdPs that don't revoke on reuse, only the losing request fails, which is probably why this hasn't shown up much. The iOS app had the same class of problem between the app and its File Provider (opencloud-eu/ios#43), fixed there by locking the refresh and re-checking the stored token after getting the lock.
Environment
App: OpenCloud Android 1.2.5
Server: OpenCloud 8.0.1 with an external IdP (Pocket ID v2.14.0), public client OpenCloudAndroid with PKCE
Activity