PAFA — Autorización (0.1.0)

Download OpenAPI specification:

URL: https://pafa.ar License: Apache 2.0

La superficie del authorization server de una entidad transmisora, tal como la exige el perfil: la metadata de descubrimiento con los valores obligatorios, PAR, autorización, token, introspección y revocación, y el tipo pafa:consent de authorization_details que ata el token al consentimiento. Es el contrato mínimo que hace implementables las decisiones de la capa. El motivo de cada valor está en el escrito.

Descubrimiento

La metadata que hace verificable el perfil con un GET.

Metadata del authorization server

RFC 8414 / OpenID Connect Discovery. El perfil exige los valores que el schema fija: una implementación que publique otros no es conforme. Es el lugar donde «sólo FAPI 2.0» se vuelve verificable con un GET.

Responses

Response Schema: application/json
issuer
required
string <uri>

Uno por entidad, descubierto desde el directorio.

authorization_endpoint
required
string <uri>
token_endpoint
required
string <uri>
pushed_authorization_request_endpoint
required
string <uri>
require_pushed_authorization_requests
required
boolean
Value: true

PAR es obligatorio.

introspection_endpoint
required
string <uri>
revocation_endpoint
required
string <uri>
jwks_uri
required
string <uri>
response_types_supported
required
Array of strings = 1 items
Items Value: "code"

Sólo code. Ni code id_token ni ninguna respuesta firmada en el canal frontal.

grant_types_supported
required
Array of strings = 3 items unique
Items Enum: "authorization_code" "refresh_token" "client_credentials"
code_challenge_methods_supported
required
Array of strings = 1 items
Items Value: "S256"

Sólo S256.

token_endpoint_auth_methods_supported
required
Array of strings = 2 items unique
Items Enum: "tls_client_auth" "private_key_jwt"

Los dos, siempre (el escrito, decisión 4).

token_endpoint_auth_signing_alg_values_supported
required
Array of strings = 1 items
Items Value: "PS256"
tls_client_certificate_bound_access_tokens
required
boolean
Value: true

El transmisor acepta la atadura por certificado.

dpop_signing_alg_values_supported
required
Array of strings = 1 items
Items Value: "PS256"

El transmisor acepta la atadura por DPoP; los proofs se firman con PS256.

authorization_details_types_supported
required
Array of strings non-empty
Items Value: "pafa:consent"
authorization_response_iss_parameter_supported
required
boolean
Value: true
id_token_signing_alg_values_supported
required
Array of strings = 1 items
Items Value: "PS256"
subject_types_supported
required
Array of strings non-empty
Items Enum: "public" "pairwise"
scopes_supported
required
Array of strings >= 3 items unique
Items Enum: "openid" "consents" "accounts"

El scope dice qué API; el consentimiento y sus permisos viajan en authorization_details, nunca dentro del scope.

required
object

Los mismos endpoints bajo un host donde el TLS lo termina la propia entidad y el certificado del cliente llega al authorization server. Obligatorio: es por donde entra el cliente que ató por certificado.

registration_endpoint
string <uri>

Opcional. Registro dinámico de clientes (RFC 7591) con el software statement emitido por el directorio. El perfil fija que un receptor activo en el directorio opera sin alta bilateral previa, y deja abierto por qué mecanismo le llega su metadata al transmisor —registro dinámico o sincronización del padrón—. Es capa 1 y no se describe acá.

response_modes_supported
Array of strings
Items Value: "query"

Si se publica, sólo query.

request_parameter_supported
boolean
Value: false

No se aceptan request objects.

request_uri_parameter_supported
boolean
Value: true
claims_supported
Array of strings

Qué claims de la persona van en el id_token es una pregunta abierta del perfil.

Response samples

Content type
application/json
{}

Autorización

PAR y la autorización con la persona presente.

Pushed Authorization Request

RFC 9126. Obligatorio: todo pedido de autorización empieza acá, autenticado como cliente (tls_client_auth o private_key_jwt), y el navegador después sólo lleva el request_uri. Acá viaja el alcance, en authorization_details con un elemento de tipo pafa:consent que nombra el consentimiento creado en la parte 1. El authorization server valida en este momento que el consentimiento existe, que es del cliente que pide y que está en AWAITING_AUTHORISATION; si no, responde 400 con invalid_authorization_details.

No se aceptan request objects (request): FAPI 2.0 no los necesita y el perfil no los admite. Un pedido con response_type distinto de code, sin code_challenge, o con code_challenge_method distinto de S256, se rechaza.

Request Body schema: application/x-www-form-urlencoded
required
client_id
required
string
response_type
required
string
Value: "code"
redirect_uri
required
string <uri>

Una de las registradas en el alta por DCR; exacta, sin comodines.

scope
required
string

Espacio-separado. openid y las APIs que el consentimiento habilita; nunca el consentimiento adentro.

code_challenge
required
string

PKCE, RFC 7636.

code_challenge_method
required
string
Value: "S256"
authorization_details
required
string

JSON serializado: un arreglo con un elemento ConsentAuthorizationDetails. Un solo consentimiento por pedido de autorización.

state
required
string
nonce
string

Obligatorio si se pide openid.

client_assertion_type
string
Value: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"

Con private_key_jwt. Con tls_client_auth no va, y el certificado viaja en el handshake.

client_assertion
string

JWT firmado con PS256 por la clave que el directorio atribuye al cliente.

Responses

Response Schema: application/json
request_uri
required
string

Referencia opaca de un solo uso al pedido.

expires_in
required
integer >= 1

Segundos de vigencia del request_uri. El perfil no fija el valor: es una pregunta abierta (el escrito, § Lo que el perfil todavía no fija).

Response samples

Content type
application/json
{
  • "request_uri": "urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c",
  • "expires_in": 1
}

Autorización, con la persona presente

El navegador de la persona llega acá con el request_uri de PAR y nada más. La entidad transmisora la autentica con autenticación fuerte —cada vez, antes de emitir el código, y dejando traza; el perfil no dicta los factores (el escrito, decisión 7)—, le muestra el consentimiento en su propia pantalla, con su marca (decisión 8), y la persona elige las cuentas y autoriza o rechaza. El resultado se refleja en el recurso consentimiento (AUTHORISED o REJECTED) y, si autorizó, el navegador vuelve al redirect_uri registrado con code, state e iss (RFC 9207). Nunca vuelve con un id_token ni con una respuesta firmada: el canal frontal no transporta estado.

query Parameters
client_id
required
string
request_uri
required
string
Example: request_uri=urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c

Responses

Response Schema: text/html
string

Token

Emisión de access, refresh e id tokens, con su atadura.

Emisión de tokens

RFC 6749 con las restricciones del perfil. El cliente se autentica con tls_client_auth (certificado presentado en el handshake, sobre el alias mTLS) o con private_key_jwt (client_assertion), y en los dos casos con una clave o certificado que el directorio atribuye a esa entidad (el escrito, decisión 4).

Atadura del token (decisión 3): si el pedido llega por el alias mTLS, el access token queda atado al certificado (cnf.x5t#S256); si llega con un header DPoP, queda atado a la clave del proof (cnf.jkt) y token_type es DPoP. Un cliente usa siempre la misma atadura; el transmisor acepta las dos. Un pedido sin ninguna de las dos se rechaza con invalid_client.

authorization_code: con code_verifier (PKCE). La respuesta incluye el authorization_details concedido, con el consentimiento ya en AUTHORISED.

refresh_token: no exige offline_access. Antes de emitir, el authorization server verifica que el consentimiento siga AUTHORISED; si no, destruye lo emitido y responde invalid_grant (decisión 6).

client_credentials: para crear y gestionar consentimientos (scope consents), sin authorization_details.

header Parameters
DPoP
string

Proof DPoP (RFC 9449), firmado con PS256, cuando el cliente ata sus tokens por clave. Si el pedido llega por el alias mTLS con certificado, este header se ignora: la atadura es una sola.

Request Body schema: application/x-www-form-urlencoded
required
grant_type
required
string
Enum: "authorization_code" "refresh_token" "client_credentials"
client_id
required
string
code
string

Con authorization_code.

redirect_uri
string <uri>

Con authorization_code; la misma del pedido.

code_verifier
string

Con authorization_code. PKCE, RFC 7636.

refresh_token
string

Con refresh_token.

scope
string

Con client_credentials: consents.

client_assertion_type
string
Value: "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
client_assertion
string

Responses

Response Headers
Cache-Control
string
Value: "no-store"
Response Schema: application/json
access_token
required
string

Opaco para el cliente y para el servidor de recursos.

token_type
required
string
Enum: "Bearer" "DPoP"

Bearer si el token está atado por certificado; DPoP si está atado por clave. Nunca un bearer sin atadura.

expires_in
required
integer >= 1
refresh_token
string

Con authorization_code y refresh_token. Vive lo que vive el consentimiento: su techo es expirationDateTime, y un consentimiento revocado lo invalida.

scope
string
id_token
string

Sólo si se pidió openid. JWT firmado con PS256, sólo por el canal trasero.

Array of objects (ConsentAuthorizationDetails)

Lo concedido, con las cuentas elegidas. No va en client_credentials.

Response samples

Content type
application/json
{
  • "access_token": "string",
  • "token_type": "Bearer",
  • "expires_in": 1,
  • "refresh_token": "string",
  • "scope": "string",
  • "id_token": "string",
  • "authorization_details": [
    • {
      }
    ]
}

Introspección y revocación

Lo que el servidor de recursos y el cliente le preguntan o le piden al authorization server sobre un token.

Introspección de un access token

RFC 7662. La llama el servidor de recursos de la misma entidad, autenticado como cliente interno del authorization server, en cada pedido de datos: los access tokens son opacos y ésta es la única forma de saber si siguen vigentes y a qué consentimiento responden (el escrito, decisión 6). La respuesta trae el authorization_details, la atadura (cnf) que el servidor de recursos tiene que verificar contra el certificado o el proof que acompañan al pedido, y la traza de la autenticación de la persona.

Cuando el consentimiento pasó a REVOKED o EXPIRED, el servidor de recursos rechaza aunque active todavía diga true: el dato se protege por el estado del consentimiento, y la limpieza del token es eventual. Por eso la respuesta lleva consent_status además de active.

Request Body schema: application/x-www-form-urlencoded
required
token
required
string
token_type_hint
string
Enum: "access_token" "refresh_token"

Responses

Response Schema: application/json
active
required
boolean

Que el token existe y no venció. No alcanza para servir datos: el servidor de recursos mira además consent_status.

client_id
string
sub
string

Identificador de la persona en la entidad, estable y opaco.

scope
string
exp
integer

Vencimiento, en segundos desde epoch.

iat
integer
token_type
string
Enum: "Bearer" "DPoP"
object

La atadura. Exactamente una de las dos claves.

Array of objects (ConsentAuthorizationDetails)
consent_status
string
Enum: "AWAITING_AUTHORISATION" "AUTHORISED" "REJECTED" "REVOKED" "EXPIRED"

El estado del consentimiento que el authorization server ve en este momento. El servidor de recursos sirve datos sólo con AUTHORISED.

auth_time
integer

Cuándo se autenticó la persona para esta autorización, en segundos desde epoch. Es la traza que exige la decisión 7.

acr
string

Cómo se autenticó, en los términos de la entidad; el perfil no fija los valores.

Response samples

Content type
application/json
{
  • "active": true,
  • "client_id": "string",
  • "sub": "string",
  • "scope": "string",
  • "exp": 0,
  • "iat": 0,
  • "token_type": "Bearer",
  • "cnf": {
    • "x5t#S256": "string",
    • "jkt": "string"
    },
  • "authorization_details": [
    • {
      }
    ],
  • "consent_status": "AWAITING_AUTHORISATION",
  • "auth_time": 0,
  • "acr": "string"
}

Revocación de un token

RFC 7009. El cliente autenticado revoca un access o refresh token propio. No sustituye a la revocación del consentimiento (DELETE /consents/{consentId} de la parte 1): revocar el consentimiento revoca los tokens; revocar un token no toca el consentimiento.

Request Body schema: application/x-www-form-urlencoded
required
token
required
string
token_type_hint
string
Enum: "access_token" "refresh_token"

Responses

Response samples

Content type
application/json
{
  • "error": "invalid_authorization_details",
  • "error_description": "string"
}