# 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.
