Rediriger avec des actions
Vous pouvez utiliser les actions post-connexion pour rediriger les utilisateurs avant la fin de la transaction d’authentification. Cela vous permet de mettre en œuvre des flux d’authentification personnalisés qui nécessitent une interaction supplémentaire avec l’utilisateur au-delà du formulaire de connexion standard.
Les redirections sont généralement utilisées pour effectuer une authentification multifacteur (MFA) personnalisée dans Auth0, mais elles peuvent également être utilisées pour :
Permettre de personnaliser l’acceptation de la politique de confidentialité, les conditions de service et les formulaires de divulgation des données.
Effectuer une collecte unique des données de profil supplémentaires requises en toute sécurité.
Autoriser les utilisateurs d’Active Directory distants à modifier leur mot de passe.
Demander aux utilisateurs de fournir une vérification supplémentaire lorsqu’ils se connectent à partir d’emplacements inconnus.
Recueillir plus d’informations sur vos utilisateurs que celles fournies lors de l’inscription initiale.
Présentation
À un niveau élevé, une action de redirection fonctionne de la manière suivante :
Une action émet une redirection vers une URL.
Le pipeline d’actions est suspendu une fois que l’action a terminé son exécution.
L’utilisateur est redirigé vers l’URL avec un paramètre
state
Lorsque le flux externe est terminé, le site externe redirige l’utilisateur vers un point de terminaison
/continue
avec le paramètrestate
Le pipeline d’actions prend le relais de l’action qui a déclenché la redirection.
Lancer une redirection
Appelez la fonction api.redirect.sendUserTo()
comme suit :
/**
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
api.redirect.sendUserTo("https://my-app.exampleco.com");
};
Was this helpful?
Les actions finiront d’exécuter cette action, puis suspendront le pipeline d’actions pour envoyer l’utilisateur à l’adresse https://my-app.exampleco.com
. En d’autres termes, toutes les actions liées aux déclencheurs post-connexion qui s’exécutent après l’Action invoquant la redirection ne s’exécuteront pas tant que le flux d’authentification n’aura pas été rétabli. Si vous connaissez les Règles de redirection, notez qu’il s’agit là d’une différence essentielle entre les actions et les Règles de redirection.
Une fois l’action exécutée, Auth0 redirige l’utilisateur vers l’URL spécifiée dans la fonction api.redirect.sendUserTo()
. Auth0 transmet également un paramètre state
dans cette URL. Par exemple :
https://my-app.exampleco.com/?state=abc123
Votre URL de redirection doit extraire le paramètre state
et le renvoyer à Auth0 pour reprendre la transaction d’authentification. L’état est une valeur opaque, utilisée pour prévenir les attaques de type falsification de requête intersite.
Reprendre le flux d’authentification
Après la redirection, reprenez l’authentification en redirigeant l’utilisateur vers le point de terminaison /continue
et incluez le paramètre state
que vous avez reçu dans l’URL. Si vous ne renvoyez pas l’état initial au point de terminaison/continue
, Auth0 perdra le contexte de la transaction de connexion et l’utilisateur ne pourra pas se connecter en raison d’une erreur invalid_request
.
Par exemple :
https://{yourAuth0Domain}/continue?state=THE_ORIGINAL_STATE
Dans cet exemple,THE_ORIGINAL_STATE
est la valeur générée par Auth0 et envoyée à l’URL de redirection. Par exemple, si votre règle redirige vers https://my-app.exampleco.com/
, Auth0 utilisera une URL de redirection semblable à https://my-app.exampleco.com/?state=abc123
, ce qui fait de abc123
la valeur THE_ORIGINAL_STATE
. Pour reprendre la transaction d’authentification, vous devez rediriger vers :
https://{yourAuth0Domain}/continue?state=THE_ORIGINAL_STATE
Lorsqu’un utilisateur a été redirigé vers le point de terminaison /continue
, le pipeline d’actions recommence à la même action qui a invoqué la redirection en appelant la fonction onContinuePostLogin
. Pour que les redirections fonctionnent correctement, vous devez créer une fonction avec la signature suivante dans l’action qui a invoqué la redirection :
/**
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
api.redirect.sendUserTo("https://my-app.exampleco.com");
};
/**
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onContinuePostLogin = async (event, api) => {
}
Was this helpful?
Transmettre des données au site externe
Pour transmettre des données au site externe, nous recommandons de coder ces données dans un JWT signé afin que votre application puisse s’assurer qu’elles n’ont pas été altérées pendant le transfert. Cela est possible grâce aux actions avec les fonctions api.redirect.encodeToken
et api.redirect.sendUserTo
:
/**
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
const YOUR_AUTH0_DOMAIN = event.secrets.YOUR_AUTH0_DOMAIN || event.request.hostname
// Craft a signed session token
const token = api.redirect.encodeToken({
secret: event.secrets.MY_REDIRECT_SECRET,
expiresInSeconds: 60,
payload: {
// Custom claims to be added to the token
email: event.user.email,
externalUserId: 1234,
continue_uri: `https://${YOUR_AUTH0_DOMAIN}/continue`
},
});
// Send the user to https://my-app.exampleco.com along
// with a `session_token` query string param including
// the email.
api.redirect.sendUserTo("https://my-app.exampleco.com", {
query: { session_token: token }
});
}
Was this helpful?
Le code ci-dessus ajoute un paramètre de chaîne de requête session_token
à l’URL utilisée pour la redirection (en plus du paramètre state
ajouté automatiquement par Auth0). Ce jeton contiendra les éléments suivants :
Élément de jeton | Description |
---|---|
sub |
Auth0 user_id de l’utilisateur. |
iss |
Nom d’hôte de votre domaine locataire Auth0 (par exemple, example.auth0.com ). |
exp |
Heure d’expiration (en secondes) spécifiée avec le paramètre expiresInSeconds . Doit être aussi court que possible pour éviter la réutilisation du jeton. La valeur par défaut est 900 secondes (15 minutes). |
ip |
Adresse IP de la demande d’authentification d’origine. |
email |
Demande personnalisée avec une valeur spécifiée dans le paramètre payload.email . |
externalUserId |
Réclamation personnalisée avec une valeur spécifiée dans le paramètre payload.externalUserId . |
signature |
Utilisant le secret spécifié ci-dessus, le jeton sera signé avec l’algorithme HS256. |
S’assurer que le jeton n’a pas été altéré
Le système externe doit vérifier que le jeton n’a pas été altéré pendant le transit. Pour ce faire, le système distant doit s’assurer que la signature du jeton est valide et, le cas échéant, que la session dans le système externe appartient au même utilisateur Auth0 que celui indiqué dans la demande sub
du jeton.
Renvoyer les données à Auth0
Une fois le flux personnalisé terminé sur le site externe, l’utilisateur doit être redirigé vers le point de terminaison /continue
. Dans certains cas, vous pouvez renvoyer des données à Auth0 afin de modifier le flux d’authentification ou d’autorisation pour cet utilisateur (par ex., si vous mettez en place des contrôles CAPTCHA ou une MFA personnalisée).
Utiliser les métadonnées de l’application dans la mesure du possible
Si possible, le système à distance doit utiliser Auth0 Management API pour stocker les informations personnalisées en tant que métadonnées d’application sur le profil utilisateur Auth0. Lorsque le flux d’actions d’Auth0 redémarre, ces informations sont disponibles dans l’objet event.user.app_metadata
. Cette approche évite de transmettre des informations sensibles à Auth0 sur le canal frontal.
Soyez sélectif lorsque vous stockez des données sur le profil utilisateur Auth0
Évitez de stocker trop de données dans le profil Auth0. Ces données sont destinées à des fins d’authentification et d’autorisation. Les métadonnées et les fonctionnalités de recherche d’Auth0 ne sont pas destinées à des scénarios nécessitant une fréquence de recherche ou de mise à jour élevée, comme les études de marché. Votre système risque de rencontrer des problèmes d’évolutivité et de performance si vous utilisez Auth0 à ces fins.
Si votre application nécessite l’accès à des données substantielles sur l’utilisateur, l’approche recommandée est de stocker ces données dans un système externe et de stocker une clé étrangère (ID de l’utilisateur) dans Auth0 afin que les systèmes principaux puissent récupérer les données en cas de besoin.
Envoyer des données sur le canal frontal
La transmission d’informations dans les deux sens sur le canal frontal ouvre une surface d’attaque aux acteurs menaçants. Si vous devez impérativement envoyer des informations sur le canal frontal, tenez compte des conseils suivants :
Renvoyer des informations à l’action
Un jeton de session signé est nécessaire pour renvoyer des informations sensibles à Auth0. Vous pouvez facilement valider ce jeton dans une Action à l’aide du code suivant :
/**
* @param {Event} event - Details about the user and the context in which they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to change the behavior of the login.
*/
exports.onContinuePostLogin = async (event, api) => {
const payload = api.redirect.validateToken({
secret: event.secrets.PRECONFIGURED_SECRET,
tokenParameterName: 'my_token',
});
// use the data encoded in the token, such as:
api.idToken.setCustomClaim('color', payload.favorite_color);
}
Was this helpful?
Le jeton sera validé pour s’assurer que :
la signature est valide,
le jeton n’a pas expiré.
La demande
state
dans le jeton correspond au paramètrestate
utilisé dans le processus de redirection.
Élément de jeton | Description |
---|---|
sub |
Auth0 user_id de l’utilisateur. |
iss |
Application ciblée pour la redirection. |
exp |
Doit être aussi court que possible pour éviter la réutilisation du jeton. |
state |
Paramètre d’état envoyé au site distant dans le cadre de la redirection. Doit être inclus dans le jeton pour éviter les attaques par réinsertion. |
other |
Toutes les autres demandes personnalisées seront exposées comme payload dans le code ci-dessus. |
signature |
Le jeton doit être signé avec l’algorithme HS256. |
Pour éviter les attaques par réinsertion, le jeton doit être renvoyé à Auth0 en effectuant une requête POST vers le point de terminaison /continue
. L’option tokenParameterName
dans le code vous permet de spécifier le nom du champ contenant votre jeton.
Méthodes d’authentification personnalisées
Une fois la redirection réussie dans le pipeline de connexion, les actions peuvent enregistrer des événements relatifs aux méthodes d’authentification personnalisées dans la session de l’utilisateur. Le tableau event.authentication.methods
contiendra une entrée pour la méthode personnalisée pendant toute la durée de la session dans le navigateur de l’utilisateur. Chaque entrée de ce tableau comporte un horodatage indiquant le moment où la méthode d’authentification a été enregistrée.
Une action personnalisée peut déclencher une redirection si la méthode personnalisée requise ne figure pas dans le tableau event.authentication.methods
ou est trop ancienne.
Vous pouvez utiliser api.redirect.sendUserTo()
pour diriger l’utilisateur vers une page qui implémente une méthode d’authentification personnalisée. Vous pouvez utiliser api.authentication.recordMethod()
dans le gestionnaire exports.onContinuePostLogin
pour stocker un enregistrement de la méthode complétée dans la session de l’utilisateur.
L’enregistrement stocké dans le tableau event.authentication.methods
aura une propriété name
qui correspond à l’URL choisie dans api.authentication.recordMethod()
. L’URL capturée ici vous permet de rechercher dans les méthodes d’authentification terminées de la transaction en cours pour déterminer si votre méthode personnalisée a déjà été utilisée.
Votre flux de travail peut exiger que la méthode personnalisée soit ré-exécutée périodiquement pendant la durée de la session d’un utilisateur. Par exemple, les scénarios MFA personnalisés peuvent exiger une nouvelle vérification de la part de l’utilisateur après un délai donné.
L’exemple ci-dessous compare l’horodatage d’un enregistrement existant pour déterminer quand exécuter à nouveau la méthode personnalisée :
const CUSTOM_METHOD_URL = "https://path.to.prompt";
const PROMPT_TTL = 1000 * 60 * 60 * 24; // 24h
/**
* Handler that will be called during the execution of a PostLogin flow.
*
* @param {Event} event - Details about the user and the context in which
* they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to
* change the behavior of the login.
*/
exports.onExecutePostLogin = async (event, api) => {
// Search authentication method records for an entry representing our
// custom method.
const methodRecord = event.authentication?.methods.find((record) =>
validateCustomRecord(record, CUSTOM_METHOD_URL, PROMPT_TTL)
);
if (!methodRecord) {
const sessionToken = api.redirect.encodeToken({
payload: {
user_id: event.user.user_id,
},
secret: event.secrets.SESSION_TOKEN_SECRET,
});
// We didn't find a valid record, so we send the user to the
// URL that implements the custom method with the signed
// data we encoded in `sessionToken`.
api.redirect.sendUserTo(CUSTOM_METHOD_URL, {
query: { session_token: sessionToken },
});
}
};
/**
* Handler that will be invoked when this action is resuming after an
* external redirect. If your onExecutePostLogin function does not perform
* a redirect, this function can be safely ignored.
*
* @param {Event} event - Details about the user and the context in which
* they are logging in.
* @param {PostLoginAPI} api - Interface whose methods can be used to
* change the behavior of the login.
*/
exports.onContinuePostLogin = async (event, api) => {
const payload = api.redirect.validateToken({
secret: event.secrets.SESSION_TOKEN_SECRET,
tokenParameterName: "session_token",
});
if (!validateSessionToken(payload)) {
return api.access.deny("Unauthorized");
}
// Record the completion of our custom authentication method.
// THIS NEW API IS ONLY AVAILABLE IN `onContinuePostLogin`.
api.authentication.recordMethod(CUSTOM_METHOD_URL);
};
function validateCustomRecord(record, url, ttl) {
if (!record) {
// No record means it isn't valid.
return false;
}
if (record.url !== url) {
// This isn't a record of our custom method.
return false;
}
// Timestamps are rendered as ISO8601 strings.
const timestamp = new Date(record.timestamp);
// The record is valid if it was recorded recently enough.
return timestamp.valueOf() >= Date.now() - ttl;
}
function validateSessionToken(payload) {
// Custom validation logic for the data returned by the
// custom method goes here.
return true;
}
Was this helpful?
L’API api.authentication.recordMethod()
n’est disponible que dans le gestionnaire exports.onContinuePostLogin
. Cette méthode permet d’éviter les tentatives d’attaque par connexion en enregistrant la méthode personnalisée après avoir effectué la redirection.
Restrictions et limites
Les actions de redirection ne fonctionnent pas avec :
Le point de terminaison du propriétaire de la ressource.
Il est impossible d’utiliser des actions de redirection lorsque vous appelez le point de terminaison Obtenir le jeton d’Authentication API pour le flux de mot de passe du propriétaire de ressource. Comme l’utilisateur n’est pas dans un flux de redirection au départ, vous ne pouvez pas le rediriger dans une action.
Flux où prompt=none
L’objectif de prompt=none
étant d’éviter tout scénario dans lequel l’utilisateur doit saisir des données, toute redirection se traduit par erreur=interaction_required
.
Comme les actions sont exécutées après la création d’une session d’authentification, vous ne pouvez pas utiliser prompt=none
si vous avez une règle de redirection qui tente de bloquer l’accès aux jetons sous certaines conditions (authentification multifacteur personnalisée, CAPTCHA à la connexion, etc.).
Vous ne pouvez pas créer un flux de redirection qui bloque l’accès aux jetons et contourne l’action de redirection si prompt=none
. Après une tentative infructueuse, un utilisateur peut appeler à nouveau avec prompt=none
et obtenir des jetons parce que sa session d’authentification a été créée, même si les actions ont échoué la première fois.
Jetons d’actualisation
Étant donné que l’utilisation d’un jeton d’actualisation nécessite un appel de canal d’appui au point de terminaison Obtenir le jeton d’Authentication API, cette opération échouera également en cas de tentative de redirection.
Il est difficile de vérifier de manière sûre que les restrictions de connexion ont été appliquées. Aucun identifiant de session cohérent dans le contexte ne peut être utilisé pour collecter des informations associées à la session, comme les défis MFA résolus par cet utilisateur. Par conséquent, vous ne pouvez absolument pas utiliser prompt=none
.
Chaque fois que api.redirect.sendUserTo()
est appelé dans une action, si prompt=none
a été transmis, l’autorisation échoue avec error=interaction_required
. Cependant, comme la session de l’utilisateur est créée même si les actions échouent, vous ne pouvez pas être sûr qu’un utilisateur a relevé tous les défis en matière de redirection. Vous ne pouvez donc pas utiliser prompt=none
pour obtenir des jetons.
Dans ce cas précis, nous vous recommandons d’utiliser exclusivement les jetons d’actualisation, qui permettent de s’assurer que l’utilisateur a répondu correctement aux défis si ceux-ci sont requis pour générer un jeton d’actualisation.