# Autenticação e OAuth

> Chaves de API, OAuth 2.1 com PKCE (lançamento autónomo SMART on FHIR), id_token OpenID Connect, âmbito SMART v2 para pacientes, tempos de vida de tokens e o ciclo de vida do consentimento.

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

A Plataforma Anpheros aceita três tipos de credenciais. Cada pedido transporta exatamente uma.

| Credencial | Parece | Quem | Vê |
|---|---|---|---|
| Chave de API | `sk_test_…` (sandbox) / `sk_live_…` (produção) | o servidor de um projeto | os pacientes que o projeto criou (em sandbox, incluindo a sua própria cópia de 30 pacientes sintéticos) |
| Token de acesso OAuth | `at_…` | uma aplicação a agir em nome de um paciente sob consentimento | apenas esse paciente, dentro dos âmbitos SMART concedidos |
| Token de ID Firebase | JWT | um programador no dashboard, ou um paciente em "Ligações" | as suas próprias organizações / os seus próprios registos |

Envie-o como `Authorization: Bearer <credential>` (as chaves de API também funcionam como `X-Api-Key`).

## Chaves de API
- Criadas no dashboard ou via `POST /admin/projects/{id}/keys`; mostradas uma vez; armazenadas como um hash SHA-256.
- Escopos: `read`, `write`. Uma chave nunca cruza o ambiente do seu projeto (`sk_test_` não pode aceder a dados de produção e vice-versa).
- O limite de taxa por chave (padrão 600/min) é aplicado em toda a plataforma (armazenamento partilhado), com `Retry-After` em 429. Existe também um limite por IP de 600/min.
- Cabeçalhos opcionais em escritas: `X-Anpheros-Author-Type`, `X-Anpheros-Author-Ref`, `X-Anpheros-Source-System`, `X-Anpheros-Origin-Id`, `X-Anpheros-Acting-As` (um Practitioner/PractitionerRole **do seu próprio diretório**), `X-Anpheros-On-Behalf-Of` (uma Organization do seu próprio diretório). Eles preenchem Provenance.

## OAuth 2.1 (SMART on FHIR, lançamento autónomo)
Descoberta: `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]`
   Mostra a página de consentimento alojada. PKCE S256 é obrigatório; o `redirect_uri` deve ser registado exatamente.
2. O paciente inicia sessão (Google ou e-mail via Firebase), escolhe o registo (próprio ou de um dependente), a duração (30/90/180/365 dias) e autoriza. A plataforma emite um código único (10 minutos).
3. `POST /oauth/token` com `grant_type=authorization_code&code=…&code_verifier=…&redirect_uri=…&client_id=…` (clientes confidenciais adicionam `client_secret`).
   Resposta: `access_token` (30 min), `refresh_token` (30 dias, rotativo), `patient` (o seu ID par para o registo), `grant_id`, `scope`.
4. Refresh: `grant_type=refresh_token`. Cada token de refresh é de uso único. **A apresentação de um token de refresh usado revoga toda a cadeia** (deteção de roubo). Uma duplicata paralela de um pedido de refresh é recusada e pode também revogar a cadeia, pelo que nunca se deve rodar em simultâneo.
5. Revogar: `POST /oauth/revoke` (token + client_id). A revogação de um token de refresh também revoga os seus tokens de acesso.

As respostas de token transportam `Cache-Control: no-store` e `Pragma: no-cache`, como exigido pelo SMART.

### OpenID Connect (`openid fhirUser`)
Solicita `openid fhirUser` juntamente com os scopes do paciente e a resposta do token também contém um `id_token`: um JWT assinado com RS256, com `iss` (o URL base da plataforma), `sub` (o seu ID par para a pessoa), `aud` (o seu `client_id`), `exp`, `iat` e `fhirUser` — o URL absoluto do recurso Patient da pessoa, legível com o token de acesso que acabou de receber. A descoberta encontra-se em `GET /.well-known/openid-configuration`; as chaves públicas em `GET /oauth/jwks` (`kid` no cabeçalho do token). O parâmetro `nonce` ainda não é suportado (é opcional no fluxo authorization-code). `launch/patient` e `offline_access` são aceites; o campo `patient` da resposta do token é o contexto de lançamento.

Outros tipos de concessão: `client_credentials` (clientes confidenciais; comporta-se como uma chave de API), e a concessão de identidade de primeira parte (apenas clientes confiáveis).

### A sua marca na página de consentimento

Uma aplicação pode exibir o seu logótipo e cor de destaque na página de consentimento alojada. Defina-os na consola
(Aplicações → Marca) ou com a API de administração:

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

- **Logótipo:** uma imagem PNG, JPEG ou WebP como um URI de dados, até 64 KB. O conteúdo é verificado, não o tipo declarado;
  SVG não é aceite. A imagem é armazenada com a aplicação e incorporada na página, pelo que a página de consentimento
  não faz qualquer pedido aos seus servidores.
- **Cor de destaque:** `#RRGGBB`, utilizada para o botão principal. O texto branco sobre ela deve manter um contraste de pelo menos
  4.5:1 (WCAG AA); cores mais claras são recusadas.
- Um campo que omite permanece como está; `null` ou uma string vazia remove-o.

O resto da página não muda: a linha "Secured by Anpheros Platform", a lista em linguagem clara do
que a aplicação solicita, e o banner TEST em projetos sandbox permanecem, para que as pessoas possam sempre saber que
o consentimento é detido pela Anpheros. Conectores de IA (MCP) mostram sempre a página Anpheros sem marca de aplicação.

### Scopes
Scopes de paciente SMART v2: `patient/<Type>.<cruds>` com um filtro `?category=<code>` opcional (o único filtro que o servidor impõe; qualquer outro filtro é recusado no momento da autorização). `patient/*.rs` lê tudo; `offline_access` adiciona um token de refresh. A demografia do paciente e o diretório são sempre legíveis sob uma concessão. Um tipo de recurso fora da concessão retorna 403; um paciente fora da concessão retorna 404.

### Ciclo de vida do consentimento
Os consentimentos expiram automaticamente, podem ser revogados pelo paciente a qualquer momento (ecrã Conexões / `/me`), e cada leitura sob um consentimento é registada com o ID da aplicação. Webhooks `consent.granted` / `consent.revoked` notificam o projeto.

## Erros
401 credencial desconhecida/expirada · 403 a credencial existe mas pode não ter permissão para esta ação · 404 o recurso não existe *para si* · 429 limite de taxa atingido (`Retry-After`). Ver [`errors.md`](https://developers.anpheros.com/pt/guides/errors).
