Configurer l’authentification renforcée pour les API
Avec l’authentification renforcée, les applications qui permettent d’accéder à différents types de ressources peuvent exiger des utilisateurs qu’ils s’authentifient à l’aide d’un mécanisme plus puissant pour accéder à des informations sensibles ou effectuer certaines transactions.
Par exemple, l’utilisateur d’une application bancaire peut être autorisé à transférer de l’argent entre ses comptes uniquement après avoir confirmé son identité à l’aide de l’authentification multifacteur (MFA).
Lorsque votre audience est une API, vous pouvez mettre en œuvre une authentification renforcée avec Auth0 en utilisant des permissions, des jetons d’accès et des Actions. Lorsqu’une application souhaite accéder aux ressources protégées d’une API, elle doit fournir un jeton d’accès. Les ressources auxquelles elle aura accès dépendent des autorisations incluses dans le jeton d’accès. Ces autorisations sont exprimées sous la forme de permissions.
Valider les jetons d’accès pour la MFA
Outre la vérification de la permission, l’API doit valider le jeton d’accès pour :
Vérifier la signature du jeton, utilisée pour vérifier que l’expéditeur du jeton est bien celui qu’il prétend être et pour s’assurer que le message n’a pas été modifié en cours de route.
Valider les demandes standard :
Demande Description exp
Expiration du jeton iss
Émetteur du jeton aud
Destinataire du jeton
Scénario : Transactions bancaires avec notifications poussées
Dans le scénario suivant, une application authentifie un utilisateur à l’aide de son nom d’utilisateur et de son mot de passe, puis demande le solde de son compte. Avant de récupérer les informations sur le solde du compte, l’utilisateur doit s’authentifier avec le facteur Guardian poussé.
L’API bancaire peut accepter deux niveaux d’autorisation différents : consulter le solde du compte (permission view:balance
) ou transférer des fonds (permission transfer:funds
). Lorsque l’application demande à l’API de récupérer le solde de l’utilisateur, le jeton d’accès doit contenir la permission view:balance
. Pour transférer de l’argent vers un autre compte, le jeton d’accès doit contenir la permission transfer:funds
.
Processus
L’utilisateur se connecte à l’application en utilisant l’authentification par nom d’utilisateur et mot de passe. La connexion standard permet à l’utilisateur d’interagir avec l’API et de récupérer son solde. Cela signifie que le jeton d’accès que l’application reçoit après l’authentification de l’utilisateur contient la permission
view:balance
.L’application envoie une demande à l’API pour récupérer le solde, en utilisant le jeton d’accès identifiants.
L’API valide le jeton et envoie les informations relatives au solde à l’application, afin que l’utilisateur puisse les consulter.
L’utilisateur souhaite transférer des fonds d’un compte à un autre, ce qui est considéré comme une transaction sensible nécessitant la permission
transfer:funds
. L’application envoie une demande à l’API en utilisant le même jeton d’accès.L’API valide le jeton et refuse l’accès parce qu’il manque au jeton la permission
transfer:funds
.L’application redirige vers Auth0, où une action est utilisée pour demander à l’utilisateur de s’authentifier avec la MFA puisqu’un champ d’application de grande valeur a été demandé. Une fois que l’utilisateur s’est authentifié avec succès avec la MFA, un nouveau jeton d’accès comprenant la permission appropriée est généré et envoyé à l’application dans le cadre de la réponse.
L’application envoie une autre demande de transfert de fonds à l’aide du nouveau jeton d’accès, qui inclut cette fois la permission
transfer:funds
.L’API valide le jeton, l’ignore et procède à l’opération.
Prérequis
Pour ce scénario, vous devez configurer les éléments suivants dans Dashboard :
Enregistrer l’API. Créez deux permissions :
view:balance
ettransfer:funds
.Activer la MFA pour utiliser les notifications poussées.
Créer une action
Créez une action qui demande à l’utilisateur de s’authentifier avec la MFA lorsque la permission transfer:funds
est demandée. Allez à Dashboard > Actions > Flux et créez une action qui contient ce qui suit :
exports.onExecutePostLogin = async (event, api) => {
const CLIENTS_WITH_MFA = ['REPLACE_WITH_YOUR_CLIENT_ID'];
// run only for the specified clients
if (CLIENTS_WITH_MFA.includes(event.client.client_id)) {
// ask for MFA only if scope transfer:funds was requested
if (event.transaction.requested_scopes.indexOf('transfer:funds') > -1)
api.multifactor.enable('any', { allowRememberBrowser: false });
}
}
}
Was this helpful?
La variable
CLIENTS_WITH_MFA
qui contient les identifiants clients des applications à laquelle vous voulez appliquer cette action. Vous pouvez la supprimer (et la conditionif
qui suit) si vous n’en avez pas besoin.La propriété
event.transaction.requested_scopes
contient toutes les permissions pour lesquelles la demande d’authentification a été effectuée. Si elle inclut la valeurtransfer:funds
, nous demandons alors la MFA en définissant la propriétécontext.multifactor
sur la valeur appropriée. Dans ce cas, nous demandons la MFA en utilisant une notification poussée push.
Configurer l’application
Configurez l’application pour qu’elle envoie la demande d’authentification appropriée à l’API, selon que l’utilisateur tente ou non d’effectuer la transaction sensible qu’est le transfert de fonds. Notez que la seule différence entre les deux demandes d’authentification (avec ou sans MFA) est la permission.
Avec MFA :
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
Was this helpful?
/Sans MFA :
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
Was this helpful?
/
Paramètre | Réglage |
---|---|
audience |
Définissez l’identifiant de votre API (trouvez-le dans API Settings (Paramètres API)). Nous avons réglé le nôtre sur https://my-banking-api . |
response_type |
Défini sur id_token token afin que nous obtenions à la fois un jeton d’ID et un jeton d’accès dans la réponse. |
client_ID |
Définissez l’ID client de votre application (trouvez-le dans Application Settings (Paramètres de l’application)). |
redirect_URI |
Définissez sur une URL dans votre application vers laquelle Auth0 devrait rediriger l’utilisateur après l’authentification (trouvez-le dans Application Settings (Paramètres de l’application)). |
nonce |
Défini sur une valeur de chaîne sécurisée qui sera incluse dans la réponse de Auth0. Ceci est utilisé pour empêcher les attaques par réinsertion de jeton et est requis pour le jeton response_type=id_token token . |
state |
Défini sur une valeur opaque que Auth0 inclut lors de la redirection vers l’application. Cette valeur doit être utilisée par l’application pour empêcher les attaques CSRF. |
Configurer l’API
Configurez l’API pour valider le jeton entrant et vérifier les autorisations accordées.
Configurez deux points de terminaison pour notre API :
GET /balance
: pour récupérer le solde actuelPOST /transfer
: pour transférer des fondsUtilisez
Node.js
et plusieurs modules :express : ajoute le cadre d’applications Web Express.
jwks-rsa : récupère les clés de connexion RSA à partir d’un point de terminaison JWKS (JSON Web Key Set). À l’aide de
expressJwtSecret
nous pouvons générer un fournisseur de secrets qui fournit la bonne clé de connexion àexpress-jwt
en fonction dukid
dans l’en-tête JWT.express-jwt : vous permet d’authentifier les requêtes HTTP à l’aide de jetons JWT dans vos applications Node.js. Il fournit plusieurs fonctions qui facilitent le travail avec les JWT.
express-jwt-authz : vérifie si le jeton d’accès contient une permission précise.
Installez les dépendances :
npm install express express-jwt jwks-rsa express-jwt-authz --save
Définissez les points de terminaison de l’API, créez une fonction de médiation pour valider le jeton d’accès et sécurisez les points de terminaison à l’aide de ce logiciel médiateur. Le code de votre fichier
server.js
ressemble à l’exemple de script suivant :Chaque fois que l’API reçoit une demande, il se produit ce qui suit :// set dependencies const express = require('express'); const app = express(); const jwt = require('express-jwt'); const jwksRsa = require('jwks-rsa'); const jwtAuthz = require('express-jwt-authz'); // Create middleware for checking the JWT const checkJwt = jwt({ // Dynamically provide a signing key based on the kid in the header and the signing keys provided by the JWKS endpoint secret: jwksRsa.expressJwtSecret({ cache: true, rateLimit: true, jwksRequestsPerMinute: 5, jwksUri: `https://{yourDomain}/.well-known/jwks.json` }), // Validate the audience and the issuer audience: 'https://my-banking-api', // replace with your API's audience, available at Dashboard > APIs issuer: 'https://{yourDomain}/', algorithms: [ 'RS256' ] // we are using RS256 to sign our tokens }); // create retrieve balance endpoint app.get('/balance', checkJwt, jwtAuthz(['view:balance']), function (req, res) { // code that retrieves the user's balance and sends it back to the calling app res.status(201).send({message: "This is the GET /balance endpoint"}); }); // create transfer funds endpoint app.post('/transfer', checkJwt, jwtAuthz(['transfer:funds']), function (req, res) { // code that transfers funds from one account to another res.status(201).send({message: "This is the POST /transfer endpoint"}); }); // launch the API Server at localhost:8080 app.listen(8080); console.log('Listening on http://localhost:8080');
Was this helpful?
/Le point de terminaison appelle le logiciel médiateur
checkJwt
.express-jwt
décode le jeton et achemine la demande, l’en-tête et les données utiles versjwksRsa.expressJwtSecret
.jwks-rsa
télécharge toutes les clés de connexion à partir du point de terminaison JWKS et vérifie si l’une des clés de connexion correspond à la valeurkid
dans l’en-tête du jeton d’accès. Si aucune des clés de connexion ne correspond à la valeurkid
reçue, une erreur sera générée. S’il y a une correspondance, transmettez la bonne clé de connexion àexpress-jwt
.express-jwt
poursuit sa propre logique pour valider la signature du jeton, l’expiration, l’audience et l’émetteur.jwtAuthz
vérifie si la permission requise par le point de terminaison fait partie du jeton d’accès. Si les permissions spécifiées sont absents du jeton d’accès, la demande est rejetée avec un message d’erreur 403.