# Cómo implementar el consentimiento del paciente con SMART on FHIR

> Tutorial: SMART on FHIR con OAuth 2.1 y PKCE paso a paso — descubrimiento, registro de aplicaciones, pantalla de consentimiento, intercambio de tokens, ámbitos aplicados, rotación de refresco y revocación — y lo que implementa Anpheros.

Source: https://developers.anpheros.com/es/guides/smart-on-fhir-backend

**SMART on FHIR es la forma estándar en que una aplicación obtiene el permiso de una persona para acceder a su registro FHIR: OAuth 2.1 con PKCE para la autorización, ámbitos que indican exactamente qué se puede leer o escribir, y un documento de descubrimiento que indica a la aplicación a dónde ir.** Este tutorial ejecuta todo el flujo contra Anpheros, paso a paso con `curl`: descubrimiento, registro de una aplicación, envío de la persona a la pantalla de consentimiento, intercambio del código, llamada a la API dentro de los ámbitos concedidos, refresco y lo que sucede cuando la persona revoca el acceso. Anpheros es el backend de SMART on FHIR: aloja el servidor de autorización, la pantalla de consentimiento y el servidor FHIR R4, por lo que usted no escribe ninguna interfaz de usuario de inicio de sesión o consentimiento propia.

## Por qué consentimiento y no solo una clave de API

Una clave de API llega a los pacientes que creó su proyecto. El registro existente de una persona (sus propios datos, recopilados por otras aplicaciones, clínicas y laboratorios) es suyo para compartir. Con SMART on FHIR:

- la persona ve, en su idioma, qué aplicación solicita, qué quiere leer o escribir, con qué propósito y por cuánto tiempo;
- su aplicación obtiene solo esos tipos de recursos y acciones, y solo para ese registro;
- cada acceso se registra y es visible para la persona, quien puede revocarlo en cualquier momento;
- la concesión también se almacena como un recurso FHIR `Consent`.

El modelo detrás de esto se describe en [API de salud con consentimiento del paciente](https://developers.anpheros.com/es/guides/healthcare-api-patient-consent) y [Modelo de consentimiento y acceso](https://developers.anpheros.com/es/guides/consent).

## Paso 1: descubrimiento

```bash
curl https://platform.anpheros.com/fhir/R4/.well-known/smart-configuration
```

La respuesta enumera los puntos finales y lo que el servidor soporta (abreviado):

```json
{"issuer": "https://platform.anpheros.com",
 "authorization_endpoint": "https://platform.anpheros.com/oauth/authorize",
 "token_endpoint": "https://platform.anpheros.com/oauth/token",
 "revocation_endpoint": "https://platform.anpheros.com/oauth/revoke",
 "code_challenge_methods_supported": ["S256"],
 "scopes_supported": ["patient/*.rs", "patient/Patient.r", "patient/Observation.rs", "patient/Observation.rs?category=laboratory",
                      "patient/Observation.rs?category=vital-signs", "patient/Observation.c", "patient/Condition.rs",
                      "patient/MedicationStatement.rs", "patient/DocumentReference.rs", "patient/AllergyIntolerance.rs",
                      "offline_access", "launch/patient", "openid", "fhirUser"],
 "capabilities": ["launch-standalone", "client-public", "client-confidential-symmetric", "permission-patient",
                  "permission-offline", "context-standalone-patient", "sso-openid-connect"]}
```

Las bibliotecas cliente de SMART leen este documento y no necesitan ninguna configuración adicional.

## Paso 2: registrar su aplicación

En el [panel](https://platform.anpheros.com/dashboard/), abra su proyecto y agregue una aplicación con su URI de redireccionamiento. O a través de la API de administración:

```bash
curl -X POST https://platform.anpheros.com/admin/projects/$PROJECT/applications \
     -H "Authorization: Bearer $FIREBASE_ID_TOKEN" -H "Content-Type: application/json" -d '{
  "name": "CardioAI", "client_type": "public",
  "redirect_uris": ["https://cardio.example/callback"],
  "purpose": "cardiology follow-up", "privacy_url": "https://cardio.example/privacy"
}'
```

```json
{"id": "app_…", "name": "CardioAI", "client_type": "public", "client_id": "client_Hg6CknNkYlMgN190", "client_secret": null,
 "redirect_uris": ["https://cardio.example/callback"], "purpose": "cardiology follow-up", "status": "active", …}
```

Use `public` para aplicaciones móviles y de navegador, que no pueden mantener un secreto y dependen de PKCE. Use `confidential` para un servidor; su `client_secret` se muestra una vez. El nombre, el propósito y el enlace de privacidad son lo que la persona ve en la pantalla de consentimiento.

## Paso 3: enviar a la persona a la pantalla de consentimiento

Crea un par PKCE. El verificador se queda contigo; solo su hash viaja:

```bash
VERIFIER=$(openssl rand -base64 64 | tr -d '=+/\n' | cut -c1-64)
CHALLENGE=$(printf %s "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 | tr '+/' '-_' | tr -d '=')
```

Luego abre esta dirección en el navegador de la persona (se agregaron saltos de línea para facilitar la lectura):

```
https://platform.anpheros.com/oauth/authorize?response_type=code
  &client_id=client_Hg6CknNkYlMgN190
  &redirect_uri=https://cardio.example/callback
  &scope=openid fhirUser patient/Observation.rs?category=laboratory patient/Condition.rs offline_access
  &state=8c1e…               ← a random value you check on return
  &code_challenge=$CHALLENGE&code_challenge_method=S256
  &purpose=treatment&lang=en
```

Pide lo mínimo que necesitas. Esta aplicación lee resultados de laboratorio y diagnósticos, nada más. `offline_access` otorga un token de actualización, para que la persona no tenga que aprobar nuevamente cada 30 minutos.

La persona inicia sesión en Anpheros, lee la solicitud en lenguaje claro, elige qué registro compartir (el suyo propio, el de un familiar que cuida, o el que tu aplicación creó para ellos) y cuánto tiempo dura el acceso, luego permite o deniega. Regresan a tu URI de redirección:

```
https://cardio.example/callback?code=…&state=8c1e…
```

Verifica que `state` sea el valor que enviaste antes de usar el código.

## Paso 4: Intercambiar el código por tokens

```bash
curl -X POST https://platform.anpheros.com/oauth/token \
  -d grant_type=authorization_code -d client_id=client_Hg6CknNkYlMgN190 \
  -d code=$CODE -d code_verifier=$VERIFIER -d redirect_uri=https://cardio.example/callback
```

```json
{"access_token": "at_…", "token_type": "Bearer", "expires_in": 1800,
 "scope": "patient/Observation.rs?category=laboratory patient/Condition.rs openid fhirUser offline_access",
 "patient": "82bfd321-6a4d-4aea-943a-a62f4d81d419", "grant_id": "grant_…",
 "id_token": "eyJ…", "refresh_token": "rt_…"}
```

- `scope` lista lo que se concedió. Manténgalo con los tokens y muestre solo las características que cubre.
- `patient` es el id del registro para su aplicación. Es por pares: otra aplicación ve a la misma persona bajo un id diferente.
- `id_token` es un token de OpenID Connect cuyo claim `fhirUser` nombra el recurso del paciente.
- El código funciona una vez, y solo con el `code_verifier` correspondiente.

## Paso 5: llamar a la API dentro de los ámbitos

```bash
curl "https://platform.anpheros.com/fhir/R4/Observation?patient=$PATIENT&category=laboratory" -H "Authorization: Bearer $ACCESS_TOKEN"
```

Los resultados de laboratorio vuelven como de costumbre. Solicite algo fuera de la concesión, como medicamentos:

```bash
curl "https://platform.anpheros.com/fhir/R4/MedicationStatement?patient=$PATIENT" -H "Authorization: Bearer $ACCESS_TOKEN"
```

```json
{"resourceType": "OperationOutcome", "issue": [{"severity": "error", "code": "forbidden",
  "diagnostics": "The consent behind this token does not allow 's' on MedicationStatement."}]}
```

Eso es un `403`. Las búsquedas dentro de la concesión también se filtran: con `Observation.rs?category=laboratory`, una búsqueda de todas las observaciones devuelve solo las de laboratorio. Cualquier otro paciente no existe para este token (`404`). La vista REST (`/v1`) y la [API de contexto](https://developers.anpheros.com/es/guides/llm-healthcare-data) aplican los mismos ámbitos.

## Paso 6: Actualizar

Los tokens de acceso duran 30 minutos. Los tokens de actualización duran 30 días y rotan en cada uso:

```bash
curl -X POST https://platform.anpheros.com/oauth/token \
  -d grant_type=refresh_token -d client_id=client_Hg6CknNkYlMgN190 -d refresh_token=$REFRESH_TOKEN
```

Obtienes un nuevo token de acceso y un nuevo token de actualización. Almacena el nuevo inmediatamente. Reutilizar un token de actualización antiguo se considera un robo: falla con `400` y revoca toda la concesión.

## Paso 7: revocación

La persona puede revocar tu acceso desde Anpheros en cualquier momento, y tú puedes revocarlo tú mismo, por ejemplo, cuando se desconecten en tu aplicación:

```bash
curl -X POST https://platform.anpheros.com/oauth/revoke -d token=$REFRESH_TOKEN -d client_id=client_Hg6CknNkYlMgN190
```

A partir de entonces, cada llamada con esa concesión responderá `401`. Maneja esto mostrando a la persona que la conexión ha finalizado y ofreciendo volver a conectar. Suscríbete al [webhook](https://developers.anpheros.com/es/guides/webhooks) `consent.revoked` para enterarte sin esperar una llamada fallida.

## Con los SDKs

Los [SDKs de TypeScript y Dart](https://developers.anpheros.com/es/guides/sdks) realizan los pasos 3 a 6 por usted: `OAuthFlow.authorizeUrl` con un par PKCE generado, `exchange` en el callback, y refresco automático con rotación. Ejemplos completos: [Cómo crear una aplicación de salud con IA con un backend FHIR](https://developers.anpheros.com/es/guides/build-ai-healthcare-app) (TypeScript) y [Cómo crear una aplicación de salud con Flutter](https://developers.anpheros.com/es/guides/healthcare-app-flutter) (Dart).

## Lo que implementa Anpheros

| Parte de SMART | En Anpheros |
|---|---|
| Descubrimiento | `/.well-known/smart-configuration` en la base FHIR, con los endpoints, scopes y métodos PKCE soportados |
| Lanzamiento | lanzamiento independiente (la aplicación se inicia y luego solicita acceso); no se ofrece lanzamiento desde EHR dentro de un sistema clínico |
| Autorización | OAuth 2.1 con PKCE requerido, flujo de código de autorización |
| Scopes | scopes de paciente SMART v2, `patient/<Resource>.<cruds>` con filtros de categoría, además de `openid` y `fhirUser` |
| Identidad | un OpenID Connect `id_token` que nombra al paciente como un recurso FHIR |
| Consentimiento | una pantalla de consentimiento alojada en el idioma del paciente, con la duración elegida por el paciente, reflejada como un `Consent` FHIR |
| Tokens | tokens de acceso de 30 minutos, tokens de actualización rotativos de 30 días vinculados al consentimiento, revocación |
| Conformidad | la declaración de capacidad declara el servicio de seguridad SMART; el grupo "Standalone Launch" del kit de pruebas Inferno SMART App Launch STU2 pasa 22 de 22 pruebas (ejecución del 28 de septiembre de 2026); los otros grupos y kits de pruebas de Inferno no se han ejecutado |

La escritura funciona de la misma manera: escribir scopes (`patient/Observation.c`, `.u`, `.d`) permite a su aplicación crear, actualizar o eliminar dentro del registro. Todo lo escrito lleva su aplicación como autor, los reintentos con una clave de idempotencia nunca duplican una medición, y las eliminaciones son blandas y conservan el historial ([Medical data API](https://developers.anpheros.com/es/guides/medical-data-api)).

## Lo que aún no está disponible

- Lanzamiento desde EHR (la aplicación se abre desde dentro de un sistema hospitalario con un contexto de lanzamiento).
- `system/` ámbitos para servicios backend; las organizaciones utilizan claves API en su lugar.
- Exportación de datos masivos (`$export`); `$everything` sobre un paciente está disponible.

Estos se enumeran con el resto en [Versionamiento y deprecación](https://developers.anpheros.com/es/guides/versioning), y la declaración de capacidad es siempre la fuente autorizada.

## Preguntas frecuentes

### ¿Qué es SMART on FHIR?
Un estándar abierto, basado en OAuth 2.0/2.1 y OpenID Connect, que define cómo una aplicación solicita acceso a un registro FHIR, qué ámbitos describen ese acceso y cómo el servidor anuncia sus puntos de conexión. Cualquier biblioteca cliente compatible con SMART puede utilizar cualquier servidor compatible con SMART.

### ¿Necesito PKCE?
Sí. Anpheros requiere PKCE con `S256` para cada flujo de código de autorización, tanto para clientes públicos como confidenciales. Evita que un código de autorización interceptado sea utilizado por cualquier otra persona.

### ¿Qué sucede si la persona dice que no?
Regresan a su URI de redirección con `error=access_denied` y su `state`, y sin código. Explique lo que necesita la función y permítales intentarlo de nuevo; las llamadas fuera de una concesión siempre responden `403`.

### ¿Puede un padre dar consentimiento para un hijo?
Sí. En la pantalla de consentimiento, una persona puede elegir un registro que le interese, como el de un hijo, si está vinculado a su cuenta. La concesión se aplica solo a ese registro.

## Relacionado

- [Autenticación y OAuth](https://developers.anpheros.com/es/guides/authentication): claves API, tokens y duraciones en detalle
- [API de salud con consentimiento del paciente](https://developers.anpheros.com/es/guides/healthcare-api-patient-consent): cómo el consentimiento cambia el diseño de su aplicación
- [Modelo de consentimiento y acceso](https://developers.anpheros.com/es/guides/consent)
- [Plataforma FHIR](https://developers.anpheros.com/es/guides/fhir)
- [Crear una aplicación de salud](https://developers.anpheros.com/es/guides/build-a-healthcare-app)
