OAuth2: invalid_redirect_uri
Why Hydra rejects redirect_uri values
{
"error": "invalid_request",
"error_description": "The 'redirect_uri' parameter does not match any of the OAuth 2.0 Client's pre-registered redirect urls."
}Hydra requires redirect_uri to exactly match (string-for-string) one of the URIs registered for the client. No fuzzy matching.
Diagnose
hydra get client <client-id>Look at redirect_uris. Compare to what your app actually sends.
Common mismatches
Trailing slash
Registered: https://my-app.com/callback
Sent: https://my-app.com/callback/
Hydra rejects. Decide on a canonical form and use everywhere.
Path case
Registered: https://my-app.com/Callback
Sent: https://my-app.com/callback
Path is case-sensitive. Fix.
Scheme
Registered: http://localhost:3000/callback
Sent: https://localhost:3000/callback
Match the scheme.
Port
Registered: http://localhost:3000/callback
Sent: http://localhost:8080/callback
Match the port.
localhost vs 127.0.0.1
Different strings, even if they resolve to the same host. Match.
Wildcards
Hydra does NOT support wildcards in redirect URIs. List each explicitly:
hydra update client <id> \
--redirect-uri https://app.example.com/callback \
--redirect-uri https://staging.example.com/callback \
--redirect-uri https://dev.example.com/callbackIf you have many subdomains or dynamic preview environments, register each.
Mobile/desktop app loopback
For native apps using loopback (RFC 8252):
http://127.0.0.1:PORT/callbackHydra does have port wildcard support for 127.0.0.1. Register:
http://127.0.0.1/callbackHydra accepts any port at runtime. This is the only exception to exact matching.
Custom URI schemes
For mobile apps using app links:
com.example.myapp://callbackRegister with the custom scheme. Hydra accepts.
After changing
When you change redirect_uris for an existing client, restart anything that caches the client config. Hydra itself queries the DB on each request, no restart needed there.
Why exact match?
OAuth2 spec rationale: a flexible match (wildcards, "starts-with") is a security weakness, attacker registers a similar redirect and intercepts the code.
Best practice (RFC 9700, OAuth2 Security BCP): always exact match. Hydra defaults to safe.
Logs
podman logs ciam-hydra | grep "invalid_request"The error includes both the registered URIs and the sent value, so you can diff them character-by-character.