Skip to main content

Troubleshooting

Common problems and solutions​

"invalid_redirect_uri" error​

Problem: The authorization request fails with a redirect URI error.

Causes:

  1. The redirect URI is not registered for the application
  2. A URI mismatch (http vs https, trailing slash, path differences)
  3. URL-encoding issues

Solution:

# Verify an exact match with the registered URI
Registered: https://myapp.com/callback
Request: https://myapp.com/callback ✓
Request: https://myapp.com/callback/ ✗ (trailing slash)
Request: http://myapp.com/callback ✗ (http vs https)

"invalid_client" error​

Problem: The token exchange fails with a client error.

Causes:

  1. Wrong client_id
  2. Wrong client_secret
  3. The secret is not included (for confidential clients)

Solution:

  • Verify that the client_id and client_secret are correct
  • Make sure confidential clients include the client_secret in token requests
  • Check for whitespace in the credentials

"invalid_grant" - code expired​

Problem: The authorization code exchange fails.

Causes:

  1. The code is older than 5 minutes
  2. The code was already used (single-use)
  3. Wrong redirect_uri in the token request

Solution:

  • Make sure the code exchange happens immediately after the callback
  • Never reuse authorization codes
  • Use the exact same redirect_uri in both the authorize and token requests

Problem: Silent authentication fails.

Cause: The user has not previously granted consent, but prompt=none prevents the consent screen from being shown.

Solution:

// Handle the consent_required error
if (error === 'consent_required') {
// Redirect without prompt=none to show the consent screen
window.location.href = authUrl.replace('prompt=none', '');
}

Token refresh failure​

Problem: The refresh token request returns an error.

Causes:

  1. The refresh token expired (14 days)
  2. The session was revoked (password change, etc.)
  3. The refresh token was already used (rotation)

Solution:

  • Redirect the user to re-authenticate
  • Always store the latest refresh token after each refresh
Two-factor authentication (2FA)

If the user has 2FA enabled, the entire verification takes place on the Klubero SSO sign-in page – your application does not implement or handle 2FA. From an integration standpoint, the result is either a successful sign-in (you receive an authorization code) or a standard OAuth error. Any issues with the code (e.g. a clock out of sync in the authenticator) are handled by the user directly on the SSO screen, where they can also use a recovery code.

Problem: Clicking the magic link shows an error.

Causes:

  1. The link expired (15 minutes)
  2. The link was already used
  3. The link was copied incorrectly (truncated)

Solution:

  • Request a new magic link
  • Click the link within 15 minutes
  • Copy the complete link, including all parameters

Debugging tips​

1. Check the Discovery endpoint​

Verify that the SSO server is reachable:

curl https://your-sso-domain.com/.well-known/openid-configuration

2. Decode JWT tokens​

Inspect a token's contents (do NOT share tokens publicly):

# Extract the payload (the middle part between the dots)
echo "eyJhbG...payload...signature" | cut -d. -f2 | base64 -d

3. Check token expiration​

const payload = JSON.parse(atob(token.split('.')[1]));
console.log('Expires:', new Date(payload.exp * 1000));
console.log('Issued:', new Date(payload.iat * 1000));

4. Test with cURL​

Test requests independently of your application:

curl -v -X POST https://your-sso-domain.com/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_SECRET"

Getting help​

If you're still having problems:

  1. Check this documentation for relevant sections
  2. Read the error messages carefully - they often indicate the cause
  3. Test with cURL to isolate the problem
  4. Verify the configuration via the Discovery endpoint /.well-known/openid-configuration
  5. Contact support at support@klubero.cz with:
    • The error message (exact text)
    • Request details (endpoint, parameters - never send secrets)
    • Steps to reproduce
    • The Client ID (not the secret)