init push
This commit is contained in:
121
docs/frontend-sso-exchange-flow.md
Normal file
121
docs/frontend-sso-exchange-flow.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# 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": "<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:
|
||||
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.
|
||||
Reference in New Issue
Block a user