# Backend Contract

Version: `2.9.8`

For the full payload and field-level specification, see [Data Contract](./data_contract.md).

## Required SaaS endpoints

These endpoints must exist on the SaaS backend that consumes `@ollaid/native-sso`.
They are not implemented by the IAM backend in `backend_sync`.

- `GET /api/sso/config`
- `POST /api/sso/exchange`
- `POST /api/sso/check-token`
- `POST /api/sso/refresh`
- `POST /api/sso/logout`
- `POST /api/sso/password-link`

## Expected flow

1. `GET /api/sso/config` returns `app_key`, `encrypted_credentials`, `iam_api_url`, `credentials_ttl`, `debug`, `bypass`
2. `POST /api/sso/exchange` returns `reference`, `alias_reference`, `iam_token`, `user_infos`, `expires_at`, `refresh_expires_at`
3. `needs_access` is returned when the user is authenticated but has no access to the SaaS yet
4. `redirectAfterLogin` and `redirectAfterLogout` are handled by `NativeSSOPage`

## `needs_access`

- default behavior when the user has no app access yet
- the package shows the confirmation modal
- the flow completes only after `grantAccess()`
- `IAM_BYPASS=true`, `IAM_VENDOR_BYPASS=true`, or `IAM_CLIENT_BYPASS=true` auto-creates access for the matching tenant

## Redirection

- use `redirectAfterLogin` to avoid staying on the SSO page after login
- use `redirectAfterLogout` if you want a custom logout destination
- do not mark the app connected before the access grant is done

## What the backend must do

- return JSON
- expose the `/api/sso/*` routes above on the SaaS backend
- use `POST /api/sso/auth/decrypt` for the IAM-side decrypt step; the old `POST /api/iam/auth/decrypt` route is obsolete
- expect the IAM decrypt response as a flat JSON object with `reference`, `alias_reference`, `iam_token`, `user_infos`, `expires_at`, and `refresh_expires_at`
- keep expiration metadata consistent
- update `last_active_at` if you enforce activity policy
- revoke access using the access token string returned as `iam_token`
- return only the canonical success fields
- keep `configPrefix` only on the SaaS configuration side
- answer `OPTIONS /api/sso/exchange` with a valid CORS preflight response
- return `422` for invalid business input such as an invalid or expired `callback_token`
- return `503` only when IAM or an upstream auth dependency is unreachable
- return `500` only for unexpected SaaS-side failures

## Debugging

- `Identifiants application invalides` means `app_key` or `encrypted_credentials` failed
- `Déchiffrement échoué` means the SaaS encrypted data does not match the expected `secret_key`
- `Credentials expirés` means the config blob is older than the TTL
- `incomplete_config` on `/api/sso/native/*` means the SaaS backend is missing its `IAM_*` variables or config cache is stale
- a browser-side `network error` on `/api/sso/exchange` usually means CORS, preflight, proxy, or transport failure, not a JSON `422`

## Canonical fields

The public SSO response contract should keep only:

- `user_infos`
- `reference`
- `alias_reference`
- `iam_token`
- `expires_at`
- `refresh_expires_at`

The numeric `app_access_tokens.id` must stay internal. The SaaS may store the
token string in a local `iam_token` column, but it should not expose the row id
as a public contract field.

## Validation checklist

- email login works
- phone login works
- OTP works
- `needs_access` appears when access is missing
- `*_BYPASS=true` works for the current tenant
- redirects are correct
- refresh survives transient network errors
