Skip to main content

Authentication Troubleshooting

Use this guide to diagnose common OIDC, PKCE, CORS, token, and external API failures when integrating with Muhajir Studio.

Start with the Failing Stage

StageEndpoint or pageMost common issue
Authorization starthttps://api.muhajirstudio.com/api/auth/oauth2/authorizeRedirect URI mismatch, missing PKCE, wrong client_id.
Login / verification / consenthttps://login.muhajirstudio.com/User not signed in, email not verified, consent metadata missing.
Token exchangehttps://api.muhajirstudio.com/api/auth/oauth2/tokenMissing or wrong code_verifier, reused code, wrong redirect URI.
Browser API callhttps://api.muhajirstudio.com/api/external/meOrigin not registered or missing bearer token.
External API auth/api/external/*Expired token, missing openid, insufficient scopes.

Redirect URI Mismatch

Symptom:

{
"error": "INVALID_REDIRECT_URI",
"message": "redirect_uri is not registered for this client"
}

Cause:

Muhajir Studio validates the authorize redirect_uri against the application's registered origin/path matrix. The value must be an exact derived URI.

Fix:

  1. Confirm the client_id belongs to the application you are testing.
  2. In web-admin, confirm the allowed web origin, for example https://app.example.com.
  3. Confirm the redirect path, for example /auth/callback.
  4. Send the exact full URI: https://app.example.com/auth/callback.
  5. Do not add query strings, fragments, wildcards, or a trailing slash unless that exact path is registered.

Missing or Invalid PKCE

Symptoms can include OAuth errors such as:

{
"error": "invalid_request",
"error_description": "..."
}

or token exchange failure with invalid_grant.

Fix:

  • Authorization requests must include code_challenge.
  • code_challenge_method must be S256.
  • The token request must include the original code_verifier.
  • Generate a fresh verifier/challenge for each login attempt.
  • Do not reuse authorization codes.

Plain PKCE challenges are disabled.

Invalid Client or Metadata Loading Errors

Public application metadata is loaded from:

GET /api/public/applications/{clientId}

Common responses:

StatusErrorMeaningFix
400INVALID_CLIENT_IDThe client ID path parameter is invalid.Check for copy/paste mistakes.
404NOT_FOUNDNo dynamic or static client exists for the ID.Confirm the app exists and was not deleted.
500INTERNAL_ERRORLookup failed unexpectedly.Retry and contact support if persistent.

The consent page disables approval when application metadata cannot be loaded.

Browser CORS Mismatch

Symptoms:

  • Browser console shows a CORS failure.
  • The request works from a server tool but not from the browser.
  • No Access-Control-Allow-Origin header appears for your SPA origin.

Cause:

Third-party browser CORS is route-scoped and origin-scoped. It applies to:

  • POST /api/auth/oauth2/token
  • OPTIONS /api/auth/oauth2/token
  • /api/external/*

It allows only origins registered in allowedWebOrigins, does not allow credentials, and allows Authorization plus Content-Type headers.

Fix:

  1. Register the exact browser origin, such as https://spa.example.com.
  2. Do not include a path in the allowed web origin.
  3. Wait briefly after admin changes; registered CORS origins are cached for 60 seconds.
  4. Do not send credentials: 'include' from a third-party SPA.
  5. Use bearer tokens for /api/external/*.

Token Exchange Returns invalid_grant

Common causes:

  • Authorization code was already used.
  • Authorization code expired.
  • code_verifier does not match the original code_challenge.
  • redirect_uri in the token request differs from the authorize request.
  • Refresh token is missing, expired, revoked, or no longer valid.

Fix:

  • Restart the login flow with a new PKCE pair.
  • Ensure your callback stores and loads the verifier for the same browser/session attempt.
  • Send the same redirect_uri string in authorize and token requests.
  • On refresh failure, clear stored tokens and sign in again.

External API Returns 401 UNAUTHORIZED

Response:

{
"error": "UNAUTHORIZED"
}

Meaning:

The external API did not receive a usable OIDC bearer access token. Cookie-only sessions are not accepted by /api/external/*.

Fix:

  • Send Authorization: Bearer ACCESS_TOKEN.
  • Confirm the token is an OIDC access token, not an ID token.
  • Confirm the token is not expired.
  • Clear local tokens and restart login if the token is unknown or expired.

External API Returns 403 FORBIDDEN

Response:

{
"error": "FORBIDDEN",
"missingScopes": ["openid"]
}

Meaning:

The token is valid but does not include a required scope. GET /api/external/me requires openid; fields such as email, profile, and permissions require their matching scopes.

Fix:

  1. Check the application's selected scopes in web-admin.
  2. Ask an admin to add required scopes if needed.
  3. Start a new login after scope changes so the user receives a token with the updated scope set.

User Gets Stuck Around Email Verification

Muhajir Studio requires signed-in users to verify their email before OIDC authorization completes. The login UI preserves OIDC parameters through login, signup, /verify-email, and the email-verified screen.

Fix:

  • Keep the original authorize query parameters intact when deep-linking users back to login or verification pages.
  • Ensure the user completes email verification before expecting the authorization callback.
  • If the flow restarts, generate a new PKCE verifier and state.

Quick Diagnostic Checklist

  • Is the client_id correct and active?
  • Does redirect_uri exactly match the registered derived URI?
  • Is code_challenge_method=S256 present?
  • Is the token request form-encoded?
  • Is client_secret omitted for Public PKCE clients?
  • Is the browser Origin registered for SPA calls?
  • Are you sending an access token, not an ID token, to /api/external/*?
  • Does the token include openid for /api/external/me?