OAuth 2.0: flujos para obtener un token de acceso
OAuth 2.0[1] es un protocolo de autorización de estándar abierto que permite a terceros (aplicaciones) acceder a los datos de un usuario sin que el usuario tenga que informar sus credenciales. Apps usan este método para obtener acceso a la cuenta de un usuario determinado a través de un client ID o client secret (claves de autenticación de OAuth).
Si desea obtener más información, visite este sitio web: http://oauth.net/2/. |
Tipos de clientes
En OAuth, hay dos tipos de clientes:
-
Cliente confidencial: se trata de clientes que pueden garantizar que ningún usuario malintencionado obtendrá un client secret o client ID para intentar pasar por una aplicación válida.
-
Cliente no confidencial: clientes que no pueden garantizar que un usuario malintencionado obtendrá su client secret o client ID para intentar pasar por una aplicación válida. En estos casos, se informa una dirección URL de devolución de llamada para asegurarse de que la información vuelve solo a la aplicación original. Como alternativa, el tiempo de vida del client ID se puede reducir mediante un refresh token.
Formas de obtener un access token
Hay diferentes flujos de OAuth 2.0, que exigen formas distintas de obtener un token de acceso.
Para algunos métodos, debe enviar un extraInfo .
Los valores enviados como extraInfo se muestran en el campo Extra Fields de la pantalla de información general de un token, a la que se puede acceder haciendo clic en el nombre de un token en la página Access Tokens.
|
Authorization Code
1. Generación de un authorization code:
En primer lugar, se debe haber creado una aplicación.
Con ella, podemos obtener el client ID, que es el primer elemento que debemos informar a través de una petición POST a este endpoint: <gateway URL>/oauth/grant-code
.
El header debe contener la siguiente información:
Content-Type: application/json
Tenemos que incluir los siguientes elementos en el cuerpo:
{
"client_id": "f9212173-e705-373b-a698-61923e378359",
"extraInfo": {},
"redirect_uri": "string",
"state": "string"
}
El client ID informado debe ser el mismo de la app creada. |
Una vez hecho esto, se espera una respuesta que contenga un authorization code, como en el ejemplo siguiente:
{
"redirect_uri": "string?state=string&code=8748d39f-1d4f-311f-92c6-4b279db1b317"
}
2. Notificación del authorization code para generar el access token:
Debe realizar una nueva petición POST, a este endpoint: <gateway URL>/oauth/access-token
.
El header debe contener la siguiente información:
Authorization: Basic client_id:client_secret
En el cuerpo, debemos informar el código de autorización generado por el endpoint anterior.
Puede usar x-www-form-urlencoded o JSON para el cuerpo, solo recuerde incluir la cabecera Content-Type
correspondiente (application/x-www-form-urlencoded
o application/json
).
Incluya la siguiente información en el cuerpo:
-
grant_type
, con valorauthorization_code
. -
code
, con el valor recibido del endpoint anterior.
Se generará el token de acceso y se devolverá el siguiente código:
{
"access_token": "57f10f0e-3d2e-311f-a797-4011f66e1cbf",
"refresh_token": "ca81cb16-43e4-3e96-aaea-4861e7791dc7",
"token_type": "access_token",
"expires_in": 3600
}
Authorization code con PKCE
A partir de la versión 4.6.1.0 de la API Platform , admitimos PKCE en el flujo del código de autorización.
PKCE (Proof Key for Code Exchange) es una extensión de OAuth que tiene como objetivo hacer más seguro el flujo de Authorization Code, evitando el ataque de interceptación — es decir, cuando una aplicación maliciosa accede al código de autorización en una comunicación no TLS y utiliza el código para emitir un token de acceso. Puede leer más sobre esto en la RFC 7636.
PKCE no es necesaria, es el cliente quien decide si la utiliza o no en el flujo de Authorization Code.
Si desea utilizar PKCE, debe enviar un code_challenge
con un code_challenge_method
en la llamada de concesión de código y, en la llamada para obtener el token de acceso, enviar un code-verifier
:
-
code-verifier
: según la RFC 7636, debe ser una cadena aleatoria encriptada de alta entropía, con un mínimo de 43 caracteres y un máximo de 128, y utilizando los caracteres [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~". -
code_challenge
: código derivado de code_verifier mediante un método de transformación (code_challenge_method). -
code_challenge_method
: método de transformación por el que se genera elcode_challenge
. Hay dos opciones:-
plain
: code_challenge = code_verifier -
S256
: code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))Si no se pasa el code_challenge_method, se asume que es plain
.
-
Para utilizar PKCE, el cliente debe incluir la siguiente información en las llamadas:
-
en el cuerpo de la llamada para la generación del código de autorización (
/grant-code
) descrita anteriormente, incluir elcode_challenge
y elcode_challenge_method
. -
en el cuerpo de la llamada para generación de tokens (
/access-token
) descrita anteriormente, incluir elcode_verifier
.
El servidor de autorización no valida si el code_challenge sigue la alta entropía que recomienda la RFC, ya que esto es responsabilidad del cliente. Tampoco es obligatorio el uso de PKCE en el flujo de Authorization Code. Sin embargo, una vez que el cliente envía el code_challenge en la llamada de generación del código de autorización, el servidor de autorización requerirá el code_verifier en la llamada de obtención del token. Este code_verifier será validado en base al code_challenge y code_challenge_method enviados anteriormente y si la validación no es exitosa, el token no será generado. |
Refresh Token
El refresh token se usará para actualizar un access token caducado. Para actualizar un token, siga los pasos que se indican a continuación.
En primer lugar, realice una petición POST a este endpoint: <gateway URL>/oauth/access-token
.
El header debe contener la siguiente información:
Authorization: Basic client_id:client_secret
En el cuerpo, debemos incluir el refresh_token
recibido desde el endpoint anterior (que generó el access token) y el grant type en el formato x-www-form-urlencoded
, como en este ejemplo:
grant_type=refresh_token&refresh_token=ca81cb16-43e4-3e96-aaea-4861e7791dc7
Por último, se regenerará el access token y se devolverá un código como el ejemplo siguiente.
{
"access_token": "ca81cb16-43e4-3e96-aaea-4861e7791dc7",
"refresh_token": "677b881a-d0b6-3b29-b9a8-f0cdb50ce035",
"token_type": "access_token",
"expires_in": 3600
}
Implicit
El flujo Implicit se utiliza para obtener tokens de acceso para clientes públicos de forma optimizada. Puede funcionar a través de una IRO de enrutamiento privado junto con un access token. Estos clientes se implementan normalmente en un navegador mediante un lenguaje de script, como JavaScript.
Al igual que con OAuth 2.0 Authorization Code, se debe haber creado una app para que podamos tener acceso al client ID.
Después de eso, realice una petición POST a este endpoint: <gateway URL>/oauth/access-token
.
Debe contener el siguiente header:
Content-Type: application/json
Debemos incluir estos elementos en el cuerpo:
{
"grant_type": "implicit",
"redirect_uri": "<URL>",
"client_id": "<client ID>"
}
El client ID debe ser el mismo de la app creada. |
Tenga en cuenta que la aplicación debe contener un extra field denominado redirect_uri , con una dirección URL válida como valor, que debe ser informado al solicitar el token (por ejemplo: http://example.demo.sensedia.com/ ).
Acceda a esta página para ver más información sobre cómo crear y configurar apps, agregando extra fields.
|
Cuando se realiza el proceso, se espera una respuesta que contenga el URI y el token de acceso, como el ejemplo siguiente.
{
"redirect_uri": "www.url.com?access_token=57f10f0e-3d2e-311f-a797-4011f66e1cbf",
"expires_in": 3600
}
Client Credentials
Al igual que el flujo Implicit, Client Credentials NO genera un refresh_token
.
Por lo tanto, no es posible actualizar un token de acceso cuando expira.
Cuando se usa este flujo, al crear un nuevo access token, debe informar el nombre de la app y el client ID en el campo Extra Info
del token, informando también de todos los valores de los campos adicionales (extra fields) que están registrados para esa app.
Acceda a esta página para ver más información sobre la creación y configuración de apps, agregando campos adicionales.
Se debe haber creado una app para que podamos obtener el client ID y el client secret.
A continuación, es necesario realizar una petición POST a este endpoint: <gateway URL>/oauth/access-token
.
La petición debe contener el siguiente header:
Authorization: Basic client_id:client_secret
En el cuerpo, debemos informar el grant_type
en formato x-www-form-urlencoded
:
grant_type=client_credentials
A continuación, se generará el access token y se debe devolver como en el ejemplo siguiente.
{
"access_token": "6c164a82-84a6-3bc4-8122-f777121a4f62",
"token_type": "access_token",
"expires_in": 3600
}
También puede crear nuevos campos adicionales (extra fields) al generar el token de acceso. Para eso, es necesario añadir el siguiente header:
Content-Type: application/json
En el cuerpo, debemos informar el grant_type
y los campos adicionales, como en este ejemplo:
{
"grant_type": "client_credentials",
"extraInfo": {"value": "32423", "value2": "874yhgt3"}
}
Password
Se debe haber creado una app para que podamos tener acceso al client ID y el client secret.
Después de eso, debe realizar una petición POST a este endpoint: <gateway URL>/oauth/access-token
.
El header debe contener esta información:
Authorization: Basic client_id:client_secret
Además del grant_type
, el cuerpo debe contener otras dos piezas de información que utilizan el userDirectory
.
Son el login y la contraseña del usuario, que pueden ser de un LDAP o un REST, y deben estar en el formato x-www-form-urlencoded
:
grant_type=password&username=<login de usuario>&password=<contraseña>
Si el usuario y la contraseña son válidos en LDAP o REST, la devolución del access token debe ser similar al ejemplo siguiente:
{
"access_token": "6c164a82-84a6-3bc4-8122-f777121a4f62",
"token_type": "refresh_token",
"expires_in": 3600
}
Para que las características anteriores se apliquen a la app, debe configurar una API Identity. |
En el caso de LDAP, se debe informar el usuario en el formato User-Principal-Name (por ejemplo, test@da.sa ).
|
La propiedad oauth.grantTypes.resourceOwnerPassword.userDirectory ya no es necesaria.
|
JWT
"JSON Web Token (JWT) es un estándar abierto (RFC 7519) que define una forma compacta e independiente de transmitir información de forma segura entre partes como un objeto JSON. Esta información se puede verificar y confiar porque está firmada digitalmente. Los JWT se pueden firmar usando un secreto (con el algoritmo HMAC) o un par de claves pública/privada usando RSA." (https://jwt.io/)
Antes de realizar la llamada para generar el token JWT, debemos realizar una llamada para generar el Authorization Code. Puedes ver más sobre esto aquí. |
En el flujo JWT, se debe haber creado una app para que podamos tener acceso al identificador de cliente y al secreto de cliente.
A continuación, debe realizar una petición POST a este endpoint: <gateway URL>/oauth/access-token
.
El header debe contener la siguiente información:
Authorization: Basic client_id:client_secret
En el cuerpo, debemos informar el code
generado por el endpoint de grant-code
y el grant type en el formato x-www-form-urlencoded
, como en este ejemplo:
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&code=8748d39f-1d4f-311f-92c6-4b279db1b317
El access token se generará de nuevo y se debe devolver como en el ejemplo siguiente.
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsb2NhbGhvc3QiLCJpc3MiOiIxNzIuMTguMC4xIiwic3ViIjoiOWI1Zjc3MWUtNzgyZC0zNTEwLWI2YmEtMzZlOWM2NWJmZDVkIiwiZXhwIjozNjAwLCJpYXQiOjE1Mjg5MTg2MzcsIkFwcDogIjoiUmljYXJkb0FwcCIsIkNvZGU6ICI6IjRlNWIyMTEzLTJkYzYtM2RlNi1iN2ZkLWNkOTYxOTMxZWQyOSIsImxvZ2luIjoidXNlci5sb2dpbiJ9.bhvFpiZ6em9tUgpHxGQGuH7cmvMy4I7STJDRBUybuPM",
"token_type": "access_token",
"expires_in": 3600
}
Con el código generado, deberá agregar el interceptor JWT al flujo de API. Él será responsable de validar el token. Ver más sobre este interceptor aquí.
OpenID
El flujo OpenID permite a los usuarios usar una credencial existente para acceder a varios sitios web sin necesidad de crear nuevas contraseñas. Esto mejora la seguridad de los usuarios porque su contraseña se proporciona solo a un proveedor en el que confían; este proveedor confirma su identidad y concede acceso a los sitios y aplicaciones que desean usar.
Para utilizar el flujo OpenID, es necesario crear la API Google OpenID. Haga clic aquí para obtener instrucciones sobre cómo crear la API.
La instrucción anterior está en Portugués. |
También es necesario que se haya creado una app.
Con ella, podemos acceder al client ID, que será el primer elemento informado a través de una petición POST a este endpoint: <gateway URL>/google/oauth/openid/redirect
.
La petición debe contener los siguientes headers:
Content-Type : application/json client_id : client_id
En el cuerpo, debemos informar el siguiente elemento:
{
"extraInfo": {}
}
El client_id debe ser el mismo de la app creada.
|
Una vez hecho esto, debe haber una respuesta que contenga un authorization code
, como en el ejemplo siguiente:
{
"redirect_uri": "string?queryParams"
}
A continuación, debe acceder a la redirect_uri
, que da acceso a una página de autenticación de su proveedor.
El inicio de sesión llevará a un redireccionamiento automático siguiendo los valores del access token.
Revocación de access token y refresh token
La revocación hace inutilizable un token que sigue siendo válido pero que ya no es necesario. Después de la revocación, el token no se acepta en peticiones a las APIs.
Se puede utilizar el endpoint /revoke
de la API «OAuth 2.0» para revocar un access token o un refresh token.
En ambos casos, se revocan todos los tokens — es decir, si se revoca un access token y hay un refresh token asociado a él, también se revoca, y si se revoca un refresh token, también se revoca el access token asociado a él.
Para hacer la revocación, hay que enviar una petición POST a <URL del gateway>/oauth/revoke
.
La petición debe contener el header Authorization
:
Authorization : Basic client_id:client_secret
En el cuerpo, pase la siguiente información en formato x-www-form-urlencoded
:
token=<valor>&token_type_hint=access_token
O
token=<valor>&token_type_hint=refresh_token
Tenga en cuenta que no es necesario pasar el token_type_hint
(porque el token se encuentra por el valor introducido), pero hace que la operación de revocación sea más rápida.
Share your suggestions with us!
Click here and then [+ Submit idea]