---
title: Validate OAuth Redirect URIs Exactly
impact: CRITICAL
impactDescription: prevents authorization code theft via malicious redirection
tags: oauth, redirect, uri, validation, security, php
---

## Validate OAuth Redirect URIs Exactly

If you are building an OAuth 2.0 Identity Provider (IdP) or an internal auth service, you must validate the `redirect_uri` parameter against an exact match of pre-registered URIs. Loose validation (like substring or prefix matching) can be bypassed to leak authorization codes to an attacker-controlled site.

**Incorrect (loose or partial validation):**

```php
// VULNERABLE: Substring matching
if (strpos($redirectUri, "example.com") !== false) {
    // Allows attacker.com/?leak=example.com
}

// VULNERABLE: Prefix matching without trailing slash
if (strpos($redirectUri, "https://app.example.com") === 0) {
    // Allows https://app.example.com.attacker.com
}
```

**Correct (exact matching against whitelist):**

```php
$registeredUris = [
    'https://app.example.com/callback',
    'https://staging.example.com/callback'
];

$requestedUri = $_GET['redirect_uri'];

// 1. Exact string comparison (Recommended)
if (!in_array($requestedUri, $registeredUris, true)) {
    die("Error: Invalid redirect_uri provided.");
}

// 2. Using Laravel Passport/Socialite
// These libraries handle exact validation if configured correctly in the client table.
```

**Security Best Practices:**
- **No Wildcards**: Do not allow `*.example.com`. Modern OAuth standards discourage any form of pattern matching.
- **Pre-Registration**: Every client must register their exact callback URLs during the app registration phase.
- **HTTPS Only**: Only allow `https://` schemes for production redirect URIs.
- **Exact Path**: The entire path must match, not just the domain.

**Why it matters?**
If an attacker can redirect the OAuth flow to their own domain, they will receive the `?code=` parameter. They can then use this code to impersonate the user or link the user's account to their own, leading to a full account takeover.

**Tools:** Laravel Passport, OpenID Connect specifications, Manual Security Audit
