When you deny a login with api.access.deny(...)
many applications do not know how to handle the Auth0 500 with error_description. So, I would like to redirect to my own deny page.
Which of the following should I do? I do not want to user to be able to onContinuePostLogin
after all, they have been DENIED access and should not be able to continue, should not have a session or token. Full-stop.
exports.onExecutePostLogin = async (event, api) => {
// No `return`, does code stop after this?
api.access.deny('Deny example.');
// Return
return api.access.deny('Deny example.');
// Deny PLUS redirect, is this even possible?
api.access.deny('Deny example.');
api.redirect.sendUserTo("https://my-app.exampleco.com");
// Found this on the forums, redirect to logout with return
api.redirect.sendUserTo("https://{auth0_tenant}.eu.auth0.com/v2/logout?returnTo=https%3A%2F%2Fmy-app.exampleco.com");
};
Do I need return? Can someone advise on the above code?
The most correct and complete approach would be:
exports.onExecutePostLogin = async (event, api) => {
return api.access.deny('Deny example.');
};
Here’s why:
- You should always
return
the api.access.deny()
call. This ensures:
- The action stops executing immediately
- No token is issued
- The denial is properly propagated
- Trying to use
api.redirect.sendUserTo()
after api.access.deny()
won’t work because:
- The deny action terminates the authentication flow
- Any code after the deny won’t execute
- The redirect would never be reached
- If you need custom error handling, you should handle this on the client side. Here’s how:
// In your NextJS app or whatever framwork you using. Customize accordiingly
const { handleRedirectCallback } = useAuth0();
try {
await handleRedirectCallback();
} catch (error) {
//Customize based on what you see in response also check for error_description in query param when auth0 redirect
if (error.error === 'access_denied' || error.error === 'unauthorized') {
// Redirect to your custom error page
router.push('/access-denied');
}
}
If you really need custom redirection on denial, you could use Auth0’s Error Pages customization:
- Go to Auth0 Dashboard → Settings → Tenant Settings → General → Error Pages
- Choose “Custom” error page
- Set your URL (e.g.,
https://my-app.exampleco.com/access-denied
)
This would handle all authentication errors, including denials from your Actions, in a more standard way.
The approach of redirecting to logout isn’t recommended because:
- It’s unnecessary - no session was created to logout from
Thanks this is very helpful. The only reason redirecting to logout was appealing to me is that gave me fine-grained control over the returnUrl. For example I could have different access-denied pages PER client.
Regarding return api.access.deny(...)
I wish I could just throw and control app flow through exceptions. I know this is generally a bad practice, but controlling flow through undefined/null is even uglier/harder. Consider the following code:
const apiResult = CallAPI(api);
if (!apiResult) {
return;
}
function CallAPI(api) {
try {
const apiResult = fetch(...);
if (apiResult) {
return { customerData: 'blah' };
} else {
return api.access.deny("Bad customer.");
}
}
catch (err) {
return api.access.deny("External API call failed.");
}
}
In the above code I have to pass “api” around to inner functions.
If I want to stop my process for whatever reason I essentially am just passing undefined (I assume deny() returns undefined) and then exiting the main parent function based on that.