Saltar al contenido principal
Con la autenticación escalonada, las aplicaciones que permiten el acceso a distintos tipos de recursos pueden exigir que los usuarios se autentiquen con un mecanismo más robusto para acceder a información confidencial o realizar determinadas transacciones. Por ejemplo, un usuario de una aplicación bancaria solo puede transferir dinero entre cuentas después de haber confirmado su identidad mediante (MFA). Cuando tu es una API, puedes implementar autenticación escalonada con Auth0 mediante scopes, y Actions. Cuando una aplicación quiere acceder a los recursos protegidos de una API, debe proporcionar un token de acceso. Los recursos a los que puede acceder dependen de los permisos incluidos en el token de acceso. Estos permisos se definen como alcances.

Validar los tokens de acceso para MFA

Además de comprobar el scope, la API debe validar el token de acceso para:
  • Verificar la firma del token, que se usa para comprobar que el remitente del token es quien dice ser y para garantizar que el mensaje no se haya modificado durante la transmisión.
  • Validar los claims estándar:
ClaimDescripción
expVencimiento del token
issEmisor del token
audDestinatario previsto del token

Escenario: Transacciones bancarias con notificaciones push

En el siguiente escenario, una aplicación autentica a un usuario con username y contraseña, y luego solicita el saldo de una cuenta. Antes de obtener la información del saldo de la cuenta, el usuario debe autenticarse con el factor push de Guardian. La API bancaria puede aceptar dos niveles diferentes de autorización: consultar el saldo de la cuenta (scope view:balance) o transferir fondos (scope transfer:funds). Cuando la aplicación solicita a la API que obtenga el saldo del usuario, el token de acceso debe contener el scope view:balance. Para transferir dinero a otra cuenta, el token de acceso debe contener el scope transfer:funds.

Flujo de trabajo

  1. El usuario inicia sesión en la aplicación mediante autenticación con username y contraseña. El inicio de sesión estándar permite a este usuario interactuar con la API y consultar su saldo. Esto significa que el token de acceso que recibe la aplicación después de que el usuario se autentica contiene el scope view:balance.
  2. La aplicación envía una solicitud a la API para recuperar el saldo, usando el token de acceso como credenciales.
  3. La API valida el token y envía la información del saldo a la aplicación para que el usuario pueda verla.
  4. El usuario quiere transferir fondos de una cuenta a otra, lo que se considera una transacción de alto valor que requiere el scope transfer:funds. La aplicación envía una solicitud a la API usando el mismo token de acceso.
  5. La API valida el token y deniega el acceso porque al token le falta el scope transfer:funds requerido.
  6. La aplicación redirige a Auth0, donde se usa una Action para exigir que el usuario se autentique con MFA, ya que se solicitó un scope de alto valor. Una vez que el usuario se autentica correctamente con MFA, se genera un nuevo token de acceso que incluye el scope correcto y se envía a la aplicación como parte de la respuesta.
  7. La aplicación envía otra solicitud de transferencia de fondos usando el nuevo token de acceso, que esta vez sí incluye el scope transfer:funds.
  8. La API valida el token, lo descarta y continúa con la operación.

Requisitos previos

Para este escenario, debe configurar los siguientes elementos en el Dashboard:

Crear una Action

Cree una Action que desafíe al usuario a autenticarse con MFA cuando se solicite el scope transfer:funds. Vaya a Dashboard > Actions > Flujos y cree una Action con el siguiente contenido:
{
exports.onExecutePostLogin = async (event, api) => {
  const CLIENTS_WITH_MFA = ['REPLACE_WITH_{yourClientId}'];
  // ejecutar solo para los clientes especificados
  if (CLIENTS_WITH_MFA.includes(event.client.client_id)) {
    // solicitar MFA solo si se solicitó el scope transfer:funds
    if (event.transaction.requested_scopes.indexOf('transfer:funds') > -1)
      api.multifactor.enable('any', { allowRememberBrowser: false });
    }
  }
},
  • La variable CLIENTS_WITH_MFA contiene los de las aplicaciones a las que quiere aplicar esta Action. Puede quitar esto (y la condición if que aparece a continuación) si no lo necesita.
  • La propiedad event.transaction.requested_scopes contiene todos los alcances solicitados en la petición de autenticación. Si incluye el valor transfer:funds, solicitamos MFA estableciendo la propiedad context.multifactor con el valor adecuado. En este caso, solicitamos MFA mediante push.

Configurar la aplicación

Configure la aplicación para enviar la solicitud de autenticación adecuada a la API, dependiendo de si el usuario intenta realizar la transacción de alto valor de transferir fondos. Tenga en cuenta que la única diferencia entre las dos solicitudes de autenticación (con o sin MFA) es el scope.
  • Con MFA: export const codeExample1 = https://{yourDomain}/authorize? audience=https://my-banking-api& scope=openid%20view:balance%20transfer:funds& response_type=id_token%20token& client_id={yourClientId}& redirect_uri={https://yourApp/callback}& nonce=NONCE& state=OPAQUE_VALUE;
  • Sin MFA: export const codeExample2 = https://{yourDomain}/authorize? audience=https://my-banking-api& scope=openid%20view:balance& response_type=id_token%20token& client_id={yourClientId}& redirect_uri={https://yourApp/callback}& nonce=NONCE& state=OPAQUE_VALUE;
ParámetroConfiguración
audienceEstablézcalo en el Identificador de su API (encuéntrelo en Configuración de la API). En este ejemplo, se establece en https://my-banking-api.
response_typeEstablézcalo en id_token token para obtener tanto un ID Token como un token de acceso en la respuesta.
client_idEstablézcalo en el ID de cliente de su aplicación (encuéntrelo en configuración de la aplicación).
redirect_uriEstablézcalo en una URL de su aplicación a la que Auth0 deba redirigir al usuario tras la autenticación (encuéntrela en configuración de la aplicación).
nonceEstablézcalo en una cadena segura que se incluirá en la respuesta de Auth0. Esto se usa para prevenir ataques de repetición de tokens y es obligatorio para response_type=id_token token.
stateEstablézcalo en un valor opaco que Auth0 incluye al redirigir de vuelta a la aplicación. La aplicación debe usar este valor para prevenir ataques CSRF.

Configurar la API

Configure la API para validar el token recibido y comprobar los permisos concedidos.
  1. Configure dos endpoints para nuestra API: GET /balance: para obtener el saldo actual POST /transfer: para transferir fondos
  2. Use Node.js y varios módulos:
    1. express: agrega el framework web Express.
    2. jwks-rsa: recupera claves de firma RSA desde un endpoint de JWKS (conjunto de claves web JSON). Con expressJwtSecret, podemos generar un proveedor que entregue la clave de firma correcta a express-jwt según el kid del encabezado del JWT.
    3. express-jwt: permite autenticar solicitudes HTTP mediante tokens JWT en sus aplicaciones de Node.js. Proporciona varias funciones que facilitan el trabajo con JWT.
    4. express-jwt-authz: comprueba si el token de acceso contiene un scope específico.
  3. Instale las dependencias: npm install express express-jwt jwks-rsa express-jwt-authz --save
  4. Defina los endpoints de la API, cree una función de middleware para validar el token de acceso y proteja los endpoints con ese middleware. El código de su archivo server.js debería verse como en el siguiente script de ejemplo:
Cada vez que la API recibe una solicitud, ocurre lo siguiente:
  1. El endpoint invoca el middleware checkJwt. 2. express-jwt decodifica el token y pasa la solicitud, el encabezado y la carga útil a jwksRsa.expressJwtSecret. 3. jwks-rsa descarga todas las claves de firma del endpoint JWKS y comprueba si alguna de ellas coincide con el kid del encabezado del token de acceso. Si ninguna clave de firma coincide con el kid recibido, se genera un error. Si hay coincidencia, se pasa la clave de firma correcta a express-jwt. 4. express-jwt continúa con su propia lógica para validar la firma del token, la expiración, la audiencia y el emisor. 5. jwtAuthz comprueba si el scope que requiere el endpoint forma parte del token de acceso. Si en el token de acceso faltan los alcances especificados, la solicitud se rechaza con un mensaje de error 403.

Más información