# Autentificare și OAuth

> Chei API, OAuth 2.1 cu PKCE (lansare independentă SMART on FHIR), id_token OpenID Connect, scopuri SMART v2 pentru pacienți, durate de viață ale token-urilor și ciclul de viață al consimțământului.

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

Platforma Anpheros acceptă trei tipuri de credențiale. Fiecare cerere transportă exact una.

| Credențial | Arată ca | Cine | Vede |
|---|---|---|---|
| Cheie API | `sk_test_…` (sandbox) / `sk_live_…` (producție) | serverul unui proiect | pacienții creați de proiect (în sandbox, inclusiv propria copie a 30 de pacienți sintetici) |
| Token de acces OAuth | `at_…` | o aplicație care acționează pentru un pacient sub un consimțământ | doar acel pacient, în cadrul scopurilor SMART acordate |
| Token Firebase ID | JWT | un dezvoltator în dashboard, sau un pacient în "Conexiuni" | propriile organizații / propriile înregistrări |

Trimiteți-l ca `Authorization: Bearer <credential>` (cheile API funcționează și ca `X-Api-Key`).

## Chei API
- Create în dashboard sau prin `POST /admin/projects/{id}/keys`; afișate o singură dată; stocate ca hash SHA-256.
- Scopes: `read`, `write`. O cheie nu părăsește niciodată mediul proiectului său (`sk_test_` nu poate accesa date de producție și invers).
- Limita de rate per cheie (implicit 600/min) este aplicată la nivel de platformă (shared store), cu `Retry-After` pe 429. Există, de asemenea, o limită per IP de 600/min.
- Headers opționale la scrieri: `X-Anpheros-Author-Type`, `X-Anpheros-Author-Ref`, `X-Anpheros-Source-System`, `X-Anpheros-Origin-Id`, `X-Anpheros-Acting-As` (un Practitioner/PractitionerRole **din directorul propriu**), `X-Anpheros-On-Behalf-Of` (o Organizație din directorul propriu). Acestea populează Provenance.

## OAuth 2.1 (SMART on FHIR, standalone launch)
Discovery: `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]`
   Afișează pagina de consimțământ găzduită. PKCE S256 este obligatoriu; `redirect_uri` trebuie să fie înregistrat exact.
2. Pacientul se autentifică (Google sau email prin Firebase), alege înregistrarea (proprie sau a unui dependent), durata (30/90/180/365 zile) și permite. Platforma emite un cod unic (10 minute).
3. `POST /oauth/token` cu `grant_type=authorization_code&code=…&code_verifier=…&redirect_uri=…&client_id=…` (clienții confidențiali adaugă `client_secret`).
   Răspuns: `access_token` (30 min), `refresh_token` (30 zile, rotativ), `patient` (ID-ul dvs. pereche pentru înregistrare), `grant_id`, `scope`.
4. Refresh: `grant_type=refresh_token`. Fiecare token de reîmprospătare este de unică folosință. **Prezentarea unui token de reîmprospătare utilizat revocă întregul lanț** (detecție furt). O duplicare paralelă a unei cereri de reîmprospătare este refuzată și poate, de asemenea, revoca lanțul, deci nu rotiți niciodată concomitent.
5. Revocare: `POST /oauth/revoke` (token + client_id). Revocarea unui token de reîmprospătare revocă și token-urile sale de acces.

Răspunsurile token includ `Cache-Control: no-store` și `Pragma: no-cache`, așa cum cere SMART.

### OpenID Connect (`openid fhirUser`)
Solicitați `openid fhirUser` alături de scope-urile pacientului, iar răspunsul token include, de asemenea, un `id_token`: un JWT semnat cu RS256, cu `iss` (URL-ul de bază al platformei), `sub` (ID-ul dvs. pereche pentru persoană), `aud` (dvs. `client_id`), `exp`, `iat` și `fhirUser` — URL-ul absolut al resursei Patient a persoanei, care poate fi citit cu token-ul de acces pe care tocmai l-ați primit. Discovery se află la `GET /.well-known/openid-configuration`; cheile publice la `GET /oauth/jwks` (`kid` în antetul token-ului). Parametrul `nonce` nu este încă suportat (este opțional în fluxul authorization-code). `launch/patient` și `offline_access` sunt acceptate; câmpul `patient` al răspunsului token este contextul de lansare.

Alte tipuri de grant: `client_credentials` (clienți confidențiali; se comportă ca o cheie API) și grant-ul de identitate first-party (doar clienți de încredere).

### Brandul dvs. pe pagina de consimțământ

O aplicație poate afișa logo-ul și culoarea de accent pe pagina de consimțământ găzduită. Setați-le în consolă
(Applications → Brand) sau cu API-ul de administrare:

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

- **Logo:** o imagine PNG, JPEG sau WebP sub formă de data URI, de până la 64 KB. Conținutul este verificat, nu tipul declarat;
  SVG nu este acceptat. Imaginea este stocată împreună cu aplicația și încorporată în pagină, astfel încât pagina de consimțământ
  nu face nicio cerere către serverele dvs.
- **Culoare de accent:** `#RRGGBB`, utilizată pentru butonul principal. Textul alb de pe acesta trebuie să mențină un contrast de cel puțin
  4.5:1 (WCAG AA); culorile mai deschise sunt refuzate.
- Un câmp pe care îl omiteți rămâne așa cum este; `null` sau un șir gol îl elimină.

Restul paginii nu se modifică: linia "Secured by Anpheros Platform", lista în limbaj simplu a
ceea ce solicită aplicația și bannerul TEST pe proiectele sandbox rămân, astfel încât oamenii să poată spune întotdeauna că
consimțământul este deținut de Anpheros. Conectorii AI (MCP) afișează întotdeauna pagina Anpheros fără un brand de aplicație.

### Scopes
SMART v2 patient scopes: `patient/<Type>.<cruds>` cu un filtru opțional `?category=<code>` (singurul filtru pe care serverul îl impune; orice alt filtru este refuzat la momentul autorizării). `patient/*.rs` citește totul; `offline_access` adaugă un token de reîmprospătare. Demografia pacientului și directorul sunt întotdeauna citibile sub un grant. Un tip de resursă din afara grant-ului returnează 403; un pacient din afara grant-ului returnează 404.

### Ciclu de viață al consimțământului
Consimțămintele expiră automat, pot fi revocate de pacient în orice moment (ecranul Connections / `/me`), iar fiecare citire sub un consimțământ este înregistrată cu ID-ul aplicației. Webhook-urile `consent.granted` / `consent.revoked` notifică proiectul.

## Erori
401 credential necunoscută/expirată · 403 credentialul există, dar s-ar putea să nu aibă permisiunea necesară · 404 resursa nu există *pentru tine* · 429 limitat la rata specificată (`Retry-After`). Vezi [`errors.md`](https://developers.anpheros.com/ro/guides/errors).
