# OAuth redirect URI validation without wildcard surprises

> Use exact registered redirects, constrained loopback handling, and explicit preview-environment patterns to prevent redirect and code-stealing flaws.

Canonical URL: https://www.devobs.io/articles/oauth-redirect-uri-validation/
By: Jonah Reed
Published: 2024-05-28T23:05:38.428Z
Updated: 2026-09-06T10:18:15.722Z
Section: Identity

OAuth clients should register complete redirect URIs and authorization servers should compare the presented URI using exact string matching, apart from narrowly specified native-app loopback behavior. Wildcards and open redirects turn a small configuration convenience into a path for authorization responses to reach an attacker.

## Compare the complete registered redirect URI

[RFC 6749: The OAuth 2.0 Authorization Framework](https://www.rfc-editor.org/rfc/rfc6749) requires the authorization server to compare a complete registered redirect URI with the request value, and it requires exact matching when a full URI was registered. Compare the complete registered and presented URI strings without adding case, port, path, or encoding normalization. The current RFC 9700 guidance retains only the explicitly specified native-app localhost port exception; general URI equivalence is not permission to broaden matching. Reject fragments, user-info tricks, suffix matches, and hosts whose apparent tenant name is merely part of an attacker-controlled domain.

A registration for `https://app.example.com/oauth/callback` should not accept `http://app.example.com/oauth/callback`, `https://app.example.com.evil.test/callback`, a different port, or `/oauth/callback/next`. Query parameters need an explicit contract. If a client needs multiple fixed callback paths, register each one.

The authorization server must use the same validated redirect URI when returning an error. If validation fails, display an error locally rather than redirecting to the untrusted value. This prevents the error path itself from becoming an open redirect.

## Treat dynamic environments as registration workflow

Preview deployments tempt teams to register `https://*.preview.example.com/callback`. That wildcard gives every preview host and any takeover of its DNS or hosting allocation a chance to receive authorization responses. Prefer an automated registration lifecycle: create a random preview hostname, prove control, register its exact callback, assign a short expiry, and remove it with the environment. Use a dedicated OAuth client with limited test data and no production audience.

For tenant domains, keep the OAuth callback on one platform-controlled host and carry the tenant choice in server-side transaction state. After consuming and validating the authorization response, redirect internally to an allowlisted tenant destination. Never accept an arbitrary post-login URL from the browser.

Native applications are a distinct case. OAuth security guidance permits loopback redirect URIs with dynamically assigned ports for native clients because the local listener chooses an available port. The current [OAuth 2.0 Security Best Current Practice](https://www.rfc-editor.org/rfc/rfc9700) also reinforces exact redirect matching and warns about open redirectors. Do not generalize the loopback exception to web domains or arbitrary paths.

## Bind the response to the initiating browser

Strict URI validation is necessary but insufficient. Use the authorization code flow with PKCE, validate state or an equivalent transaction binding, and make authorization codes single-use and short-lived. Bind the code to the client and redirect URI. These controls limit what a stolen or misdelivered code can do, while exact matching prevents its delivery to the wrong endpoint in the first place.

Ory Hydra provides OAuth 2.0 and OpenID Connect and can integrate with an existing user-management system. For either Ory Network or a self-hosted deployment, review the current redirect registration path and configure exact production callbacks. Keep preview clients separate and short-lived rather than relying on a broad wildcard.

## Test exploit-shaped inputs

Build a table of registered values and expected matches, then test mixed schemes, suffix hosts, encoded path separators, duplicate query keys, fragments, Unicode hostnames, default ports, and local loopback ports. Include a redirect endpoint that itself accepts a destination parameter and verify it cannot be chained.

The next step is to export every registered redirect URI, identify wildcards and shared preview clients, and replace the riskiest entry with an automated exact-registration workflow.

## Handle ownership changes

Redirect safety depends on continued control of registered hosts. Inventory DNS records, hosting projects, and mobile application associations behind every callback. Remove registrations before retiring a domain or preview environment, and alert on callbacks whose certificates or ownership proofs expire. A URI that matched exactly at registration can become unsafe after infrastructure ownership changes. Include abandoned subdomains and transferred mobile bundle identifiers in periodic reviews.

Reviewed September 2026.

## Source references

- <https://www.rfc-editor.org/rfc/rfc6749>
- <https://www.rfc-editor.org/rfc/rfc9700>
