OAuth2 Redirect URIs — Secure Callback Configuration for Authorization Flows
In this tutorial, you will learn about OAuth2 Redirect URIs. We cover key concepts, practical examples, and best practices to help you master this topic.
OAuth2 redirect URIs are the callback URLs where the authorization server sends users (with authorization codes or tokens) after authentication and consent.
What You'll Learn
How redirect URIs work, validation rules, common misconfigurations, and how attackers exploit weak redirect URI validation.
Why It Matters
Redirect URI validation is the primary defense against authorization code interception. A single misconfigured redirect URI can compromise the entire OAuth2 flow.
Real-World Use
Google requires exact redirect URI matching. GitHub supports multiple registered URIs. Facebook allows port variation. Each provider has different validation rules, but the security principle is the same.
flowchart LR
A["Client"] -->|"Register redirect_uri\nhttps://app.com/callback"| B["Auth Server"]
A -->|"Auth request with redirect_uri"| B
B -->|"Validate redirect_uri\nagainst registration"| B
B -->|"Redirect with code\nonly to registered URI"| C["https://app.com/callback"]
style A fill:#dbeafe,stroke:#2563eb
style B fill:#fef3c7,stroke:#d97706
style C fill:#dcfce7,stroke:#16a34a
Redirect URI Validation Rules
| Provider | Validation Rule |
|---|---|
| Strict (recommended) | Exact match of the full URL |
| Path match | Protocol, host, port must match; path prefix allowed |
| Pattern match | Wildcards or glob patterns (dangerous) |
Code Example: Secure Redirect URI Validation
from urllib.parse import urlparse
REGISTERED_REDIRECT_URIS = [
"https://app.dodatech.com/oauth/callback",
"https://app.dodatech.com/oauth/callback-v2"
]
def validate_redirect_uri(redirect_uri):
"""Strict validation: exact match against registered URIs."""
if redirect_uri in REGISTERED_REDIRECT_URIS:
return True
# Additional security checks
parsed = urlparse(redirect_uri)
# Reject non-HTTPS
if parsed.scheme != "https":
return False
# Reject IP addresses
import re
if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}", parsed.hostname):
return False
# Reject localhost
if parsed.hostname in ("localhost", "127.0.0.1"):
return False
# Reject fragments
if parsed.fragment:
return False
return False # No match
# Test
uris = [
"https://app.dodatech.com/oauth/callback",
"https://evil.com/oauth/callback",
"https://app.dodatech.com/oauth/callback?extra=param",
"http://app.dodatech.com/oauth/callback"
]
for uri in uris:
print(f"{uri}: {'OK' if validate_redirect_uri(uri) else 'REJECTED'}")
Expected output:
https://app.dodatech.com/oauth/callback: OK
https://evil.com/oauth/callback: REJECTED
https://app.dodatech.com/oauth/callback?extra=param: REJECTED
http://app.dodatech.com/oauth/callback: REJECTED
Open Redirector Attack
An open redirector is an endpoint that redirects to any URL specified in a parameter. If your app has an open redirector and OAuth2 redirect URIs are not strictly validated, an attacker can:
- Register a redirect URI that matches your app's redirector pattern
- Intercept the authorization code via the redirector
Common Mistakes
1. Using Wildcards in Redirect URIs
https://*.ngrok.io/callback allows any ngrok URL. An attacker can use their own ngrok tunnel.
2. Allowing Localhost in Production
http://localhost:3000/callback is useful for development but dangerous in production.
3. Not Validating redirect_uri in Token Exchange
The token endpoint must also validate that the redirect_uri matches the one used in the authorization request.
4. Allowing Query Parameters in Redirect
If the redirect URI is https://app.com/callback, requests with ?extra=param should be rejected.
5. Using Base Path Matching
https://app.com/ matches https://app.com/evil if only the base path is checked.
Practice Questions
- Why must redirect URIs be strictly validated?
- What is an open redirector attack in OAuth2?
- Why should localhost redirect URIs not be in production?
- How do different providers handle redirect URI validation?
- What happens if the redirect URI in the token exchange doesn't match?
Answers:
- Strict validation prevents attackers from intercepting authorization codes by redirecting to their own server.
- An attacker uses an open redirector on the legitimate app's domain to capture the authorization code from the URL.
- An attacker on the same machine can intercept the redirect. Mobile emulators also use localhost.
- Some require exact match, some allow path prefix, some use patterns. Exact match is most secure.
- The token endpoint should reject the exchange. The redirect_uri parameter in the token request must match the one used in the auth request.
Challenge: Set up a test OAuth2 server and intentionally configure an insecure redirect URI. Demonstrate how an attacker could intercept the authorization code using an open redirector.
FAQ
Mini Project
Build a redirect URI validator that checks strict exact match, rejects HTTP/localhost in production, prevents open redirector patterns, and provides clear error messages for invalid URIs.
What's Next
Now learn about OAuth2 Client Types — confidential vs public clients and their security implications.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro