identity-svc

identity-svc

Identidad de styx: login OIDC ligado al navegador con sesión por cookie (vía el BFF), refresh de clientes nativos, logout con CSRF, revocación de sesiones y resolución del principal de un access token. Publica las claves de firma (JWKS) con las que los servicios verifican los tokens en local. ## Errores Todo error es un Problem Details (RFC 9457) servido como `application/problem+json`, con `type`, `title`, `status` y un `code` estable. Los errores de dominio añaden `retryable` y `category` (`transient`, `permanent` o `recoverable`). Los de framework son `400 parse` (JSON roto), `404 not-found` (ruta inexistente) y `422 validation` (con `on`; `property` y `detail` sólo fuera de producción). Las denegaciones del Bearer son `401 unauthenticated` o `reauth-required`, `403 forbidden` y `429 rate-limited` (con `Retry-After`). Ningún problem repite el valor recibido y un recurso de otro actor responde 404, sin oráculo.

GET
/.well-known/jwks.json

JWKS (RFC 7517) con las claves con las que identity-svc firma los access tokens. Cacheable 5 min; por el bus el mismo contenido es qry.identity.jwks.

Response Body

application/json

curl -X GET "https://example.com/.well-known/jwks.json"
{  "keys": [    {      "alg": "string",      "crv": "string",      "kid": "string",      "kty": "string",      "use": "string",      "x": "string"    }  ]}
POST
/auth/admin/actors/{actorId}/revoke

Revoca todas las sesiones del actor indicado. Exige rol admin y un login reciente (401 reauth-required si no).

Acceso: Bearer de identity con policy role:admin, con login reciente.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Path Parameters

actorId*string
Length1 <= length <= 128

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/admin/actors/string/revoke"
{  "revoked": 0}
POST
/auth/admin/sessions/{sessionId}/revoke

Revoca la sesión indicada de cualquier actor. Exige rol admin y un login reciente (401 reauth-required si no).

Acceso: Bearer de identity con policy role:admin, con login reciente.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Path Parameters

sessionId*string
Formatuuid

Response Body

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/admin/sessions/497f6eca-6276-4993-bfeb-53cbbbba6f08/revoke"
Empty
POST
/auth/device/approve

Autenticado. Los scopes finales son lo pedido ∩ lo que el aprobador puede; un dispositivo nunca recibe más que quien lo aprueba. El CSRF lo exige el BFF de la web (la ruta sólo acepta Bearer, sin credencial ambiente).

Acceso: Bearer de identity con policy authenticated.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Request Body

TypeScript Definitions

Use the request body type in TypeScript.

scopes?array<>
Itemsitems <= 64
userCode*string
Length4 <= length <= 16

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/device/approve" \  -H "Content-Type: application/json" \  -d '{    "userCode": "string"  }'
{  "decision": "approved"}
POST
/auth/device/code

Anónimo, con límite por IP y tope global de pendientes. Devuelve device_code (secreto del dispositivo), user_code de 8 dígitos y la página de verificación de la web. Acepta application/x-www-form-urlencoded y JSON. Errores en formato OAuth.

Request Body

TypeScript Definitions

Use the request body type in TypeScript.

client_id*string
Length1 <= length <= 64
device_kind?string

Value in

  • "cli"
  • "tv"
  • "native"
device_name*string
Match^[^\u0000-\u001f\u007f-\u009f]+$
Length1 <= length <= 64
scope?string
Lengthlength <= 1024

Response Body

application/json

application/json

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/device/code" \  -H "Content-Type: application/json" \  -d '{    "client_id": "string",    "device_name": "string"  }'
{  "device_code": "string",  "expires_in": 1,  "interval": 1,  "user_code": "string",  "verification_uri": "string",  "verification_uri_complete": "string"}
POST
/auth/device/deny

Acceso: Bearer de identity con policy authenticated.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Request Body

TypeScript Definitions

Use the request body type in TypeScript.

userCode*string
Length4 <= length <= 16

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/device/deny" \  -H "Content-Type: application/json" \  -d '{    "userCode": "string"  }'
{  "decision": "approved"}
GET
/auth/device/lookup

Autenticado. Cuenta como intento contra la sesión y la cuenta (5/min, 20/h por defecto). Una credencial pat no puede.

Acceso: Bearer de identity con policy authenticated.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Query Parameters

user_code*string
Length4 <= length <= 16

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/auth/device/lookup?user_code=string"
{  "clientId": "string",  "deviceKind": "string",  "deviceName": "string",  "expiresAt": 0,  "requestIp": "string",  "requestedAt": 0,  "requestedScopes": [    "string"  ],  "userCode": "string"}
POST
/auth/device/token

Sondea con el device_code. authorization_pending / slow_down / access_denied / expired_token como errores OAuth (400). Aprobado: access JWT (cred=device) + refresh opaco de dec-0113, una sola vez.

Request Body

TypeScript Definitions

Use the request body type in TypeScript.

client_id*string
Length1 <= length <= 64
device_code*string
Length1 <= length <= 128
grant_type*string

Response Body

application/json

application/json

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/device/token" \  -H "Content-Type: application/json" \  -d '{    "client_id": "string",    "device_code": "string",    "grant_type": "urn:ietf:params:oauth:grant-type:device_code"  }'
{  "access_token": "string",  "expires_in": 1,  "refresh_token": "string",  "scope": "string",  "token_type": "Bearer"}
GET
/auth/invitations

Las más recientes primero, con su estado, usos y las cuentas creadas.

Acceso: Bearer de identity con policy resource:invitation:read.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Query Parameters

status?string

Value in

  • "active"
  • "exhausted"
  • "expired"
  • "revoked"
limit?integer
Range1 <= value <= 100

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/auth/invitations"
{  "invitations": [    {      "createdAt": 0,      "createdBy": "string",      "email": "string",      "expiresAt": 0,      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",      "maxUses": 1,      "note": "string",      "redeemedBy": [        "string"      ],      "revokedAt": 0,      "role": "restricted",      "status": "active",      "uses": 0    }  ]}
POST
/auth/invitations

Caducidad obligatoria (tope IDENTITY_INVITE_MAX_TTL_S), rol restricted o member (admin y owner nunca por invitación) y, opcional, ligada a un email. El token sólo se devuelve aquí; identity guarda su hash.

Acceso: Bearer de identity con policy resource:invitation:create, con login reciente.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Request Body

Invitación de un solo uso con caducidad obligatoria.

TypeScript Definitions

Use the request body type in TypeScript.

Invitación de un solo uso con caducidad obligatoria.

email?string

Liga la invitación a un email: el id_token del login debe traerlo igual.

Formatemail
Lengthlength <= 254
expiresInS*integer
Range60 <= value <= 2592000
note?string
Lengthlength <= 200
role?string

Value in

  • "restricted"
  • "member"

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/invitations" \  -H "Content-Type: application/json" \  -d '{    "expiresInS": 60  }'
{  "invitation": {    "createdAt": 0,    "createdBy": "string",    "email": "string",    "expiresAt": 0,    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",    "maxUses": 1,    "note": "string",    "redeemedBy": [      "string"    ],    "revokedAt": 0,    "role": "restricted",    "status": "active",    "uses": 0  },  "token": "string"}
POST
/auth/invitations/preview

Público y con el rate-limit por IP de /auth/*. Un token mal formado, inexistente o revocado da el mismo error (sin oráculo); sólo quien tiene un token válido ve que caducó o se agotó. No devuelve datos personales.

Request Body

Token a inspeccionar sin consumirlo.

TypeScript Definitions

Use the request body type in TypeScript.

Token a inspeccionar sin consumirlo.

token*string
Match^styx_inv_[A-Za-z0-9_-]{43}$
Lengthlength <= 52

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/invitations/preview" \  -H "Content-Type: application/json" \  -d '{    "token": "string"  }'
{  "emailBound": true,  "expiresAt": 0,  "role": "restricted"}
GET
/auth/invitations/{id}

Acceso: Bearer de identity con policy resource:invitation:read.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Path Parameters

id*string
Formatuuid

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/auth/invitations/497f6eca-6276-4993-bfeb-53cbbbba6f08"
{  "createdAt": 0,  "createdBy": "string",  "email": "string",  "expiresAt": 0,  "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",  "maxUses": 1,  "note": "string",  "redeemedBy": [    "string"  ],  "revokedAt": 0,  "role": "restricted",  "status": "active",  "uses": 0}
DELETE
/auth/invitations/{id}

Idempotente. No afecta a las cuentas ya creadas con ella; borrarlas es una operación aparte.

Acceso: Bearer de identity con policy resource:invitation:create, con login reciente.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Path Parameters

id*string
Formatuuid

Response Body

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X DELETE "https://example.com/auth/invitations/497f6eca-6276-4993-bfeb-53cbbbba6f08"
Empty
GET
/auth/keys

Acceso: Bearer de identity con policy resource:api-key:list.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/auth/keys"
{  "keys": [    {      "createdAt": 0,      "displayPrefix": "string",      "expiresAt": 0,      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",      "lastUsedAt": 0,      "name": "string",      "revokedAt": 0,      "scopes": [        "string"      ]    }  ]}
POST
/auth/keys

Scopes obligatorios y ⊆ permisos actuales del creador; caducidad obligatoria con tope. Una credencial pat no puede crear keys. Sólo se guarda el SHA-256.

Acceso: Bearer de identity con policy resource:api-key:create, con login reciente.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Request Body

TypeScript Definitions

Use the request body type in TypeScript.

expiresInSeconds?integer
Range60 <= value
name*string
Length1 <= length <= 64
scopes*array<>
Items1 <= items <= 64

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/keys" \  -H "Content-Type: application/json" \  -d '{    "name": "string",    "scopes": [      "string"    ]  }'
{  "key": {    "createdAt": 0,    "displayPrefix": "string",    "expiresAt": 0,    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",    "lastUsedAt": 0,    "name": "string",    "revokedAt": 0,    "scopes": [      "string"    ]  },  "token": "string"}
DELETE
/auth/keys/{keyId}

Una key ajena o inexistente es 404 (sin oráculo).

Acceso: Bearer de identity con policy resource:api-key:revoke.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Path Parameters

keyId*string
Formatuuid

Response Body

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X DELETE "https://example.com/auth/keys/497f6eca-6276-4993-bfeb-53cbbbba6f08"
Empty
POST
/auth/logout

Cliente nativo: refresh token en el body. Navegador: cookie de sesión más CSRF de doble barrera (Sec-Fetch-Site u Origin exacto, y el token CSRF de la sesión); responde 204 con Clear-Site-Data.

Authorization

sessionCookie
__Host-styx_sess<token>

Cookie de sesión del navegador. Sólo la acepta identity-svc en /auth/logout, con CSRF de doble barrera; llega a través del BFF.

In: cookie

Response Body

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/logout"
Empty
GET
/auth/oidc/callback

Valida el callback contra el login sellado en la cookie de binding, crea la sesión de navegador y redirige a returnTo con la cookie __Host-styx_sess. Si falla, borra la cookie de binding.

Response Body

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/auth/oidc/callback"
{  "category": "transient",  "code": "IDENTITY_INVALID_INPUT",  "detail": "string",  "instance": "string",  "retryable": true,  "status": 400,  "title": "string",  "type": "string"}
GET
/auth/oidc/start

Prepara el login (PKCE, state y nonce sellados en la cookie de binding __Host-styx_login) y redirige al OP. returnTo tiene que pertenecer a un origen de la web. Con invite, la invitación se comprueba sin consumirla, viaja sellada con el login y se canjea en el callback (dec-0125 §7.3).

Query Parameters

returnTo*string
Formaturl
Lengthlength <= 2048
invite?string

Token de invitación (dec-0125 §7.3): se valida sin consumirlo, viaja sellado en el login pendiente y se canjea de forma atómica en el callback.

Match^styx_inv_[A-Za-z0-9_-]{43}$
Lengthlength <= 52

Response Body

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/auth/oidc/start?returnTo=string"
{  "category": "transient",  "code": "IDENTITY_INVALID_INPUT",  "detail": "string",  "instance": "string",  "retryable": true,  "status": 400,  "title": "string",  "type": "string"}
POST
/auth/refresh

Sólo clientes nativos: refresh token en el body JSON. Una petición con la cookie de sesión del navegador se rechaza (el navegador nunca recibe access tokens). Un refresh token ya rotado que vuelve a presentarse se rechaza (IDENTITY_REFRESH_TOKEN_REUSED) y queda en el audit.

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/refresh"
{  "accessToken": "string",  "expiresAt": 0,  "refreshToken": "string",  "tokenType": "Bearer"}
GET
/auth/session

Devuelve el principal del access token tras verificarlo en local y contra la sesión viva.

Acceso: Bearer de identity con policy authenticated.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X GET "https://example.com/auth/session"
{  "actorId": "string",  "authTime": 0,  "cred": "browser",  "displayName": "string",  "expiresAt": 0,  "role": "restricted",  "scopes": [    "string"  ],  "sessionId": "string"}
POST
/auth/sessions/revoke-all

Revoca todas las sesiones del actor del token, también la actual.

Acceso: Bearer de identity con policy resource:actor:revoke-sessions.

Authorization

bearerAuth
AuthorizationBearer <token>

Access token de identity-svc (JWT EdDSA, caducidad corta). Se verifica en local y después contra la sesión viva (revocation-aware).

In: header

Response Body

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/sessions/revoke-all"
{  "revoked": 0}
POST
/auth/token

La key se presenta en subject_token (nunca en la URL). Rechaza con IDENTITY_KEY_IN_BROWSER_CONTEXT cualquier canje con Cookie, Origin o Sec-Fetch-*. El JWT lleva cred=pat y scp; caduca en ≤ 5 min y el principal se resuelve contra la key viva (revocarla corta el acceso en la siguiente resolución).

Request Body

TypeScript Definitions

Use the request body type in TypeScript.

grant_type*string
subject_token*string
Length1 <= length <= 128
subject_token_type*string

Response Body

application/json

application/json

application/json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

application/problem+json

curl -X POST "https://example.com/auth/token" \  -H "Content-Type: application/json" \  -d '{    "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",    "subject_token": "string",    "subject_token_type": "urn:styx:token-type:api-key"  }'
{  "access_token": "string",  "expires_in": 1,  "scope": "string",  "token_type": "Bearer"}
GET
/health

Responde 200 mientras el proceso atiende peticiones; no comprueba dependencias. La usan el HEALTHCHECK de la imagen y el compose (con GET: HEAD es opt-in en Elysia 2).

Response Body

application/json

curl -X GET "https://example.com/health"
{  "status": "ok",  "timestamp": 0,  "uptime": 0,  "version": "string"}
GET
/ready

Prueba cada dependencia registrada con un plazo de 3 s. 503 si falla alguna crítica; las no críticas sólo se informan.

Response Body

application/json

application/json

curl -X GET "https://example.com/ready"
{  "checks": [    {      "critical": true,      "error": "string",      "name": "string",      "ok": true    }  ],  "status": "ready"}
GET
/version

Response Body

application/json

curl -X GET "https://example.com/version"
{  "commit": "string",  "component": "string",  "train": "string",  "version": "string"}