-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Description
Bug: startAuthorization silently redirects to wrong URL when AS metadata discovery fails
Package: packages/client/src/client/auth.ts
Problem
When discoverAuthorizationServerMetadata() returns undefined (all discovery URLs returned 4xx or were unreachable), startAuthorization() falls back to constructing the authorization URL as:
authorizationUrl = new URL('/authorize', authorizationServerUrl);new URL('/authorize', authorizationServerUrl) uses an absolute path, which replaces the entire pathname of authorizationServerUrl. When the authorization server has a subpath (e.g. https://example.com/admin), the result is https://example.com/authorize — the /admin prefix is silently lost.
The same pattern exists for the token endpoint fallback in executeTokenRequest():
const tokenUrl = metadata?.token_endpoint ? new URL(metadata.token_endpoint) : new URL('/token', authorizationServerUrl);And the registration endpoint fallback in registerClient():
registrationUrl = new URL('/register', authorizationServerUrl);Reproduction
- PRM (
/.well-known/oauth-protected-resource) returnsauthorization_servers: ["https://example.com/admin"] - AS metadata discovery at
https://example.com/.well-known/oauth-authorization-server/adminreturns 404 - SDK constructs
new URL('/authorize', 'https://example.com/admin')→https://example.com/authorize - User is redirected to a nonexistent authorization endpoint
- The actual correct endpoint (
https://example.com/admin/oauth/authorize) is never reached
Impact
- Silent failure: no error is thrown; the user sees a broken redirect with no diagnostic info
- Path loss: any authorization server with a non-root path is affected
- Masks real errors: the actual cause (AS metadata unreachable) is hidden behind a mysterious redirect failure
Proposed fix
When metadata is undefined and the authorization server URL has a non-root path, throw an error instead of guessing. The fallback to /authorize, /token, and /register should only apply when the AS is at the domain root (where it's a reasonable guess per RFC 6749 defaults).
Affected locations:
startAuthorization()—/authorizefallback (line ~1204)executeTokenRequest()—/tokenfallback (line ~1286)registerClient()—/registerfallback (line ~1533)