Can I use wildcard redirect URIs with OAuth?
Short answer
Usually not, and you shouldn’t rely on them. RFC 9700, the OAuth 2.0 Security Best Current Practice, requires authorization servers to match redirect URIs exactly, because loose patterns have let attackers steal authorization codes. Google rejects wildcards, while Auth0 and Okta allow narrow ones with warnings. Register exact URIs through an API instead, or use a provider that verifies wildcard ownership or asks your server.
You run many subdomains, or your customers bring their own domains, and registering a callback URL for each one by hand doesn’t scale. A pattern like https://*.example.com/callback looks like the obvious fix. The OAuth specs say no: a redirect URI should match a registered value exactly, character for character. Some providers still accept wildcards, with restrictions and warnings, and there are safer ways to get the same result.
What do the OAuth specs say about wildcard redirect URIs?
A redirect URI is the address where the authorization server sends the browser back after sign-in, with an authorization code. The code is what your app trades for tokens, so the redirect URI decides who gets it.
- RFC 6749, the OAuth 2.0 framework from 2012, asked servers to require the complete redirect URI, but allowed registering only part of it when that wasn’t possible.
- RFC 9700, the OAuth 2.0 Security Best Current Practice published in January 2025, updates RFC 6749 and closes that gap. Section 2.1 says authorization servers “MUST utilize exact string matching” when they compare redirect URIs. The only exception is the port of
localhostredirect URIs in native apps. - OpenID Connect Core 1.0 requires the
redirect_urito exactly match a pre-registered value, compared as plain strings. - OAuth 2.1, still an Internet-Draft in October 2026, requires exact matching as well.
Exact means exact: same scheme, host, port, path and query. https://app.example.com/callback and https://app.example.com/callback/ are two different URIs.
Why are wildcard redirect URIs dangerous?
Your client ID is public, so anyone can build an authorization request for your app with a redirect URI of their choice. The server’s matching is the only thing that decides where the code goes. RFC 9700 describes three ways patterns fail:
- Matching bugs. RFC 9700’s example registers
https://*.somesite.example/*. A naive server reads*as “any characters” and acceptshttps://attacker.example/.somesite.example, a different domain entirely. - Subdomain takeover. Even correct matching trusts every subdomain. Subdomain takeover is when an attacker gains control of one of your subdomains, typically through a stale CNAME record that still points at a cloud service you stopped using. Once they claim that service, the wildcard hands them your users’ codes.
- Open redirects. An open redirect is a URL on your site that forwards the browser to any address given in a parameter. A broad pattern can match such a URL, which then carries the sign-in response off your site. RFC 9700 forbids clients from exposing open redirectors.
What leaks is an authorization code, or a token in older flows that return one directly. A code alone isn’t enough for a confidential client, since the exchange needs your client secret. But an attacker can try to inject the stolen code into your own callback. PKCE (Proof Key for Code Exchange), which binds each code to a secret held by whoever started the sign-in, blocks that. Exact matching plus PKCE is the baseline.
Which providers allow wildcard redirect URIs?
Rules differ, and they change, so check your provider’s current docs. As of October 2026:
| Provider | Wildcards in redirect URIs | Limits and warnings |
|---|---|---|
| No | Redirect URIs can’t contain *, and redirect_uri must exactly match an authorized URI. | |
| Microsoft Entra ID | Only for apps that sign in work or school accounts alone, added in the manifest editor | Not for apps that also sign in personal Microsoft accounts. Microsoft says to avoid them. |
| Auth0 | One * in the subdomain furthest from the root | Matches one level only. Auth0 says not to use them in production and suggests {organization_name} placeholders. |
| Okta | One * in the lowest-level subdomain, once turned on per app | HTTPS only, not in paths or logout URIs. Okta calls wildcard subdomains an insecure practice. |
| Keycloak | At the end of a URL pattern, like https://app.example.com/* | A lone * allows any URL; the docs say not to use it in production. |
| GitHub OAuth apps | Optional wildcard matching per callback URL | Any subdomain or subdirectory of the callback URL matches. GitHub warns that attackers can then receive codes. |
On GitHub, an OAuth app that had a single callback URL before August 3, 2026 has wildcard matching turned on for it, and GitHub recommends turning it off if you don’t need it.
What can you do instead of a wildcard?
Four approaches give you many domains without a loose pattern.
Verify the parent domain first
A wildcard is safer when the provider accepts it only after you prove control of the parent domain, usually with a DNS TXT record, and never lets it cover the parent domain itself. That rules out typos and patterns over domains you don’t control. The subdomains are still only as safe as your DNS, so remove records for services you no longer use.
Register exact URIs through an API
Auth0, Microsoft Entra ID and Amazon Cognito, among others, let your server change a client’s redirect URIs through a management API. Call it when a domain goes live and again when it goes away. Watch the caps. Auth0 allows 100 callback URLs per application and Amazon Cognito 100 per app client. Microsoft Entra ID allows 256 redirect URIs per app, or 100 if the app also signs in personal Microsoft accounts. How to add a redirect URI automatically has the code.
One fixed callback that redirects onward
Register a single callback, like https://login.example.com/callback, and carry a reference to the return address in state. After the code exchange, the callback sends the person on to the right domain. Microsoft documents this pattern as its alternative to wildcards. It has two catches:
- The onward redirect is an open redirect unless you check the target against your own list. Keep the target itself out of
state; Microsoft suggests a key that points to data you stored. - The session starts on the login domain. Subdomains can share a cookie set for the parent domain, but a customer’s own domain can’t, so it needs a one-time hand-off token: a small identity provider you now maintain. Authentication on customers’ custom domains compares the two designs.
Let your server confirm new domains
In this approach, the provider asks your server about each new domain the first time a sign-in comes from it, and your server answers from its own records. Nothing is trusted because of how a name looks.
RFC 9126, the spec for pushed authorization requests (PAR), has a related idea. When a client sends its request to the server first, with authentication, the server may accept a redirect URI that was never registered. That is optional, so check whether your provider does it.
How loginos does it
In loginos, the callback path is the same on every domain, so you register domains, not URLs. loginos only sends people back to https://<one of your domains><callback path>, exactly, with no query string. Three things cover many domains:
- A verified wildcard.
*.example.comcovers every subdomain of example.com at any depth, but never example.com itself. You prove ownership once with a TXT record, and until loginos finds it, the wildcard matches nothing. - Exact hosts from your server.
POST /api/v1/domainstakes up to 1,000 hosts at once and is safe to repeat, andDELETE /api/v1/domains/{host}removes one. A platform has no limit on domains. - Automatic domains. loginos asks your server about an unknown host the first time someone signs in there, and adds it only if your server says yes. See automatic domains.
The record that proves you own example.com:
Type TXT
Name _loginos.example.com
Value loginos-verify=<the value the console or the API gives you>Add the wildcard in the console’s Domains tab or from your server, then check the record:
curl -X POST https://loginos.io/api/v1/domains \
-u "$LOGINOS_APP_KEY:$LOGINOS_APP_SECRET" \
-H "content-type: application/json" \
-d '{"host": "*.example.com"}' # the answer includes the TXT record
curl -X POST "https://loginos.io/api/v1/domains/*.example.com/verify" \
-u "$LOGINOS_APP_KEY:$LOGINOS_APP_SECRET"Pushed requests get no shortcut: loginos applies the same domain check to /oauth/par as to the redirect flow. A wildcard can’t cover your customers’ own domains, so register those by name or confirm them with automatic domains. Domains has the details.
Frequently asked questions
Does RFC 6749 allow wildcard redirect URIs?
RFC 6749 left room for them. It asked servers to require the complete redirect URI. As a fallback, it allowed registering only part of it, such as everything except the query string, and some servers went further and accepted patterns. RFC 9700 updates RFC 6749 and requires exact string matching, so a server that follows current best practice doesn’t accept wildcards.
Can I vary the path or query string of a redirect URI?
Not with exact matching. Put per-request data in state, which the server returns untouched, or keep it in your session and put only a random key in state. RFC 6749 already suggested state for this.
Do I need wildcards for localhost?
No. For native apps that listen on a loopback address, RFC 9700 makes servers accept any port, so the app can pick a free one. For web development, register your local address exactly, like http://localhost:3001/callback, next to your production URIs.
Is a wildcard safe if I own every subdomain?
Safer, not safe. Every subdomain becomes a valid place to receive codes, including forgotten ones with stale DNS records and any subdomain where customers or users can publish their own pages. If you use one, audit your DNS records and remove the ones you no longer need.
Can PAR replace redirect URI registration?
Sometimes. RFC 9126 lets a server accept unregistered redirect URIs from clients that push their requests with authentication, but servers don’t have to. loginos doesn’t: a pushed request must use one of your domains like any other.
One account for every domain you run
loginos is an OpenID Connect provider with passkeys, a user pool shared by all of your domains, roles in every token, and account linking for the users you already have. Add your platform and its domains in a few minutes.
Keep reading
- Customer domainsHow do I add a redirect URI automatically when a customer adds a domain?Call your identity provider’s management API from the code that marks a customer’s domain as verified and active, and add that domain’s callback URL there. Run the call from a job queue so it retries, make it safe to repeat, and remove the URL when the customer disconnects the domain. With loginos you register the host with one POST, or let loginos ask your server.6 min read
- Customer domainsHow do I handle authentication on customers’ custom domains in my SaaS?Let each custom domain run its own sign-in: it sends people to your identity provider and gets them back on its own callback, where your app sets that domain’s session cookie. The provider must accept every custom domain as a redirect target, so register a domain once your records mark it verified and active, and remove it when the customer leaves. loginos does this with one API call.7 min read
- Customer domainsHow do I make NextAuth work with multiple domains?Leave AUTH_URL and NEXTAUTH_URL unset and turn on trustHost, so Auth.js builds its URLs from the host of each request instead of one fixed domain. Each domain then keeps its own session cookie, and your identity provider must accept the Auth.js callback URL on every domain. With loginos, someone signed in on one domain comes back on the others without a form.7 min read
- Customer domainsAuth0 multiple custom domains is too expensive, what are the alternatives?The main alternatives are one shared login domain for all your brands, one Auth0 tenant per brand, or a self-hosted server such as Keycloak, Zitadel or Authentik, where every domain is yours. Auth0 offers Multiple Custom Domains only on Enterprise. If your real need is many app domains sharing one user pool, loginos fits, but its sign-in page always stays on loginos.io.5 min read