Saltar al contenido principal
En esta sección veremos cómo implementar una API para nuestro caso.
Para simplificar, mantendremos la implementación centrada exclusivamente en la autenticación y la autorización. Como verá en los ejemplos, el registro de horas de entrada estará definido de forma fija en el código, y la API no persistirá ese registro. En su lugar, simplemente devolverá parte de la información.

Definir los endpoints de la API

Primero debemos definir los endpoints de nuestra API.

¿Qué es un endpoint de API?

Un endpoint de API es una URL única que representa un objeto. Para interactuar con este objeto, la aplicación debe apuntar a su URL. Por ejemplo, si tuviera una API que pudiera devolver pedidos o clientes, podría configurar dos endpoints: /orders y /customers. La aplicación interactuaría con estos endpoints mediante distintos métodos HTTP; por ejemplo, POST /orders podría crear un pedido nuevo o GET /orders podría recuperar el conjunto de datos de uno o más pedidos.
Para esta implementación, solo definiremos dos endpoints: uno para recuperar una lista de todos los registros de horas de un empleado y otro que permitirá a un empleado crear un nuevo registro de horas. Una solicitud HTTP GET al endpoint /timesheets permitirá que un usuario recupere sus registros de horas, y una solicitud HTTP POST al endpoint /timesheets permitirá que un usuario agregue un nuevo registro de horas. Consulte la implementación en Node.js

Proteger los endpoints

Cuando una API recibe una solicitud con un bearer en el encabezado, lo primero que debe hacerse es validar el token. Esto consiste en una serie de pasos y, si alguno de ellos falla, la solicitud debe rechazarse con el mensaje de error Missing or invalid token para la aplicación que realiza la llamada. Las validaciones que debe realizar la API son:
  • Verificar que el tenga un formato válido
  • Verificar la firma
  • Validar los claims estándar
JWT.io proporciona una lista de bibliotecas que pueden hacer la mayor parte del trabajo por usted: analizar el JWT y verificar la firma y los claims.
Parte del proceso de validación también consiste en comprobar los permisos del cliente (alcances), pero esto se abordará por separado en el siguiente párrafo de este documento. Para obtener más información sobre cómo validar tokens de acceso, consulte Validar tokens de acceso. Consulte la implementación en Node.js

Comprobar los permisos del cliente

A estas alturas, ya hemos verificado que el JWT es válido. El último paso es comprobar que el cliente tenga los permisos necesarios para acceder a los recursos protegidos. Para ello, la API debe comprobar los alcances del JWT decodificado. Esta claim forma parte de la carga útil y es una lista de cadenas separadas por espacios. Consulta la implementación en Node.js

Determinar la identidad del usuario

Para ambos endpoints (obtener la lista de registros de horas y agregar un nuevo registro de horas), necesitaremos determinar la identidad del usuario. Al obtener la lista de registros de horas, esto garantiza que solo devolvamos los registros de horas que pertenecen al usuario que realiza la solicitud; y al agregar un nuevo registro de horas, garantiza que este se asocie con el usuario que realiza la solicitud. Una de las claims estándar de un JWT es la claim sub, que identifica al principal que es el sujeto de la claim. En el caso del flujo Implicit Grant, esta claim contendrá la identidad del usuario, que será el identificador único del usuario de Auth0. Puede usarla para asociar cualquier información en sistemas externos con un usuario concreto. También puede usar una claim personalizada para agregar otro atributo del usuario, como su correo electrónico, al Token de acceso y usarlo para identificar de forma única al usuario. Consulte la implementación en Node.js

Implementa la aplicación móvil

En esta sección veremos cómo implementar una aplicación móvil para este escenario. Consulta la implementación en Android.

Autorice al usuario

Para autorizar al usuario, implementaremos el flujo de código de autorización con Proof Key for Code Exchange (PKCE). La aplicación móvil primero debe redirigir al usuario a la URL de autorización junto con el code_challenge y el método utilizado para generarlo: La solicitud GET a la URL de autorización debe incluir los siguientes valores:
ParameterDescription
client_idEl valor de tu ID de cliente de Auth0. Puedes obtenerlo en la configuración de tu aplicación en el Auth0 Dashboard.
audienceEl valor del identificador de tu API. Puedes obtenerlo en la configuración de tu API en el Auth0 Dashboard.
scopeLos alcances que determinan los claims que se devolverán en el ID Token y el token de acceso. Por ejemplo, un scope de openid devolverá un ID Token en la respuesta. En nuestra aplicación móvil de ejemplo, usamos los siguientes alcances: create:timesheets read:timesheets openid profile email offline_access. Estos alcances permiten que la aplicación móvil llame a la API, obtenga un Token de actualización y devuelva los claims name, picture y email del usuario en el ID Token.
response_typeIndica el flujo de autenticación que se debe usar. En una aplicación móvil que usa PKCE, debe establecerse en code.
code_challengeEl desafío de código generado a partir del verificador de código. Puedes encontrar instrucciones para generar un desafío de código aquí.
code_challenge_methodMétodo utilizado para generar el desafío. Auth0 solo admite S256.
redirect_uriLa URL a la que Auth0 redirigirá el navegador después de que el usuario haya otorgado la autorización. El código de autorización estará disponible en el parámetro de URL code. Esta URL debe especificarse como una URL de callback válida en la configuración de tu aplicación.
Consulta la implementación en Android.

Obtener las credenciales

Tras realizar correctamente una solicitud a la URL de autorización, deberías recibir la siguiente respuesta: A continuación, puedes intercambiar el authorization_code de la respuesta por un Token de acceso que puedes usar para llamar a tu API. Realiza una solicitud POST a la URL del token e incluye los siguientes datos:
ParámetroDescripción
grant_typeDebe establecerse como authorization_code.
client_idEl valor de tu ID de cliente de Auth0. Puedes obtenerlo en la sección Settings de tu aplicación en el Auth0 Dashboard.
code_verifierClave aleatoria criptográficamente segura que se utilizó para generar el code_challenge enviado a la URL de autorización (/authorize).
codeEl authorization_code recibido de la llamada anterior a authorize.
redirect_uriLa URL debe coincidir con el redirect_uri enviado en la sección anterior a /authorize.
La respuesta de la URL de token contendrá:
{
  "access_token": "eyJz93a...k4laUWw",
  "refresh_token": "GEbRxBN...edjnXbL",
  "id_token": "eyJ0XAi...4faeEoQ",
  "token_type": "Bearer",
  "expires_in":86400
}
  • access_token: Un Token de acceso para la API, especificado por audience.
  • refresh_token: Un Token de actualización solo estará presente si incluyó el scope offline_access y habilitó Permitir acceso sin conexión para su API en el Dashboard.
  • id_token: Un JWT que contiene información del perfil del usuario.
  • token_type: Una cadena que contiene el tipo de token; siempre será un token Bearer.
  • expires_in: La cantidad de segundos hasta que expire el Token de acceso.
Deberá almacenar las credenciales anteriores en el almacenamiento local para usarlas al llamar a su API y recuperar el perfil del usuario. Consulte la implementación en Android.

Obtener el perfil del usuario

Para obtener el perfil del usuario, tu aplicación móvil puede decodificar el ID Token con una de las bibliotecas JWT. Para ello, verifica la firma y las claims del token. Después de validar el ID Token, puedes acceder a su payload, que contiene la información del usuario:
{
  "email_verified": false,
  "email": "test.account@userinfo.com",
  "clientID": "q2hnj2iu...",
  "updated_at": "2016-12-05T15:15:40.545Z",
  "name": "test.account@userinfo.com",
  "picture": "https://s.gravatar.com/avatar/dummy.png",
  "user_id": "auth0|58454...",
  "nickname": "test.account",
  "created_at": "2016-12-05T11:16:59.640Z",
  "sub": "auth0|58454..."
}
Consulte la implementación para Android.

Mostrar elementos de la IU de forma condicional según el scope

En función del scope del usuario, es posible que quiera mostrar u ocultar determinados elementos de la IU. Para determinar el scope emitido para un usuario, deberá inspeccionar el scope que se concedió cuando el usuario se autenticó. Será una cadena que contiene todos los alcances, por lo que deberá comprobar si esa cadena contiene el scope requerido y, en función de ello, decidir si mostrar un elemento concreto de la IU. Consulte la implementación en Android

Llamar a la API

Para acceder a los recursos protegidos de tu API, debes incluir el token de acceso del usuario autenticado en las solicitudes que le envíes. Esto se logra enviando el token de acceso en un encabezado Authorization mediante el esquema Bearer. Consulta la implementación en Android.

Renovar el token

Los Tokens de actualización deben almacenarse de forma segura en la aplicación, ya que no caducan y permiten que un usuario permanezca autenticado prácticamente de forma indefinida. Si los Tokens de actualización se ven comprometidos o ya no los necesita, puede revocarlos mediante la Authentication API.
Para renovar su Token de acceso, realice una solicitud POST al endpoint /oauth/token con el de su resultado de autorización. Un Token de actualización solo estará presente si incluyó el scope offline_access en la solicitud de autorización anterior y habilitó Allow Offline Access para su API en el Dashboard. Su solicitud debe incluir:
ParámetroDescripción
grant_typeDebe establecerse en refresh_token.
client_idEl valor de su ID de cliente de Auth0. Puede recuperarlo en la sección Settings de su aplicación en el Auth0 Dashboard.
refresh_tokenel Token de actualización que se usará, obtenido del resultado de autenticación anterior.
La respuesta incluirá el nuevo Token de acceso:
{
  "access_token": "eyJz93a...k4laUWw",
  "refresh_token": "GEbRxBN...edjnXbL",
  "id_token": "eyJ0XAi...4faeEoQ",
  "token_type": "Bearer",
  "expires_in":86400
}
Consulte la implementación en Android.