Canjear una API key por un access JWT corto (RFC 8693)
apps/docs/generated/openapi/identity-svc.jsonPágina generada desde
apps/identity-svc/src/app.aot.ts. No se edita a mano:bun run docs:genla regenera ybun run docs:checkfalla si difiere.
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).
| Campo | Valor |
|---|---|
| Servicio | identity-svc |
| operationId | postAuthToken |
Policy (dec-0118 §3) | public |
| Tags | identity |
Requerido: sí.
application/json{
"type": "object",
"required": [
"grant_type",
"subject_token",
"subject_token_type"
],
"properties": {
"grant_type": {
"type": "string",
"const": "urn:ietf:params:oauth:grant-type:token-exchange"
},
"subject_token": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"subject_token_type": {
"type": "string",
"const": "urn:styx:token-type:api-key"
}
}
}application/x-www-form-urlencoded{
"type": "object",
"required": [
"grant_type",
"subject_token",
"subject_token_type"
],
"properties": {
"grant_type": {
"type": "string",
"const": "urn:ietf:params:oauth:grant-type:token-exchange"
},
"subject_token": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"subject_token_type": {
"type": "string",
"const": "urn:styx:token-type:api-key"
}
}
}multipart/form-data{
"type": "object",
"required": [
"grant_type",
"subject_token",
"subject_token_type"
],
"properties": {
"grant_type": {
"type": "string",
"const": "urn:ietf:params:oauth:grant-type:token-exchange"
},
"subject_token": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"subject_token_type": {
"type": "string",
"const": "urn:styx:token-type:api-key"
}
}
}Response for status 200
application/json
{
"type": "object",
"required": [
"access_token",
"token_type",
"expires_in",
"scope"
],
"properties": {
"access_token": {
"type": "string"
},
"token_type": {
"type": "string",
"const": "Bearer"
},
"expires_in": {
"type": "integer",
"minimum": 1
},
"scope": {
"type": "string"
}
}
}Response for status 400
application/json
{
"anyOf": [
{
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string",
"enum": [
"authorization_pending",
"slow_down",
"access_denied",
"expired_token",
"invalid_request",
"invalid_client",
"invalid_scope",
"temporarily_unavailable"
]
},
"error_description": {
"type": "string"
}
}
},
{
"type": "object",
"required": [
"type",
"title",
"status",
"code",
"retryable",
"category"
],
"properties": {
"type": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "number",
"const": 400
},
"code": {
"type": "string",
"enum": [
"IDENTITY_INVALID_INPUT",
"IDENTITY_RETURN_TO_NOT_ALLOWED",
"IDENTITY_OIDC_STATE_MISMATCH",
"IDENTITY_SCOPE_INVALID",
"IDENTITY_DEVICE_AUTHORIZATION_PENDING",
"IDENTITY_DEVICE_SLOW_DOWN",
"IDENTITY_DEVICE_ACCESS_DENIED",
"IDENTITY_DEVICE_CODE_EXPIRED",
"IDENTITY_DEVICE_CLIENT_UNKNOWN",
"IDENTITY_INVITE_INVALID"
]
},
"detail": {
"type": "string"
},
"instance": {
"type": "string"
},
"retryable": {
"type": "boolean"
},
"category": {
"type": "string",
"enum": [
"transient",
"permanent",
"recoverable"
]
}
},
"x-styx-media-type": "application/problem+json"
}
]
}Response for status 401
application/json
{
"anyOf": [
{
"type": "object",
"required": [
"error"
],
"properties": {
"error": {
"type": "string",
"enum": [
"authorization_pending",
"slow_down",
"access_denied",
"expired_token",
"invalid_request",
"invalid_client",
"invalid_scope",
"temporarily_unavailable"
]
},
"error_description": {
"type": "string"
}
}
},
{
"type": "object",
"required": [
"type",
"title",
"status",
"code",
"retryable",
"category"
],
"properties": {
"type": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "number",
"const": 401
},
"code": {
"type": "string",
"enum": [
"IDENTITY_OIDC_CALLBACK_REJECTED",
"IDENTITY_TOKEN_EXPIRED",
"IDENTITY_TOKEN_INVALID",
"IDENTITY_SESSION_REVOKED",
"IDENTITY_REFRESH_TOKEN_REUSED",
"IDENTITY_KEY_INVALID"
]
},
"detail": {
"type": "string"
},
"instance": {
"type": "string"
},
"retryable": {
"type": "boolean"
},
"category": {
"type": "string",
"enum": [
"transient",
"permanent",
"recoverable"
]
}
},
"x-styx-media-type": "application/problem+json"
}
]
}Problem Details (RFC 9457), status 403. Códigos: IDENTITY_CSRF_REJECTED, IDENTITY_FORBIDDEN, IDENTITY_SCOPE_EXCEEDS_GRANTS, IDENTITY_KEY_IN_BROWSER_CONTEXT.
application/problem+json
{
"type": "object",
"required": [
"type",
"title",
"status",
"code",
"retryable",
"category"
],
"properties": {
"type": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "number",
"const": 403
},
"code": {
"type": "string",
"enum": [
"IDENTITY_CSRF_REJECTED",
"IDENTITY_FORBIDDEN",
"IDENTITY_SCOPE_EXCEEDS_GRANTS",
"IDENTITY_KEY_IN_BROWSER_CONTEXT"
]
},
"detail": {
"type": "string"
},
"instance": {
"type": "string"
},
"retryable": {
"type": "boolean"
},
"category": {
"type": "string",
"enum": [
"transient",
"permanent",
"recoverable"
]
}
},
"x-styx-media-type": "application/problem+json"
}Problem Details (RFC 9457), status 404. Códigos: IDENTITY_SESSION_NOT_FOUND, IDENTITY_DEVICE_CODE_UNKNOWN, IDENTITY_KEY_NOT_FOUND, IDENTITY_INVITE_NOT_FOUND.
application/problem+json
{
"type": "object",
"required": [
"type",
"title",
"status",
"code",
"retryable",
"category"
],
"properties": {
"type": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "number",
"const": 404
},
"code": {
"type": "string",
"enum": [
"IDENTITY_SESSION_NOT_FOUND",
"IDENTITY_DEVICE_CODE_UNKNOWN",
"IDENTITY_KEY_NOT_FOUND",
"IDENTITY_INVITE_NOT_FOUND"
]
},
"detail": {
"type": "string"
},
"instance": {
"type": "string"
},
"retryable": {
"type": "boolean"
},
"category": {
"type": "string",
"enum": [
"transient",
"permanent",
"recoverable"
]
}
},
"x-styx-media-type": "application/problem+json"
}Problem Details (RFC 9457), status 409. Códigos: IDENTITY_KEY_LIMIT, IDENTITY_INVITE_EXHAUSTED, IDENTITY_ACCOUNT_EXISTS.
application/problem+json
{
"type": "object",
"required": [
"type",
"title",
"status",
"code",
"retryable",
"category"
],
"properties": {
"type": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "number",
"const": 409
},
"code": {
"type": "string",
"enum": [
"IDENTITY_KEY_LIMIT",
"IDENTITY_INVITE_EXHAUSTED",
"IDENTITY_ACCOUNT_EXISTS"
]
},
"detail": {
"type": "string"
},
"instance": {
"type": "string"
},
"retryable": {
"type": "boolean"
},
"category": {
"type": "string",
"enum": [
"transient",
"permanent",
"recoverable"
]
}
},
"x-styx-media-type": "application/problem+json"
}Problem Details (RFC 9457), status 410. Códigos: IDENTITY_INVITE_EXPIRED.
application/problem+json
{
"type": "object",
"required": [
"type",
"title",
"status",
"code",
"retryable",
"category"
],
"properties": {
"type": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "number",
"const": 410
},
"code": {
"type": "string",
"const": "IDENTITY_INVITE_EXPIRED"
},
"detail": {
"type": "string"
},
"instance": {
"type": "string"
},
"retryable": {
"type": "boolean"
},
"category": {
"type": "string",
"enum": [
"transient",
"permanent",
"recoverable"
]
}
},
"x-styx-media-type": "application/problem+json"
}Problem Details (RFC 9457), status 422. Códigos: validation.
application/problem+json
{
"type": "object",
"required": [
"type",
"title",
"status",
"code"
],
"properties": {
"type": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "number",
"const": 422
},
"code": {
"type": "string",
"const": "validation"
},
"on": {
"type": "string"
},
"property": {
"type": "string"
},
"detail": {
"type": "string"
}
},
"x-styx-media-type": "application/problem+json"
}Problem Details (RFC 9457), status 429. Códigos: IDENTITY_RATE_LIMITED.
application/problem+json
{
"type": "object",
"required": [
"type",
"title",
"status",
"code",
"retryable",
"category"
],
"properties": {
"type": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "number",
"const": 429
},
"code": {
"type": "string",
"const": "IDENTITY_RATE_LIMITED"
},
"detail": {
"type": "string"
},
"instance": {
"type": "string"
},
"retryable": {
"type": "boolean"
},
"category": {
"type": "string",
"enum": [
"transient",
"permanent",
"recoverable"
]
}
},
"x-styx-media-type": "application/problem+json"
}Problem Details (RFC 9457), status 500. Códigos: IDENTITY_INTERNAL.
application/problem+json
{
"type": "object",
"required": [
"type",
"title",
"status",
"code",
"retryable",
"category"
],
"properties": {
"type": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "number",
"const": 500
},
"code": {
"type": "string",
"const": "IDENTITY_INTERNAL"
},
"detail": {
"type": "string"
},
"instance": {
"type": "string"
},
"retryable": {
"type": "boolean"
},
"category": {
"type": "string",
"enum": [
"transient",
"permanent",
"recoverable"
]
}
},
"x-styx-media-type": "application/problem+json"
}Problem Details (RFC 9457), status 503. Códigos: IDENTITY_OIDC_PROVIDER_UNAVAILABLE, IDENTITY_CLIENT_ADDRESS_UNKNOWN, IDENTITY_DEVICE_CAPACITY, IDENTITY_STORE_UNAVAILABLE, IDENTITY_DB_READ_FAILED, IDENTITY_DB_WRITE_FAILED.
application/problem+json
{
"type": "object",
"required": [
"type",
"title",
"status",
"code",
"retryable",
"category"
],
"properties": {
"type": {
"type": "string"
},
"title": {
"type": "string"
},
"status": {
"type": "number",
"const": 503
},
"code": {
"type": "string",
"enum": [
"IDENTITY_OIDC_PROVIDER_UNAVAILABLE",
"IDENTITY_CLIENT_ADDRESS_UNKNOWN",
"IDENTITY_DEVICE_CAPACITY",
"IDENTITY_STORE_UNAVAILABLE",
"IDENTITY_DB_READ_FAILED",
"IDENTITY_DB_WRITE_FAILED"
]
},
"detail": {
"type": "string"
},
"instance": {
"type": "string"
},
"retryable": {
"type": "boolean"
},
"category": {
"type": "string",
"enum": [
"transient",
"permanent",
"recoverable"
]
}
},
"x-styx-media-type": "application/problem+json"
}