The End of Life (EOL) date of Rules and Hooks will be November 18, 2026, and they are no longer available to new tenants created as of October 16, 2023. Existing tenants with active Hooks will retain Hooks product access through end of life.We highly recommend that you use Actions to extend Auth0. With Actions, you have access to rich type information, inline documentation, and public
npm
packages, and can connect external integrations that enhance your overall extensibility experience. To learn more about what Actions offer, read Understand How Auth0 Actions Work.To help with your migration, we offer guides that will help you migrate from Rules to Actions and migrate from Hooks to Actions. We also have a dedicated Move to Actions page that highlights feature comparisons, an Actions demo, and other resources to help you on your migration journey.To read more about the Rules and Hooks deprecation, read our blog post: Preparing for Rules and Hooks End of Life.- Custom privacy policy acceptance, terms of service, and data disclosure forms.
- Securely performing a one-time collection of additional required profile data.
- Allowing remote Active Directory users to change their password.
- Requiring users to provide additional verification when logging in from unknown locations.
- Gathering more information about your users than they provided at initial signup.
Start redirect and resume authentication
Set thecontext.redirect
property as follows:
context.redirect.url
property. Auth0 also passes a state
parameter in that URL. For example:
state
parameter and send it back to Auth0 to resume the authentication transaction. State is an opaque value, used to prevent Cross-Site Request Forgery (CSRF) attacks.
After the redirect, resume authentication by redirecting the user to the /continue
endpoint and include the state
parameter you received in the URL. If you do not send the original state back to the /continue
endpoint, Auth0 will lose the context of the login transaction and the user will not be able to log in due to an invalid_request
error.
For example:
THE_ORIGINAL_STATE
is the value that Auth0 generated and sent to the redirect URL. For example, if your rule redirected to https://example.com/foo
, Auth0 would use a redirect URL similar to https://example.com/foo?state=abc123
. So abc123
would be the THE_ORIGINAL_STATE
. To resume the authentication transaction, you would redirect to:
/continue
endpoint:
- all rules will be run again, however, the
context.redirect
will be ignored to allow authentication to continue. - any changes to the user object are made during the redirect, prior to calling the
/continue
endpoint. For example, updates through the Auth0 are available after continuing the transaction.
Validate resumed login
To distinguish between user-initiated logins and resumed login flows, check thecontext.protocol
property:
Force password change example
In some cases, you may want to force users to change their passwords under specific conditions. You can write a rule that has the following behavior:- The user attempts to log in and needs to change their password.
- The user is redirected to an application-specific page with a JWT in the query string. This JWT ensures that only this user’s password can be changed and must be validated by the application.
- The user changes their password in the application-specific page by having the application call the Auth0 Management API
- Once the user has successfully changed their password, the application extracts the
authorize_again
claim from the verified and decoded JWT, then proceeds to redirect the user to that URL allowing them to sign in with their new password.
Where to store data
Beware of storing too much data in the Auth0 profile. This data is intended to be used for authentication and authorization purposes. The metadata and search capabilities of Auth0 are not designed for marketing research or anything else that requires heavy search or update frequency. Your system is likely to run into scalability and performance issues if you use Auth0 for this purpose. A better approach is to store data in an external system and store a pointer (the user ID) in Auth0 so that backend systems can fetch the data if needed. A simple rule to follow is to store only items that you plan to use in rules to add to tokens or make decisions.Security considerations
Passing information back and forth in the front channel opens up surface area for to attack. This should definitely be done only in conditions where you must take action in the rule (such as rejecting the authorization attempt withUnauthorizedError
).
If, however, you need to communicate directly back to Auth0 and give it instructions for restricting access (you are implementing CAPTCHA checks or custom MFA), then you must have a way to securely tell Auth0 that the requirements of that operation were performed. Likewise, if you need to hand information to the application that you are redirecting to, then you must have a secure way to ensure that the information transferred has not been tampered with.
Ensure app is logging into the same user
The application is going to redirect the user back to the Auth0 tenant, so any data related to the user can be gathered through the that is returned to the application. However, you may want to ensure that the application is logging into the same user that is being redirected from to ensure that there is no tampering of any sort in-between. Therefore you will likely want to send a token along with the request. The token sent to the app should have the following requirements:Token Element | Description |
---|---|
sub | The Auth0 user_id of the user. |
iss | An identifier that identifies the rule itself. |
aud | The application that is targeted for the redirect. |
jti | A randomly generated string that is stored for confirmation in the user object (in the rule code, set user.jti = uuid.v4(); and then add it as a jti to the token you create). user.jti will still be set when rules run again when /continue is called. This is inline with specifications. |
exp | Should be as short as possible to avoid re-use of the token. |
other | Any other custom claims information you need to pass. |
signature | Assuming that the application has a secure place to store a secret, you can use HS256 signed signatures. This greatly reduces the complexity of the solution and since the token being passed back will have to be signed as well, this is a requirement of this solution. You can use RS256, but it requires the creating of a certificate and updating that certificate when it expires. If you are not passing any information directly back to the rules, then you could use an SPA for this intermediate app and then may prefer RS256 so that the application doesn’t have to store the info. It would require you to have a way to validate the token, either through an introspection endpoint or through a public JWKS endpoint. |
This token should not be treated as a Bearer token! It is a signed piece of information for use in the application. The application should still redirect back to Auth0 to authenticate the user.
Pass information back to the rule
In most scenarios, even if you want to pass information from the rule to the application. The application will hopefully be able to safely store the information in whatever storage is necessary. Even if the idea is to update the app or user metadata in Auth0, that can be done using the management API and the user information will be updated as long as it has been completed before redirecting the user back to the/continue
endpoint. Only if the rule itself must get information and that information is only relevant to this particular sign in session should you pass information back to the rule.
When passing information back to the /continue
endpoint, the token passed should have the following requirements:
Token Element | Description |
---|---|
sub | The Auth0 user_id of the user. |
iss | The application that is targeted for the redirect. |
aud | Some identifier that identifies the rule itself. |
jti | The same JTI that was stored in the token passed to the application (NOTE: it should match user.jti or fail). |
exp | Should be as short as possible to avoid reuse of the token. |
other | Any other custom claims information you need to pass. |
signature | Assuming that the application has a secure place to store a secret, you can use HS256 signed signatures. This greatly reduces the complexity of the solution and since the token being passed back will have to be signed as well, this is a requirement of this solution. You can use RS256, but it requires the creating of a certificate and updating that certificate when it expires. |
context.request.body.token
(or something similar) rather than passing it as a query parameter. This is similar to the form-post method for authentication.
If you are not passing information back to the /continue
endpoint, you may want to denylist the JTI unless your expiration times are short enough that replay attacks will be almost impossible.
Restrictions and limitations
Redirect Rules won’t work with: You can detect the above cases by checkingcontext.protocol
:
- For Password exchange:
context.protocol === 'oauth2-password'
- For exchange:
context.protocol === 'oauth2-refresh-token'
- For logins:
context.protocol === 'oauth2-resource-owner'
Session timeout
Redirect rule sessions are normally valid for 3 days unless you have configured a shorter timeout in your Login Session Management settings. You can find these settings in your tenant’s advanced settings.Resource Owner endpoint
It is impossible to use redirect rules in the context where you are calling/oauth/token
directly for the Resource Owner Password Grant. Since the user is not in a redirect flow to begin with, you can not redirect the user in a rule. If you attempt to set context.redirect you will get a failed login attempt with the error interaction_required.
Flows where prompt=none
Since the goal ofprompt=none
is to avoid any scenario where the user will be required to enter input, any redirection will result in an error=interaction_required
.
Since rules run after an authentication session is created, you cannot use prompt=none
if you have a redirect rule that is attempting to block access to tokens under certain conditions (custom MFA, CAPTCHA with login, etc.).
You cannot create a redirect flow that blocks token access and bypasses the redirect rule if prompt=none
because after a failed attempt, a user can simply call again with prompt=none
and get tokens because their authentication session has been created even though rules failed the first time.
Refresh tokens
Due to the fact that using a refresh token requires a backchannel call to/oauth/token
, this will also fail if you set context.redirect
.
It is difficult to securely verify that any restrictions on login were carried out. There is not a consistent session ID in the context that could be used to collect information associated with the session such as this user passed MFA challenges. Therefore, you cannot use prompt=none
at all.
Anytime context.redirect
is set in a rule, if prompt=none
was passed, then the authorization fails with error=interaction_required
, but since the user’s session is created even if rules fail, we can’t trust that a user passed all context.redirect
challenges and therefore can’t use prompt=none
as a way to get tokens.
In this specific case, we recommend that you use refresh tokens exclusively, because you can ensure that a user passed challenges if those challenges are required to generate a refresh token.