Hi @BitshiftNate,
Welcome to the Auth0 Community!
The Auth0 Dashboard requires explicit, static URLs in the “Allowed Callback URLs” field. You can’t use a wildcard like https://{organization_name}.[PRODUCT NAME].com/redirect-uri or template variables that Auth0 would evaluate. When using an identity provider like Auth0, the redirect_uri sent in the initial request needs to match a value configured in the application settings exactly.
The solution to your architecture, where each customer has a distinct, server-side-hosted subdomain, is to route all tenants through a single, static Redirect URI and then handle the post-login routing on your side.
First, change your mod_auth_openidc configuration to use a universal, static subdomain that all tenants temporarily hit:
OIDCRedirectURI "https://sso.[PRODUCTNAME].com/redirect-uri"
In your Auth0 Dashboard, you would then configure only this one URL:
- Allowed Callback URLs:
https://sso.[PRODUCT NAME].com/redirect-uri
After that, you need to tell the user’s browser where to go next (back to their specific tenant subdomain). You can use a Post-Login Action to inject this routing information.
Use the user’s app_metadata or the context of the login to determine the correct tenant subdomain and then pass that information back to the app.
Here is an example of a Post-Login Action:
/**
* Handler that will be executed after a successful login
*
* @param {Event} event - Details about the login context.
* @param {PostLoginAPI} api - Interface for interacting with Auth0.
*/
exports.onExecutePostLogin = async (event, api) => {
// 1. Determine the user's tenant/organization.
// This logic depends on where you store the tenant ID (e.g., user's app_metadata, a custom database lookup, or an organization ID if using the Organizations feature).
const userTenant = event.user.app_metadata.tenant_subdomain; // Assuming you store it here
if (userTenant) {
// 2. Add the target tenant's subdomain to the ID Token/Access Token.
// We'll use a custom claim namespace to ensure it's not confused with standard claims.
const namespace = "https://[PRODUCT NAME].com/claims";
api.idToken.setCustomClaim(`${namespace}/tenant`, userTenant);
api.accessToken.setCustomClaim(`${namespace}/tenant`, userTenant);
}
};
After the user is redirected to https://sso.[PRODUCT NAME].com/redirect-uri, your Apache server’s mod_auth_openidc will receive the token.
- Your server must then inspect the token to read the custom
tenant claim you injected in the Action.
- The server then performs an internal redirect (or a 302 redirect back to the client) to the correct, secured URL:
https://[tenant].sso.[PRODUCT NAME].com/dashboard.
If you have any further questions, please don’t hesitate to reach out.
Have a good one,
Vlad