Autenticación
Flujo Authorization Code
Autenticación - Authorization endpoint
El endpoint de autorización permite al sistema cliente ser autorizado por parte del usuario final.
El usuario debe inicialmente autenticarse en el Proveedor de Identidad y posteriormente autorizar al cliente por lo que este paso se lo realiza en un navegador web con la interacción del usuario final.
Para el proceso de autenticación se deberá seguir con los siguientes pasos:
1. Generar valores aleatorios:
Para proteger la seguridad de los ciudadanos mediante la prevención de ataques de falsificación de solicitudes se debe crear un par de tokens de sesión únicos para mantener el estado entre el sistema cliente y Proveedor de Identidad, estos dos tokens son denominados state y nonce
Los valores deben ser generados de manera aleatoria y debe ser conservados para ser validados más adelante (se sugiere generar una cadena de al menos 30 caracteres).
Sólo si se está integrando una aplicación móvil adicionalmente debe generar los siguientes códigos:
- code_verifier:
Es recomendable que sea una cadena aleatoria criptográfica de alta entropía que utiliza los caracteres no reservados [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~", con una longitud mínima de 43 caracteres y una longitud máxima de 128 caracteres.
Ejemplo:
code_verifier = 2AcLLc82Tdu8HUESuVxJeL28DGavoDQfpJGSjLLC3FfJfpwtWR0efZaTUgHRL3wTvkwUJ9nwuTd9QXSA
- code_challenge:
Para generar el code_challenge se recomienda utilizar la codificación SHA256, para la generación de este código es necesario usar la siguiente fórmula:
code_challenge = BASE64URL_ENCODE(SHA256(ASCII(code_verifier)))
Ejemplo:
code_challenge = mKlsmdDCnEeIatFQbv0CJugIeiaIcU_IfKfuBOfQeJE
2. Enviar solicitud al Proveedor de Identidad
Siempre en el navegador web, se debe enviar la petición HTTP al valor del campo authorization_endpoint que se obtiene del punto anterior, con los siguientes parámetros:
| Parámetro | Condición | Descripción |
|---|---|---|
| client_id | requerido | Es el identificador del Sistema Cliente, este identificador se obtiene cuando se registra el Sistema Cliente en el Sistema Proveedor de Identidad. |
| response_type | requerido | Parámetro utilizado en el flujo openID connect y siempre deberá ser code. |
| redirect_uri | requerido | Es la url que recibirá el código de acceso tras la autenticación en el proveedor de identidad. Debe estar codificado en formato url y debe ser la misma que se proporcionó en el registro del sistema cliente. |
| scope | requerido | Los scopes enviados debe ser un subconjunto de los scopes solicitados en la creación del cliente. Los scopes deben estar separados por un espacio. |
| state | requerido | Valor del token de estado y de sesión única creada en el paso anterior. |
| nonce | requerido | Valor aleatorio generado en el sistema cliente. Es utilizada para la posterior verificación del id_token y evita replay attacks. |
| prompt | opcional | prompt=login: este parámetro sirve para asegurarse de que el Usuario final está presente en la sesión actual (si se envía este parámetro el proveedor de identidad siempre solicitará las credenciales al ciudadano en el inicio de sesión). prompt=consent: este parámetro sirve para solicitar refresh_token |
| code_challenge_method | opcional | Algoritmo con el que se obtuvo el hash para generar el code_challenge, si utilizó SHA256 enviar el valor: S256 (este valor es requerido sólo si el cliente es una aplicación móvil) |
Ejemplo de solicitud:
https://<base-url-proveedor-identidad>/auth?response_type=code&client_id=mGntc6oKqoFMCRZArKDad&state=509ccc2713049e6efea071a9c34f6f45&nonce=231301a1afe20d88ca963ee84c3929c3&redirect_uri=https://dominio/app/login&scope=openid%20profile
Ejemplo de solicitud que siempre pide las credenciales al ciudadano:
https://<base-url-proveedor-identidad>/auth?response_type=code&client_id=mGntc6oKqoFMCRZArKDad&state=509ccc2713049e6efea071a9c34f6f45&nonce=231301a1afe20d88ca963ee84c3929c3&redirect_uri=https://dominio/app/login&scope=openid%20profile&prompt=login
Ejemplo de solicitud de una aplicación móvil
https://<base-url-proveedor-identidad>/auth?response_type=code&client_id=yhOiNSDcWeXQEz2Hs7DeW&state=509ccc2713049e6efea071a9c34f6f45&redirect_uri=net.openid.appauthdemo:/oauth2redirect&scope=openid%20profile&code_challenge=mKlsmdDCnEeIatFQbv0CJugIeiaIcU_IfKfuBOfQeJE&code_challenge_method=S256
Una vez solicitada la URL el usuario final se autenticará en el dominio del Proveedor de Identidad y autorizará al sistema cliente.
3. Redirección al sistema cliente
Una vez que el ciudadano haya procedido a autenticarse en el proveedor de Identidad el mismo redirigirá al Sistema Cliente (a la URL registrada como redirect_uri) con un código de autorización (authorization code), los códigos state y nonce, en caso de éxito; por el contrario, un código de error en caso de que la autenticación no fuera exitosa, petición malformada o se produjera un error.
Sobre el código de autorización es necesario mencionar que es un código intermedio, opaco y que puede ser usado solo una vez, es necesario para obtener el token de acceso y eventualmente un token de refresh.
En caso de retorno exitoso el sistema cliente debe verificar que el valor del parámetro state y el valor del parámetro nonce que recibe del proveedor de identidad coincide con el generado en paso anterior, esto da la certeza de que la petición no ha sido fruto de algún tipo de ataque de falsificación de solicitud.
Ejemplo de retorno con autenticación exitosa:
https://<sistema-cliente/callback>?code=bzjggVXIHPrqZDAwlTAC5W6Z2BkrNXefHPi3jCqGkcG&state=509ccc2713049e6efea071a9c34f6f45&nonce=2sad12aa292kdhj1l34dks2&iss=https://<base-url-proveedor-identidad>
Ejemplo de retorno con autenticación NO exitosa:
https://<sistema-cliente/callback>?error=consent_required&error_description=client%20not%20authorized%20for%20End-User%20session%20yet&state=509ccc2713049e6efea071a9c34f6f45&nonce=2sad12aa292kdhj1l34dks2&iss=https://<base-url-proveedor-identidad>
Autorización - Token endpoint
Para intercambiar el código de autorización (authorization code) por el token de acceso y el token de identidad se debe enviar una petición POST via HTTPS con los parámetros necesarios.
La url donde se debe enviar la solicitud POST es la siguiente:
https://<base-url-proveedor-identidad>/token
Los parámetros necesarios que se deben enviar son:
| Parámetro | Tipo | Condición | Descripción |
|---|---|---|---|
| Authorization | header | requerido si el método de autenticación del cliente es basic | El id_client y secret (ambos obtenidos en el registro del sistema cliente) deben ser pasados en la cabecera mediante la autenticación básica (el secret debe estar codificado con urlEncode). |
| code | body | requerido | Es el código de acceso obtenido en el paso de autenticación. |
| redirect_uri | body | requerido | Es la misma uri utilizada en el paso anterior. |
| grant_type | body | requerido | valor: authorization_code. |
| code_verifier | body | requerido si es una aplicación móvil | Valor generado en el paso anterior. |
| client_id | body | requerido si el tipo de autenticación del cliente es post o es aplicación móvil | Identificador del cliente, obtenido al crear el cliente. |
| client_secret | body | requerido si el tipo de autenticación del cliente es post | Credencial del sistema cliente obtenido en el registro. |
Ejemplo de solicitud si el tipo de autenticación es basic:
curl -X POST \
https://<base-url-proveedor-identidad>token \
-H 'authorization: Basic M1ZOS0x4UkNjUVF4US05NEphcGhjOnBabjAzbG1PaE1Ga0E0Y0h4V2REY0xYSHBtOXlsMU9CSkNnRTFtRDFoYmFOaXdBYWxPbHAxWkJRQjVJNzVUX2dFWGcwYm5vZFN4eUxuOU8yVzFGR1F3' \
-H 'cache-control: no-cache' \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code&code=KhYAjeCwU3BOchZZhFVr-ukqFOrc4jAF_9ZUwMhQU32&redirect_uri=https://<sistema-cliente>/callback'
Ejemplo de solicitud si el tipo de autenticación es post:
curl -X POST \
https://<base-url-proveedor-identidad>/token \
-H 'cache-control: no-cache' \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code&code=1LVvS3_X8QdIOJejBtAmvBEUzdAy-QYTtIb4SpEY29c&redirect_uri=https://<sistema-cliente>/callback&client_id=W5ulM-2xLKtXpBxahfTQQ&client_secret=lY9MSMzTTn0tp4avTBrQ44CnicKpoLEATG-QfcyJWOI1kIrVjqpcqPKps8-eMruYqd6vdzu6RiuL7Q9inOwkpQ'
Ejemplo de solicitud si la aplicación es móvil:
curl -X POST \
https://<base-url-proveedor-identidad>/token \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code&redirect_uri=net.openid.appauthdemo%3A%2Foauth2redirect&code_verifier=2AcLLc82Tdu8HUESuVxJeL28DGavoDQfpJGSjLLC3FfJfpwtWR0efZaTUgHRL3wTvkwUJ9nwuTd9QXSA&code=64GrCF1ps00cU1d1jp5d8mDlQjYRhojH6JEMn6yu5l5&client_id=yhOiNSDcWeXQEz2Hs7DeW'
En caso de éxito el Proveedor de identidad devolverá un objeto JSON con los siguientes parámetros:
| Parámetro | Descripción |
|---|---|
| access_token | Es un token que servirá acceder a los recursos protegidos. |
| expires_in | Tiempo de vida del token de acceso. |
| id_token | Token de identidad. |
| scope | scopes a los que se tiene permiso. |
| token_type | Identifica el tipo de token devuelto. |
Ejemplo de respuesta:
{
"access_token": "6m4IKQt3M98vLu4qWTwyNlcMk5ZVXV_fITSDXLuke30",
"expires_in": 86400,
"id_token": "eyJhbGciOiJSUzI1NiIsInR5...", // JWT
"scope": "openid profile",
"token_type": "Bearer"
}