3.8 KiB
3.8 KiB
Frontend Flow: Microsoft ssoSilent + Backend /auth/exchange
This document describes the recommended frontend authentication flow when using:
- Microsoft Entra
ssoSilenton 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+refreshcookies).
High-Level Sequence
- Frontend attempts to call backend API with current backend access session.
- If backend responds
401, frontend callsPOST /api/v1/auth/refreshonce. - If refresh fails (
401), frontend tries MicrosoftssoSilent. - If
ssoSilentsucceeds, frontend callsPOST /api/v1/auth/exchange. - Backend issues fresh auth cookies. Frontend retries the original API request.
- If
ssoSilentfails withinteraction_required, frontend logs out local app session and redirects user to interactive login.
Detailed Frontend Logic
1) App startup / route guard
- Try calling a lightweight authenticated endpoint (for example
/api/v1/auth/me). - If response is
200, continue app normally. - If response is
401, run the recovery flow below.
2) Recovery flow for backend 401
- Call
POST /api/v1/auth/refreshonce. - If refresh is successful (
200), retry the original request and continue. - If refresh fails (
401), call MicrosoftssoSilent.
3) On successful ssoSilent
The frontend receives a Microsoft auth result (example fields):
accessTokenidTokenidTokenClaims
Send them to backend exchange endpoint:
POST /api/v1/auth/exchange
Content-Type: application/json
{
"data": {
"type": "auth_exchange",
"attributes": {
"access_token": "<ms_access_token>",
"id_token": "<ms_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:
- Clear local app auth state (user store, cached flags, pending retries).
- 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
- one
- 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
- action:
/auth/refresh401:- action:
ssoSilent
- action:
ssoSilentsuccess:- action:
/auth/exchange
- action:
ssoSilentinteraction_required:- action: clear session + redirect login
/auth/exchange401:- action: clear session + redirect login
Security Notes
- Do not store backend refresh tokens in JavaScript storage.
- Prefer
HttpOnly,Secure,SameSitecookies 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.