Keycloak Redirect URI Mismatch: Complete Troubleshooting Guide

Guilliano Molaire Guilliano Molaire 10 min read

Last updated: March 2026

If you have worked with Keycloak for any length of time, you have almost certainly encountered this error:

Invalid parameter: redirect_uri

Or its more descriptive cousin in the Keycloak server logs:

WARN [org.keycloak.protocol.oidc.utils.RedirectUtils] Invalid redirect uri: redirect_uri does not match any valid redirect URI

The redirect URI mismatch is the single most common error developers hit when integrating applications with Keycloak. The good news is that it is always a configuration issue, and once you understand the matching rules, it becomes straightforward to debug.

This guide walks through every cause of redirect URI mismatches in Keycloak, how to diagnose each one, and how to fix them across common frameworks.

How Keycloak Validates Redirect URIs

Before troubleshooting, it helps to understand exactly how Keycloak matches redirect URIs.

When a client initiates an OIDC authorization request, it includes a redirect_uri parameter. Keycloak compares this value against the list of Valid Redirect URIs configured for that client in the admin console. The matching rules are:

  1. Exact match is the default behavior. https://app.example.com/callback only matches https://app.example.com/callback.
  2. Trailing wildcards are supported. https://app.example.com/* matches any path under that domain.
  3. Matching is case-sensitive for the path component.
  4. Query parameters in the configured URI are ignored during matching, but the path must match.
  5. Fragments (#) are not allowed in redirect URIs per the OAuth 2.0 spec.

With these rules in mind, let us walk through each common cause.

Cause 1: Trailing Slash Mismatch

This is the most frequent culprit and the easiest to miss.

The problem:

Your application sends redirect_uri=https://app.example.com/callback but Keycloak has https://app.example.com/callback/ configured (or vice versa).

How to verify:

Check the actual authorization request your application is sending. Open your browser’s developer tools, go to the Network tab, and look for the request to Keycloak’s /auth endpoint. Examine the redirect_uri query parameter.

# Extract the redirect_uri from a Keycloak authorization URL
echo "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/auth?client_id=myapp&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback&response_type=code&scope=openid" | python3 -c "import sys, urllib.parse; url=sys.stdin.read().strip(); params=urllib.parse.parse_qs(urllib.parse.urlparse(url).query); print(params.get('redirect_uri', [''])[0])"

The fix:

Make sure the URI in Keycloak’s admin console matches exactly what your application sends, including the presence or absence of a trailing slash.

In Keycloak Admin Console:

  1. Navigate to Clients > your client > Settings
  2. Check the Valid Redirect URIs field
  3. Ensure the value matches your application’s redirect URI character for character

Cause 2: HTTP vs HTTPS Mismatch

The problem:

Your application is behind a reverse proxy that terminates TLS. The app itself sees http:// but the browser sees https://. Your OAuth library might generate the redirect URI based on the incoming request scheme, resulting in http://app.example.com/callback being sent to Keycloak while https://app.example.com/callback is configured.

How to verify:

# Test what redirect_uri your app generates
curl -s -o /dev/null -w "%{redirect_url}" "https://app.example.com/login" 2>/dev/null

Look at the redirect_uri parameter in the redirect URL. If it starts with http:// when your Keycloak client has https:// configured, you have found the problem.

The fix:

Configure your reverse proxy to forward the correct headers, and configure your application to trust them:

# Nginx - forward the original scheme
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;

For Spring Boot applications:

# application.properties
server.forward-headers-strategy=framework

For Next.js behind a reverse proxy, make sure your NEXTAUTH_URL environment variable uses https://:

NEXTAUTH_URL=https://app.example.com

This is a common pitfall when running Keycloak behind a reverse proxy. If you are deploying Keycloak with Skycloak’s managed hosting, TLS termination is handled for you, but your application still needs to generate the correct scheme.

Cause 3: Port Number Mismatch

The problem:

During local development, your app runs on http://localhost:3000/callback, but you configured http://localhost:8080/callback in Keycloak. Or you forgot to include the port entirely and configured http://localhost/callback.

How to verify:

Check the port in both your application’s configuration and Keycloak’s client settings. Remember that http://localhost:3000 and http://localhost are different URIs.

The fix:

Include the exact port number in Keycloak’s Valid Redirect URIs. For local development, it is common to add multiple URIs:

http://localhost:3000/callback
http://localhost:3000/api/auth/callback/keycloak
http://localhost:5173/callback

For development convenience, you can use a wildcard pattern (but never in production):

http://localhost:*/*

Cause 4: URL-Encoded Characters

The problem:

Some OAuth libraries URL-encode the redirect URI before sending it, while Keycloak compares against the decoded value. Alternatively, you might have pasted a URL-encoded value into Keycloak’s admin console.

How to verify:

Decode the redirect_uri parameter from your authorization request and compare it with what is in Keycloak:

# Decode a URL-encoded redirect_uri
python3 -c "import urllib.parse; print(urllib.parse.unquote('https%3A%2F%2Fapp.example.com%2Fcallback'))"
# Output: https://app.example.com/callback

The fix:

Always enter decoded (plain text) URLs in Keycloak’s Valid Redirect URIs field. Keycloak handles the decoding of the incoming redirect_uri parameter automatically.

Cause 5: Wildcard Patterns Done Wrong

The problem:

Keycloak supports wildcards in redirect URIs, but the rules are specific:

  • * is only allowed at the end of a URI path
  • https://app.example.com/* is valid (matches any path)
  • https://*.example.com/callback is not valid (subdomain wildcards are not supported in the path-based matching)
  • * alone matches everything (extremely dangerous and should never be used in production)

How to verify:

Check if your wildcard pattern follows Keycloak’s rules. A common mistake is trying to use subdomain wildcards.

The fix:

If you need to support multiple subdomains, list each one explicitly:

https://app1.example.com/callback
https://app2.example.com/callback
https://staging.example.com/callback

Or use a trailing wildcard if all subdomains share the same origin:

https://app.example.com/*

For security best practices, avoid wildcards in production entirely. Each redirect URI should be explicitly listed. This is a key part of securing your OIDC client configuration.

Cause 6: Wrong Realm or Client

The problem:

You are testing against the wrong realm or have configured the redirect URI on the wrong client. This is common in development when you have multiple realms (dev, staging, production) or when multiple applications share a Keycloak instance.

How to verify:

Check the authorization URL your application is using:

https://keycloak.example.com/realms/{realm-name}/protocol/openid-connect/auth?client_id={client-id}&redirect_uri=...

Make sure {realm-name} and {client-id} match where you configured the redirect URI.

The fix:

Navigate to the correct realm and client in the admin console and verify the redirect URI configuration there. If you manage multiple environments, consider using Terraform to configure Keycloak to keep configurations consistent.

Cause 7: Post-Logout Redirect URI

The problem:

Keycloak has separate fields for login redirect URIs and post-logout redirect URIs. If you get a redirect URI error during logout, the login redirect URI configuration is not the issue.

How to verify:

Check if the error occurs during logout (the URL will contain /logout rather than /auth). Look for the post_logout_redirect_uri parameter.

The fix:

In Keycloak Admin Console:

  1. Navigate to Clients > your client > Settings
  2. Scroll to Valid Post Logout Redirect URIs
  3. Add the URI your application sends during logout

If you want post-logout redirects to match the same patterns as login redirects, you can enter + in the post-logout field, which tells Keycloak to use the Valid Redirect URIs list.

Framework-Specific Gotchas

Next.js with NextAuth.js / Auth.js

NextAuth.js uses /api/auth/callback/{provider} as the default callback path. Your Keycloak client needs:

https://your-app.com/api/auth/callback/keycloak

Common mistakes:

  • Forgetting the /api/auth/ prefix
  • Using the wrong provider name (must match the provider ID in your NextAuth config)
  • Not setting NEXTAUTH_URL correctly, causing the wrong base URL
// next-auth configuration
import KeycloakProvider from "next-auth/providers/keycloak";

export const authOptions = {
  providers: [
    KeycloakProvider({
      clientId: process.env.KEYCLOAK_ID,
      clientSecret: process.env.KEYCLOAK_SECRET,
      issuer: process.env.KEYCLOAK_ISSUER,
    }),
  ],
};
# .env.local
NEXTAUTH_URL=https://your-app.com
KEYCLOAK_ID=your-client-id
KEYCLOAK_SECRET=your-client-secret
KEYCLOAK_ISSUER=https://keycloak.example.com/realms/your-realm

For a full integration guide, see our post on configuring CORS with Keycloak OIDC clients.

React with PKCE

If you are using a React SPA with PKCE (which you should be for public clients), the redirect URI is typically your app’s base URL or a dedicated callback route:

// Example using oidc-client-ts
const config = {
  authority: "https://keycloak.example.com/realms/myrealm",
  client_id: "my-spa",
  redirect_uri: "https://app.example.com/callback",
  post_logout_redirect_uri: "https://app.example.com/",
  response_type: "code",
  scope: "openid profile email",
};

In Keycloak, set the client access type to public (no client secret) and add the exact redirect_uri value. See our guide on securing React API access with Keycloak OIDC PKCE for a complete walkthrough.

Spring Boot

Spring Security’s OAuth 2.0 client uses /login/oauth2/code/{registrationId} as the default callback path:

# application.yml
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: my-spring-app
            client-secret: ${KEYCLOAK_SECRET}
            scope: openid,profile,email
        provider:
          keycloak:
            issuer-uri: https://keycloak.example.com/realms/myrealm

The redirect URI will be https://your-app.com/login/oauth2/code/keycloak. Add this to your Keycloak client configuration.

For applications using the legacy Keycloak Spring Boot adapter, see our migration guide.

Angular

Angular applications using angular-auth-oidc-client or keycloak-angular have their own redirect URI patterns:

// Using angular-auth-oidc-client
export const authConfig: OpenIdConfiguration = {
  authority: 'https://keycloak.example.com/realms/myrealm',
  redirectUrl: window.location.origin + '/callback',
  postLogoutRedirectUri: window.location.origin,
  clientId: 'my-angular-app',
  scope: 'openid profile email',
  responseType: 'code',
};

See our Angular and Keycloak integration guide for the full setup.

Debugging with Keycloak Server Logs

When the error page does not give you enough information, Keycloak’s server logs tell you exactly what went wrong.

Enable debug logging for the redirect URI validator:

# For standalone Keycloak (Quarkus-based, v17+)
bin/kc.sh start-dev --log-level=org.keycloak.protocol.oidc.utils.RedirectUtils:DEBUG

With debug logging enabled, you will see messages like:

DEBUG [org.keycloak.protocol.oidc.utils.RedirectUtils] Checking redirect URI: https://app.example.com/callback against valid redirects: [https://app.example.com/callback/]

This immediately tells you the exact mismatch.

If you are using Skycloak managed hosting, you can access logs through the Insights dashboard without needing to configure log levels manually. You can also forward events to a SIEM for centralized monitoring.

Debugging the Token Exchange

If the redirect URI validates during the authorization request but fails during the token exchange, the issue is that your application is sending a different redirect_uri in the token request than it sent in the authorization request. The OAuth 2.0 spec requires these to be identical.

You can test the token exchange manually with curl:

# Exchange authorization code for tokens
curl -X POST "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token" 
  -H "Content-Type: application/x-www-form-urlencoded" 
  -d "grant_type=authorization_code" 
  -d "code=YOUR_AUTH_CODE" 
  -d "client_id=your-client-id" 
  -d "client_secret=your-client-secret" 
  -d "redirect_uri=https://app.example.com/callback"

The redirect_uri in this request must exactly match the one used in the authorization request. If they differ, you will get an invalid_grant error rather than a redirect URI error. For more on that, see our invalid_grant troubleshooting guide.

Once you have the token, you can inspect it with our JWT Token Analyzer to verify the claims are correct.

Security Best Practices for Redirect URIs

While troubleshooting, it is tempting to use overly permissive redirect URIs. Here are the security guidelines:

  1. *Never use `` as a redirect URI in production.** This allows any URI to receive authorization codes, enabling authorization code interception attacks.

  2. *Avoid broad wildcards like `https://example.com/`.** An open redirect vulnerability anywhere on your domain would then allow token theft.

  3. List each redirect URI explicitly. This is the most secure approach.

  4. Use HTTPS in production. Always. Keycloak allows http:// for localhost only by default.

  5. Keep development and production URIs separate. Do not add http://localhost:3000/callback to your production client. Use separate clients or realms for each environment.

  6. Review redirect URIs regularly. Old or unused URIs should be removed. Keycloak’s audit logs can help you track client configuration changes.

Quick Reference: Checklist

When you hit a redirect URI mismatch, work through this checklist:

  • [ ] Is the scheme correct? (http vs https)
  • [ ] Is the hostname correct? (including www vs no www)
  • [ ] Is the port correct? (remember: no port = default 80/443)
  • [ ] Is the path correct? (including trailing slash)
  • [ ] Are you using the right realm?
  • [ ] Are you using the right client ID?
  • [ ] Is this a login or logout redirect? (check the right field)
  • [ ] Does the token exchange use the same redirect URI as the authorization request?
  • [ ] Are there any URL-encoded characters in the Keycloak configuration?
  • [ ] Is your reverse proxy forwarding the correct X-Forwarded-Proto header?

Wrapping Up

Redirect URI mismatches are frustrating because the error message does not tell you what the mismatch actually is. But with debug logging enabled and a systematic approach to checking each possible cause, you can resolve them quickly.

The most common fixes are trailing slash mismatches, HTTP vs HTTPS scheme issues, and wrong port numbers. Start with those three, check the server logs, and you will likely have your answer within minutes.

If you are setting up a new Keycloak integration and want to skip the infrastructure headaches, Skycloak’s managed hosting gives you a production-ready Keycloak instance with logging and monitoring built in. Check out our pricing plans to get started, or use our Keycloak Docker Compose Generator if you prefer to start with a local development environment.

Guilliano Molaire
Written by Guilliano Molaire Founder

Guilliano is the founder of Skycloak and a cloud infrastructure specialist with deep expertise in product development and scaling SaaS products. He discovered Keycloak while consulting on enterprise IAM and built Skycloak to make managed Keycloak accessible to teams of every size.

Ready to simplify your authentication?

Deploy production-ready Keycloak in minutes. Unlimited users, flat pricing, no SSO tax.

© 2026 Skycloak. All Rights Reserved. Design by Yasser Soliman