Files
tatlock-ui/TODO_AUTH_REFACTOR.md

2.7 KiB

Auth Flow Refactor: Invisible Token Exchange

Research note for future implementation

Problem

The /callback?code=... URL is visible in the browser during token refresh. This happens every time tokens need refreshing, not just on initial login. The current implementation appears to re-run the full OIDC redirect flow (prompt=none) instead of using the refresh_token.

Current Behavior

Token expires → Redirect to Authentik (prompt=none) →
Redirect to /callback?code=xxx → Exchange code → Continue

User sees URL flicker to /callback repeatedly.

Desired Behavior

Token expires → Show overlay (lock/lightning icon) →
XHR refresh request → Hide overlay → Continue

No URL changes. No redirects. Just a brief visual indicator.

Key Insight

Only the initial authorization MUST redirect (user needs to see Authentik login UI).

Everything else can be XHR:

Operation Current Should Be
Initial login Redirect Redirect (unavoidable)
Token exchange (code → tokens) Redirect to /callback XHR POST
Token refresh Full OIDC with prompt=none XHR POST with refresh_token
Session expired Redirect Redirect (unavoidable)

Token Refresh via XHR

final response = await dio.post(
  'https://authentik.schweitz.net/application/o/token/',
  data: {
    'grant_type': 'refresh_token',
    'refresh_token': storedRefreshToken,
    'client_id': clientId,
  },
  options: Options(
    contentType: Headers.formUrlEncodedContentType,
  ),
);
// Returns new access_token, refresh_token, expires_in

Potential Blocker: CORS

Authentik's token endpoint may block browser XHR. Solutions:

  1. Configure Authentik CORS - Allow home.schweitz.net origin
  2. Proxy through core-api (recommended)
    • Flutter → POST /auth/refresh → core-api → Authentik
    • Keeps client_secret server-side
    • No CORS issues

Implementation Steps

  1. Verify Authentik is issuing refresh_tokens (check token response)
  2. Check if refresh_token is being stored (SharedPreferences)
  3. Test XHR to token endpoint (check CORS)
  4. If CORS blocked, add /auth/refresh endpoint to core-api
  5. Refactor AuthProvider to use XHR refresh instead of full OIDC flow
  6. Add refresh overlay UI (lock icon + brief animation)
  7. Remove prompt=none redirect logic for refresh cases

Files to Investigate

  • lib/core/auth/auth_provider.dart - Main auth state management
  • lib/core/auth/oidc_service_web.dart - OIDC implementation
  • lib/core/api/api_interceptors.dart - Token refresh trigger point

References

  • CHANGELOG entries v1.1.3-v1.1.6 document the current auth architecture
  • AuthController runs in main() before runApp() (v1.1.6 pattern)