# Frontend Flow: Microsoft `ssoSilent` + Backend `/auth/exchange` This document describes the recommended frontend authentication flow when using: - Microsoft Entra `ssoSilent` on the frontend - Backend session tokens (`access` + `refresh`) issued by `/api/v1/auth/exchange` ## Goal Use Microsoft silent SSO to re-establish identity, then exchange that identity for backend session cookies/tokens used by API requests. ## Prerequisites - Frontend already integrated with MSAL and can call `ssoSilent`. - Backend has `POST /api/v1/auth/exchange`. - User account is already linked/recognized by backend SSO mapping. - Backend uses cookie-based auth session (`access` + `refresh` cookies). ## High-Level Sequence 1. Frontend attempts to call backend API with current backend access session. 2. If backend responds `401`, frontend calls `POST /api/v1/auth/refresh` once. 3. If refresh fails (`401`), frontend tries Microsoft `ssoSilent`. 4. If `ssoSilent` succeeds, frontend calls `POST /api/v1/auth/exchange`. 5. Backend issues fresh auth cookies. Frontend retries the original API request. 6. If `ssoSilent` fails with `interaction_required`, frontend logs out local app session and redirects user to interactive login. ## Detailed Frontend Logic ## 1) App startup / route guard 1. Try calling a lightweight authenticated endpoint (for example `/api/v1/auth/me`). 2. If response is `200`, continue app normally. 3. If response is `401`, run the recovery flow below. ## 2) Recovery flow for backend `401` 1. Call `POST /api/v1/auth/refresh` once. 2. If refresh is successful (`200`), retry the original request and continue. 3. If refresh fails (`401`), call Microsoft `ssoSilent`. ## 3) On successful `ssoSilent` The frontend receives a Microsoft auth result (example fields): - `accessToken` - `idToken` - `idTokenClaims` Send them to backend exchange endpoint: ```http POST /api/v1/auth/exchange Content-Type: application/json ``` ```json { "data": { "type": "auth_exchange", "attributes": { "access_token": "", "id_token": "", "id_token_claims": { "sub": "...", "preferred_username": "user@company.com", "name": "User Name", "tid": "...", "oid": "...", "exp": 1715603600 } } } } ``` Expected behavior: - `200`: backend sets fresh session cookies -> frontend retries previous API call. - `401`: identity not linked / invalid token -> treat as not authenticated and move to login. ## 4) On failed `ssoSilent` If frontend receives: - `errorCode = "interaction_required"` (or equivalent no-session/no-cookie condition) Then: 1. Clear local app auth state (user store, cached flags, pending retries). 2. Redirect to interactive login page/flow. Do not loop `ssoSilent` repeatedly. ## Retry Rules (Important) - Only attempt each step once per failure chain: - one `/auth/refresh` - one `ssoSilent` - one `/auth/exchange` - Use a request queue/lock to prevent multiple parallel refresh/exchange attempts. - If exchange fails, stop retries and force user to login interactively. ## Suggested Error Handling Matrix - Backend API `401`: - action: `/auth/refresh` - `/auth/refresh` `401`: - action: `ssoSilent` - `ssoSilent` success: - action: `/auth/exchange` - `ssoSilent` `interaction_required`: - action: clear session + redirect login - `/auth/exchange` `401`: - action: clear session + redirect login ## Security Notes - Do not store backend refresh tokens in JavaScript storage. - Prefer `HttpOnly`, `Secure`, `SameSite` cookies from backend. - Avoid logging raw Microsoft tokens in browser console or monitoring payloads. ## Optional UX Improvement When redirecting to login after `interaction_required`, preserve the intended route: - Save current path (`returnTo`) and restore it after successful login.