Uh oh!
There was an error while loading. Please reload this page.
Handle expired signature GraphQL errors with ApolloAuthInterceptor - #115
Handle expired signature GraphQL errors with ApolloAuthInterceptor#115AndrewCheung360 wants to merge 3 commits into
Conversation
📝 WalkthroughWalkthroughAdds an Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Interceptor as ApolloAuthInterceptor
participant TokenMgr as TokenManager
participant RefreshClient as ApolloClient (refresh)
participant SessionMgr as SessionManager
participant Server
Client->>Interceptor: Execute GraphQL request
Interceptor->>TokenMgr: Read access token
Interceptor->>Server: Send request (with access token)
Server-->>Interceptor: Response (error: "Signature has expired")
Interceptor->>Interceptor: Check RetryContext (not retried)
Interceptor->>TokenMgr: Get refresh token
TokenMgr-->>Interceptor: Refresh token (or null)
alt refresh token present
Interceptor->>RefreshClient: Execute RefreshAccessTokenMutation (Authorization: Bearer <refresh>)
RefreshClient->>Server: Refresh request
Server-->>RefreshClient: Return new access token (or none)
RefreshClient-->>Interceptor: New access token (or null)
alt new access token returned
Interceptor->>TokenMgr: Save new access token
Interceptor->>Interceptor: Increment RetryContext
Interceptor->>Server: Retry original request (with new access token)
Server-->>Interceptor: Success response
Interceptor-->>Client: Return successful response
else no token / refresh failed
Interceptor->>SessionMgr: Trigger logout()
Interceptor-->>Client: Return original/error response
end
else no refresh token
Interceptor->>SessionMgr: Trigger logout()
Interceptor-->>Client: Return original/error response
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@app/src/main/java/com/cornellappdev/uplift/data/auth/ApolloAuthInterceptor.kt`:
- Around line 66-67: In ApolloAuthInterceptor.kt inside ApolloAuthInterceptor
(likely in the intercept() catch block), don’t silently swallow the Exception
before calling sessionManager.logout(): capture the caught exception (e) and
record it via your app’s logging/telemetry mechanism (e.g., Timber.e /
logger.error / Sentry.captureException) with context about the token refresh
failure, then proceed to call sessionManager.logout(); ensure the log includes
the exception message/stacktrace and any relevant identifiers (userId/sessionId)
to aid diagnosis.
- Around line 47-70: The refresh branch in ApolloAuthInterceptor is racy:
multiple coroutines may run refreshClient.mutation(...) concurrently and one
failing path can call sessionManager.logout() even after another succeeded;
serialize refresh attempts by introducing a single synchronization point (e.g.,
a Mutex or synchronized block) around the refresh logic inside
ApolloAuthInterceptor: before calling refreshClient.mutation(...) acquire the
lock, re-check tokenManager.getRefreshToken() and/or current access token to see
if another coroutine already refreshed, perform the mutation/save via
tokenManager.saveTokens(newAccessToken, refreshToken) only while holding the
lock, then release it, and only call sessionManager.logout() if after the locked
check there is still no valid token; this mirrors the guard in
TokenAuthenticator and prevents concurrent refresh/logout races.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 49e1a5bb-302c-4e89-86e0-df87aab0971e
📒 Files selected for processing (2)
app/src/main/java/com/cornellappdev/uplift/data/auth/ApolloAuthInterceptor.ktapp/src/main/java/com/cornellappdev/uplift/di/AppModule.kt
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
AndrewCheung360
commented
Apr 30, 2026
Addressed comments by adding a |
Overview
Fixed the issue where GraphQL queries would fail with a "Signature has expired" error, even when returning a 200 OK HTTP status code.
Changes Made
ApolloAuthInterceptorto detect GraphQL-level "Signature has expired" errors in the response body.RetryContextto prevent infinite retry loops in case of persistent authentication failures.AppModulefor the primaryApolloClient.Test Coverage
ProfileRepository.getProfile()properly handles the expired signature error by triggering a refresh and successfully completing the query on retry.Related PRs or Issues
Fixes the "Failed to load profile" crash caused by expired tokens.
Summary by CodeRabbit
Update
Update