Saltar al contenido principal
En esta sección veremos cómo implementar una API para este caso.
Para simplificar, la implementación se centrará únicamente en la autenticación y la autorización. Como verá en los ejemplos, la entrada del registro de horas estará codificada de forma fija y la API no persistirá esa entrada. 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, debe hacer que su aplicación apunte a esa URL. Por ejemplo, si tuviera una API que pudiera devolver pedidos o clientes, podría configurar dos endpoints: /orders y /customers. Su aplicación interactuaría con estos endpoints mediante distintos métodos HTTP; por ejemplo, POST /orders podría crear un nuevo pedido o GET /orders podría recuperar los datos de uno o varios pedidos.
Para esta implementación, solo definiremos 2 endpoints: uno para recuperar una lista de todos los registros de horas de un empleado y otro que permitirá a un empleado crear una nueva entrada de 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 añada un nuevo registro de horas. Consulte la implementación en Node.js.

Protege los endpoints

Cuando una API recibe una solicitud con un bearer en el encabezado, lo primero 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:
  • Comprobar que el tenga un formato válido
  • Verificar la firma
  • Validar los claims estándar
JWT.io proporciona una lista de bibliotecas que pueden realizar la mayor parte del trabajo por ti: analizar el JWT y verificar la firma y los claims.
Parte del proceso de validación también consiste en comprobar los permisos de la aplicación (alcances), pero esto se abordará por separado en el siguiente apartado de este documento. Para obtener más información sobre cómo validar tokens de acceso, consulta Validar tokens de acceso. Consulta la implementación en Node.js.

Comprueba los permisos de la aplicación

En este punto, ya hemos verificado que el JWT es válido. El último paso es verificar que la aplicación tenga los permisos necesarios para acceder a los recursos protegidos. Para ello, la API debe comprobar los alcances del JWT decodificado. La claim forma parte de la carga útil y contiene 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), tendremos que determinar la identidad del usuario. Al obtener la lista de registros de horas, esto nos permite asegurarnos de devolver solo los registros de horas que pertenecen al usuario que realiza la solicitud. Al agregar un nuevo registro de horas, nos permite asegurarnos de que el registro de horas quede asociado al usuario que realiza la solicitud. Uno de los claim estándar de un JWT es el claim sub, que identifica a la entidad principal a la que se refiere el claim. En el caso del flujo de Implicit Grant, este claim contendrá la identidad del usuario, que será el identificador único del usuario de Auth0. Puede usarlo para asociar cualquier información en sistemas externos con un usuario en particular. También puede usar un claim personalizado para agregar otro atributo del usuario, como su correo electrónico, al Token de acceso y usarlo para identificar al usuario de forma única. Consulte la implementación en Node.js.

Implementa la SPA

En esta sección veremos cómo implementar una SPA para este caso.

Autorizar al usuario

Para autorizar al usuario, usaremos la librería auth0.js. Puede inicializar una nueva instancia de la aplicación de Auth0 de la siguiente manera: Debes proporcionar los siguientes valores de configuración:
  • clientID: El valor de tu de Auth0. Puedes obtenerlo en la sección Configuración de tu aplicación en el Dashboard.
  • domain: El valor de tu dominio de Auth0. Puedes obtenerlo en la sección Configuración de tu aplicación en el Dashboard.
  • responseType: Indica el flujo de autenticación que se va a usar. Para una SPA que usa el Flujo implícito, debes establecerlo en token id_token. La parte token hace que el flujo devuelva un Token de acceso en el fragmento de la URL, mientras que la parte id_token hace que el flujo también devuelva un .
  • : El valor del identificador de tu API. Puedes obtenerlo en la Configuración de tu API en el Dashboard.
  • redirectUri: La URL a la que Auth0 debe redirigir después de que el usuario se haya autenticado.
  • scope: Los alcances que determinan la información que se devolverá en el ID Token y el Token de acceso. Un scope de openid profile devolverá toda la información del perfil de usuario en el ID Token. También debes solicitar los alcances necesarios para llamar a la API; en este caso, los scopes read:timesheets create:timesheets. Esto garantizará que el Token de acceso tenga esos alcances.
Para iniciar el flujo de autenticación, puedes llamar al método authorize():
auth0.authorize();
Después de la autenticación, Auth0 redirigirá al redirectUri que especificaste al configurar la nueva instancia de la aplicación de Auth0. En este punto, deberás llamar al método parseHash(), que analiza un fragmento hash de una URL para extraer el resultado de una respuesta de autenticación de Auth0. El contenido del objeto authResult devuelto por parseHash depende de los parámetros de autenticación que se hayan usado. Puede incluir lo siguiente:
  • idToken: Un JWT de ID Token que contiene información del perfil de usuario
  • accessToken: Un Token de acceso para la API, especificado por la audience.
  • expiresIn: Una cadena que contiene el tiempo de expiración (en segundos) del Token de acceso.
Determina cuál es el mejor lugar para almacenar los tokens. Si tu aplicación de página única tiene un servidor backend, los tokens deben manejarse del lado del servidor mediante el Flujo de código de autorización o el Flujo de código de autorización con Proof Key for Code Exchange (PKCE). Si tienes una aplicación de página única (SPA) sin un servidor backend correspondiente, tu SPA debe solicitar nuevos tokens al iniciar sesión y almacenarlos en memoria sin persistencia. Para hacer llamadas a la API, tu SPA usará entonces la copia en memoria del token. Para ver un ejemplo de cómo gestionar sesiones en las SPA, consulta la sección Handle Authentication Tokens del Quickstart de JavaScript para aplicaciones de página única. Consulte la implementación en Angular 2.

Obtener el perfil de usuario

Extraer información del token

En esta sección se muestra cómo obtener la información del usuario mediante el Token de acceso y el /userinfo endpoint. Para evitar esta llamada a la API, puedes simplemente decodificar el ID Token con una biblioteca (asegúrate de validarlo primero). Si necesitas información adicional del usuario, considera usar la Management API desde tu backend.
Se puede llamar al método client.userInfo pasando el valor devuelto de authResult.accessToken para obtener la información del perfil del usuario. Esto hará una solicitud al /userinfo endpoint y devolverá el objeto user, que contiene la información del usuario, como en el siguiente ejemplo:
{
    "email_verified": "false",
    "email": "test@example.com",
    "clientID": "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHH",
    "updated_at": "2017-02-07T20:50:33.563Z",
    "name": "tester9@example.com",
    "picture": "https://gravatar.com/avatar/example.png",
    "user_id": "auth0|123456789012345678901234",
    "nickname": "tester9",
    "created_at": "2017-01-20T20:06:05.008Z",
    "sub": "auth0|123456789012345678901234"
}
Puede acceder a cualquiera de estas propiedades en la función callback que se pasa al llamar a la función userInfo:
const accessToken = authResult.accessToken;

auth0.client.userInfo(accessToken, (err, profile) => {
  if (profile) {
    // Obtener el apodo y la imagen de perfil del usuario
    var nickname = profile.nickname;
    var picture = profile.picture;
  }
});
Consulte la implementación en Angular 2.

Mostrar elementos de la interfaz de usuario de forma condicional según el scope

Según el scope del usuario, puede que desee mostrar u ocultar determinados elementos de la interfaz de usuario. Para determinar el scope emitido para un usuario, deberá almacenar el scope que se solicitó inicialmente durante el proceso de autorización. Cuando se autoriza a un usuario, el scope también se devuelve en authResult. Si el scope en authResult está vacío, significa que se concedieron todos los alcances solicitados. Si el scope en authResult no está vacío, significa que se concedió un conjunto diferente de alcances y que debe usar los de authResult.scope. Consulte la implementación en Angular 2.

Llama a la API

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

Renovar el Token de acceso

Como medida de seguridad, se recomienda mantener corta la duración del Token de acceso de un usuario. Cuando crea una API en el , la duración predeterminada es de 7200 segundos (2 horas), aunque esto puede configurarse para cada API. Una vez que caduca, un Token de acceso ya no puede usarse para acceder a una API. Para volver a obtener acceso, es necesario obtener un nuevo Token de acceso. Para obtener un nuevo Token de acceso, puede repetir el flujo de autenticación utilizado para obtener el Token de acceso inicial. En una SPA, esto no es lo ideal, ya que quizá no quiera redirigir al usuario para apartarlo de su tarea actual y que vuelva a completar el flujo de autenticación. En casos como este, puede usar la Autenticación silenciosa. La autenticación silenciosa le permite realizar un flujo de autenticación en el que Auth0 solo responde con redireccionamientos y nunca con una página de inicio de sesión. Sin embargo, esto requiere que el usuario ya haya iniciado sesión mediante inicio de sesión único (SSO). Consulte la implementación en Angular 2.