Open Redirect with Bearer Tokens
How Open Redirect Manifests in Bearer Tokens
Open Redirect vulnerabilities in Bearer Tokens contexts occur when an application uses user-controlled data to construct redirect URLs without proper validation. In Bearer Token implementations, this often manifests through authorization flows, callback parameters, or redirect_uri parameters that are passed back to the client with a token.
The most common Bearer Tokens-specific pattern involves OAuth 2.0 flows where the redirect_uri parameter is used to return authorization codes or access tokens. Attackers can manipulate these parameters to redirect users to malicious sites while still receiving valid tokens. For example:
GET /oauth/authorize?client_id=12345&redirect_uri=https://malicious-site.com/callback&response_type=codeIn this scenario, if the application doesn't validate that the redirect_uri matches a pre-registered domain, the authorization code or access token gets sent to the attacker's domain. The vulnerability is particularly dangerous in Bearer Tokens because the token itself is often included in the URL fragment or query parameters:
GET https://malicious-site.com/callback?code=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...Another Bearer Tokens-specific manifestation occurs in API endpoints that use redirect parameters for authentication flows. Consider a password reset endpoint that accepts a redirect parameter:
POST /api/v1/auth/reset HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"email": "victim@example.com",
"redirect": "https://malicious-site.com?token=abc123"
}When the user clicks the reset link, they're redirected to the attacker's site with a valid token, allowing session hijacking or phishing attacks. The token remains valid because it was issued by the legitimate service, making detection difficult.
API endpoints that dynamically construct URLs based on user input are also vulnerable. A common pattern in Bearer Tokens implementations is using user-supplied base URLs for API calls:
GET /api/v1/data?base_url=https://api.example.com&endpoint=/users/123 HTTP/1.1If the base_url parameter isn't validated, attackers can redirect API requests to their own servers, potentially exposing tokens through the Referer header or request logs.
Bearer Tokens-Specific Detection
Detecting Open Redirect vulnerabilities in Bearer Tokens implementations requires both automated scanning and manual testing. Automated tools like middleBrick can identify these issues by testing redirect parameters with controlled payloads and analyzing responses for suspicious behavior.
middleBrick's detection approach for Bearer Tokens includes:
- Parameter fuzzing with known redirect patterns (http://, https://, //, \/, \\)
- Testing for header-based redirects (Location, Content-Location, Refresh)
- Analyzing URL construction logic in API endpoints
- Checking for SSRF-like behavior in redirect chains
- Validating OAuth 2.0 redirect_uri handling
For manual testing of Bearer Tokens endpoints, use these techniques:
# Test OAuth redirect_uri parameter
curl -X GET "https://api.example.com/oauth/authorize?client_id=12345&redirect_uri=https://evil.com/callback&response_type=code"
# Test API redirect parameters
curl -X GET "https://api.example.com/v1/data?base_url=https://evil.com/&endpoint=/users/123" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
# Test for header-based redirects
curl -X GET "https://api.example.com/v1/auth/callback?token=abc123" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-vLook for these indicators of Open Redirect in Bearer Tokens contexts:
| Indicator | Description |
|---|---|
| HTTP 3xx status codes | Unexpected redirects to external domains |
| URL fragments | Tokens appearing in URL fragments (#access_token=) |
| Cross-domain redirects | Redirects to domains not in the allowlist |
| Header manipulation | Custom headers triggering redirects |
Security headers can help detect and mitigate these issues:
Content-Security-Policy: frame-ancestors 'none';
Referrer-Policy: strict-origin-when-cross-origin;
Strict-Transport-Security: max-age=31536000;These headers prevent clickjacking, control referrer information, and enforce HTTPS, respectively, making Open Redirect attacks more difficult to execute successfully.
Bearer Tokens-Specific Remediation
Remediating Open Redirect vulnerabilities in Bearer Tokens implementations requires a defense-in-depth approach. The most effective strategy combines strict validation, secure defaults, and proper token handling.
Implement strict redirect_uri validation for OAuth flows:
// Node.js/Express example
const validRedirects = new Set([
'https://example.com/callback',
'https://app.example.com/redirect'
]);\n
app.get('/oauth/authorize', (req, res) => {
const { client_id, redirect_uri, response_type } = req.query;
// Validate redirect_uri against pre-registered values
if (!validRedirects.has(redirect_uri)) {
return res.status(400).json({ error: 'Invalid redirect URI' });
}
// Generate authorization code
const code = generateAuthCode(client_id);
// Redirect to validated URI
res.redirect(`${redirect_uri}?code=${code}`);
});Use state parameters to prevent CSRF and open redirect attacks:
// Generate and validate state parameter
app.get('/oauth/authorize', (req, res) => {
const state = crypto.randomBytes(16).toString('hex');
res.cookie('oauth_state', state, { httpOnly: true, secure: true });
res.redirect(`https://provider.com/auth?client_id=12345&redirect_uri=${
encodeURIComponent('https://example.com/callback')
}&state=${state}`);
});
// Validate state on callback
app.get('/callback', (req, res) => {
const { state } = req.query;
const cookieState = req.cookies.oauth_state;
if (state !== cookieState) {
return res.status(400).json({ error: 'State mismatch' });
}
// Continue with token exchange
});Implement safe URL construction patterns:
// Safe URL builder for API endpoints
function buildApiUrl(baseUrl, endpoint) {
const allowedBases = new Set([
'https://api.example.com',
'https://api.staging.example.com'
]);
// Validate base URL
if (!allowedBases.has(baseUrl)) {
throw new Error('Invalid base URL');
}
// Validate endpoint path
if (!endpoint.startsWith('/')) {
throw new Error('Invalid endpoint path');
}
return `${baseUrl}${endpoint}`;
}
// Usage
const safeUrl = buildApiUrl(
'https://api.example.com',
'/users/123'
);
fetch(safeUrl, {
headers: {
'Authorization': `Bearer ${token}`
}
});Use relative redirects when possible:
// Instead of absolute URLs, use relative paths
app.post('/api/v1/auth/callback', (req, res) => {
const { token } = req.body;
// Store token in secure, HTTP-only cookie
res.cookie('auth_token', token, {
httpOnly: true,
secure: true,
sameSite: 'strict'
});
// Relative redirect to dashboard
res.redirect('/dashboard');
});Implement comprehensive logging and monitoring:
// Log suspicious redirect attempts
app.use((req, res, next) => {
const suspicious = [
req.query.redirect,
req.query.callback,
req.query.returnUrl,
req.query.next
].some(param => param && !isValidRedirect(param));
if (suspicious) {
console.warn('Suspicious redirect attempt', {
ip: req.ip,
url: req.originalUrl,
userAgent: req.get('User-Agent')
});
}
next();
});