Hosted login pages are the right default. The authorization server owns the credential handling, your application never touches a password, and you inherit the provider's work on rate limiting, breach detection, and passkey support.
The usual cost is the address bar. Your user is on example.com, clicks sign in,
and lands on example-prod-3.someauthvendor.com. That moment is where the flow
feels wrong — it's the same visual pattern as a phishing redirect, and users who
have been trained to check the domain will hesitate exactly when you need them
not to.
Mapping a custom domain fixes it. Here's what actually changes.
What moves, and what doesn't
After mapping, every endpoint your users touch is served from your domain:
authorization_endpoint https://auth.example.com/oauth2/authorize
token_endpoint https://auth.example.com/oauth2/token
jwks_uri https://auth.example.com/.well-known/jwks.json
end_session_endpoint https://auth.example.com/oauth2/logout
The tenant's canonical hostname (<tenant>.<region>.authaction.com) keeps
working. Mapping a domain adds a route; it doesn't remove one. That matters
during migration — you can point a staging client at the canonical host and
production at the custom domain, and both function.
The cookie argument
Branding is the visible reason. Cookie behaviour is the one that bites you later.
An authorization server on a vendor domain is a completely separate site from your application as far as the browser is concerned. Any cookie it sets is third-party, and third-party cookies are now blocked by default in Safari and Firefox and increasingly restricted in Chrome. That affects silent re-authentication, session checks in an iframe, and anything relying on the authorization server recognising a returning user without a full redirect.
Serve auth from auth.example.com while your app is on app.example.com and
both are the same registrable domain. Cookies scoped to .example.com are
first-party. SameSite=Lax behaves the way you'd expect across the redirect
instead of silently dropping.
If you plan to use silent refresh, this is the difference between a design that works and one that quietly degrades as browsers tighten defaults.
Setup
Three steps, and DNS propagation is the slow one.
1. Add the domain in Tenant Settings → Custom Domain. Up to five per tenant,
and it can't be a subdomain of authaction.com.
2. Create a CNAME pointing your subdomain at the tenant's canonical hostname:
| Type | Name | Target |
|---|---|---|
| CNAME | auth.example.com |
acme.eu.authaction.com |
The target follows <tenant>.<region>.authaction.com. The region segment is the
one your tenant data lives in — eu keeps it in the EU, which matters if you
have data residency obligations.
Use a subdomain, not the apex. CNAME at a zone apex isn't valid DNS, and while
some providers offer ALIAS or ANAME records to work around it, an apex
dedicated to auth isn't what you want anyway.
3. Verify in the dashboard. AuthAction does a DNS lookup to confirm the CNAME resolves to your canonical hostname. Propagation is usually minutes but the TTL on any previous record governs — if you had something else at that name, wait out the old TTL before assuming the setup is broken.
Certificates
Once verified, TLS is provisioned automatically. Nothing to upload, no CSR, no renewal to diary.
You can check what any deployment is serving:
$ echo | openssl s_client -servername auth.example.com \
-connect auth.example.com:443 2>/dev/null \
| openssl x509 -noout -issuer -subject -dates
issuer= C=US, O=Let's Encrypt, CN=YE2
subject= CN=auth.example.com
notBefore=Jul 29 09:49:12 2026 GMT
notAfter=Oct 27 09:49:11 2026 GMT
Let's Encrypt, roughly ninety days, renewed for you. Each mapped domain gets its own certificate rather than sharing a multi-SAN certificate across tenants — which means the certificate for your domain names only your domain, and nothing about your setup is visible to anyone inspecting another tenant's.
If you want to see this working on live deployments rather than take our word for
it, auth.illam.de and auth.mozhilingo.com are both running this
configuration. Run the command above against either.
Things that catch people
Registering the new redirect URIs. Your callback URLs don't change, but the
authorization server your app points at does. Update the issuer or base URL in
your SDK configuration, and confirm the application's allowed origins cover the
new domain. A redirect_uri_mismatch immediately after a domain migration is
almost always this.
CAA records. If your domain publishes a CAA record restricting which
authorities may issue certificates, and Let's Encrypt isn't among them,
provisioning fails with an error that doesn't obviously point at DNS. Check with
dig CAA example.com before assuming the verification is stuck.
Proxying the CNAME. If your DNS provider offers to proxy the record — Cloudflare's orange cloud being the common case — that breaks the verification lookup and interferes with certificate issuance. Leave it unproxied.
Existing sessions. Cookies set on the canonical hostname don't transfer to the custom domain. Users with a live session will be asked to sign in again after the switch. Worth timing deliberately rather than discovering through support tickets.
Where to look next
The OIDC Discovery tool will fetch and format the configuration a custom domain serves, which is a fast way to confirm the endpoints moved. For the CORS side of a browser client talking to a new auth origin, the CORS Tester shows which headers are present.
Full setup reference is in the custom domains documentation.