# Authentification et OAuth

> Clés API, OAuth 2.1 avec PKCE (lancement autonome SMART on FHIR), id_token OpenID Connect, scopes patient SMART v2, durées de vie des tokens et cycle de vie du consentement.

Source: https://developers.anpheros.com/fr/guides/authentication

La plateforme Anpheros accepte trois types d'identifiants. Chaque requête en transporte exactement un.

| Identifiant | Aspect | Qui | Voit |
|---|---|---|---|
| Clé API | `sk_test_…` (sandbox) / `sk_live_…` (production) | le serveur d'un projet | les patients créés par le projet (en sandbox, y compris sa propre copie de 30 patients synthétiques) |
| Token d'accès OAuth | `at_…` | une application agissant pour un patient sous un consentement | ce patient uniquement, dans les limites des scopes SMART accordés |
| Token d'identification Firebase | JWT | un développeur dans le tableau de bord, ou un patient dans "Connexions" | ses propres organisations / ses propres enregistrements |

Envoyez-le comme `Authorization: Bearer <credential>` (les clés API fonctionnent également comme `X-Api-Key`).

## Clés API
- Créées dans le tableau de bord ou via `POST /admin/projects/{id}/keys` ; affichées une seule fois ; stockées sous forme de hachage SHA-256.
- Portées (Scopes) : `read`, `write`. Une clé ne franchit jamais l'environnement de son projet (`sk_test_` ne peut pas accéder aux données de production et vice versa).
- La limite de débit par clé (par défaut 600/min) est appliquée à l'échelle de la plateforme (magasin partagé), avec `Retry-After` sur 429. Il existe également une limite par adresse IP de 600/min.
- En-têtes optionnels sur les écritures : `X-Anpheros-Author-Type`, `X-Anpheros-Author-Ref`, `X-Anpheros-Source-System`, `X-Anpheros-Origin-Id`, `X-Anpheros-Acting-As` (un Practitioner/PractitionerRole **de votre propre répertoire**), `X-Anpheros-On-Behalf-Of` (une Organization de votre propre répertoire). Ils remplissent Provenance.

## OAuth 2.1 (SMART on FHIR, lancement autonome)
Découverte : `GET /.well-known/smart-configuration`.

1. `GET /oauth/authorize?response_type=code&client_id=…&redirect_uri=…&scope=…&state=…&code_challenge=…&code_challenge_method=S256[&purpose=treatment][&patient=<pairwise id>][&lang=ro]`
   Affiche la page de consentement hébergée. PKCE S256 est obligatoire ; le `redirect_uri` doit être enregistré exactement.
2. Le patient se connecte (Google ou e-mail via Firebase), choisit le dossier (le sien ou celui d'un dépendant), la durée (30/90/180/365 jours) et autorise. La plateforme émet un code unique (10 minutes).
3. `POST /oauth/token` avec `grant_type=authorization_code&code=…&code_verifier=…&redirect_uri=…&client_id=…` (les clients confidentiels ajoutent `client_secret`).
   Réponse : `access_token` (30 min), `refresh_token` (30 jours, rotation), `patient` (votre identifiant pair pour le dossier), `grant_id`, `scope`.
4. Rafraîchissement : `grant_type=refresh_token`. Chaque jeton de rafraîchissement est à usage unique. **La présentation d'un jeton de rafraîchissement utilisé révoque toute la chaîne** (détection de vol). Un doublon parallèle d'une requête de rafraîchissement est refusé et peut également révoquer la chaîne, ne faites donc jamais de rotation simultanément.
5. Révocation : `POST /oauth/revoke` (jeton + client_id). La révocation d'un jeton de rafraîchissement révoque également ses jetons d'accès.

Les réponses de jeton transportent `Cache-Control: no-store` et `Pragma: no-cache`, comme l'exige SMART.

### OpenID Connect (`openid fhirUser`)
Demandez `openid fhirUser` en plus des scopes patient et la réponse du jeton contient également un `id_token` : un JWT signé avec RS256, avec `iss` (l'URL de base de la plateforme), `sub` (votre identifiant pair pour la personne), `aud` (votre `client_id`), `exp`, `iat` et `fhirUser` — l'URL absolue de la ressource Patient de la personne, lisible avec le jeton d'accès que vous venez de recevoir. La découverte se trouve à `GET /.well-known/openid-configuration` ; les clés publiques à `GET /oauth/jwks` (`kid` dans l'en-tête du jeton). Le paramètre `nonce` n'est pas encore pris en charge (il est facultatif dans le flux code d'autorisation). `launch/patient` et `offline_access` sont acceptés ; le champ `patient` de la réponse du jeton est le contexte de lancement.

Autres types d'octroi : `client_credentials` (clients confidentiels ; se comporte comme une clé API), et l'octroi d'identité de première partie (clients de confiance uniquement).

### Votre marque sur la page de consentement

Une application peut afficher son logo et sa couleur d'accent sur la page de consentement hébergée. Définissez-les dans la console
(Applications → Marque) ou avec l'API d'administration :

```http
PUT /admin/applications/{application_id}/branding
{"logo": "data:image/png;base64,…", "brand_color": "#1D4ED8"}
```

- **Logo :** une image PNG, JPEG ou WebP sous forme d'URI de données, jusqu'à 64 Ko. Le contenu est vérifié, pas le type déclaré ;
  SVG n'est pas accepté. L'image est stockée avec l'application et intégrée à la page, de sorte que la page de consentement
  ne fait aucune requête à vos serveurs.
- **Couleur d'accent :** `#RRGGBB`, utilisée pour le bouton principal. Le texte blanc sur celui-ci doit conserver un contraste d'au moins
  4,5:1 (WCAG AA) ; les couleurs plus claires sont refusées.
- Un champ que vous laissez vide reste tel quel ; `null` ou une chaîne vide le supprime.

Le reste de la page ne change pas : la ligne "Sécurisé par la plateforme Anpheros", la liste en langage clair de
ce que l'application demande, et la bannière TEST sur les projets sandbox restent, afin que les gens puissent toujours savoir que
le consentement est détenu par Anpheros. Les connecteurs IA (MCP) affichent toujours la page Anpheros sans marque d'application.

### Scopes
Scopes patient SMART v2 : `patient/<Type>.<cruds>` avec un filtre `?category=<code>` optionnel (le seul filtre appliqué par le serveur ; tout autre filtre est refusé au moment de l'autorisation). `patient/*.rs` lit tout ; `offline_access` ajoute un jeton de rafraîchissement. Les données démographiques du patient et le répertoire sont toujours lisibles sous un octroi. Un type de ressource en dehors de l'octroi renvoie 403 ; un patient en dehors de l'octroi renvoie 404.

### Cycle de vie du consentement
Les consentements expirent automatiquement, peuvent être révoqués par le patient à tout moment (écran Connexions / `/me`), et chaque lecture sous un consentement est enregistrée avec l'identifiant de l'application. Les webhooks `consent.granted` / `consent.revoked` notifient le projet.

## Erreurs
401 identifiant inconnu/expiré · 403 l'identifiant existe mais ne permet pas cette action · 404 la ressource n'existe pas *pour vous* · 429 limite atteinte (`Retry-After`). Voir [`errors.md`](https://developers.anpheros.com/fr/guides/errors).
