loginos

Can I use wildcard redirect URIs with OAuth?

loginos teamUpdated 7 min read

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 localhost redirect URIs in native apps.
  • OpenID Connect Core 1.0 requires the redirect_uri to 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:

  1. Matching bugs. RFC 9700’s example registers https://*.somesite.example/*. A naive server reads * as “any characters” and accepts https://attacker.example/.somesite.example, a different domain entirely.
  2. 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.
  3. 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:

ProviderWildcards in redirect URIsLimits and warnings
GoogleNoRedirect URIs can’t contain *, and redirect_uri must exactly match an authorized URI.
Microsoft Entra IDOnly for apps that sign in work or school accounts alone, added in the manifest editorNot for apps that also sign in personal Microsoft accounts. Microsoft says to avoid them.
Auth0One * in the subdomain furthest from the rootMatches one level only. Auth0 says not to use them in production and suggests {organization_name} placeholders.
OktaOne * in the lowest-level subdomain, once turned on per appHTTPS only, not in paths or logout URIs. Okta calls wildcard subdomains an insecure practice.
KeycloakAt 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 appsOptional wildcard matching per callback URLAny 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.com covers 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/domains takes up to 1,000 hosts at once and is safe to repeat, and DELETE /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:

DNS record
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
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

All answers