Troubleshooting
Common problems and solutions
"invalid_redirect_uri" error
Problem: The authorization request fails with a redirect URI error.
Causes:
- The redirect URI is not registered for the application
- A URI mismatch (http vs https, trailing slash, path differences)
- 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:
- Wrong client_id
- Wrong client_secret
- 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:
- The code is older than 5 minutes
- The code was already used (single-use)
- 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
"consent_required" with prompt=none
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:
- The refresh token expired (14 days)
- The session was revoked (password change, etc.)
- The refresh token was already used (rotation)
Solution:
- Redirect the user to re-authenticate
- Always store the latest refresh token after each refresh
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.
Magic Link doesn't work
Problem: Clicking the magic link shows an error.
Causes:
- The link expired (15 minutes)
- The link was already used
- 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:
- Check this documentation for relevant sections
- Read the error messages carefully - they often indicate the cause
- Test with cURL to isolate the problem
- Verify the configuration via the Discovery endpoint
/.well-known/openid-configuration - 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)