elsa-workflows/elsa-core · error · OpenIdConnectAuthenticationException
The identity provider rejected the authentication request.
Error message
The identity provider rejected the authentication request.
What it means
During the OpenID Connect authorization-code callback, AuthenticateCallbackAsync first checks the query parameters returned by the identity provider. If the provider returned an 'error' parameter (per RFC 6749 section 4.1.2.1), the adapter throws this OpenIdConnectAuthenticationException, meaning the provider itself rejected the end user's authentication or authorization request.
Solutions
- Log the actual 'error' and 'error_description' query parameters from the callback URL to see why the provider rejected the request.
- Check the provider's app registration: client_id, redirect URI, and requested scopes must all be registered.
- Surface a friendly message to the end user explaining the login was cancelled or denied, and retry the sign-in flow via the adapter's initiation endpoint.
Example fix
// inspect the callback to diagnose
var error = Request.Query["error"].ToString();
var description = Request.Query["error_description"].ToString();
logger.LogWarning("OIDC callback rejected: {Error} - {Description}", error, description);
return Challenge(); // restart the login flow Defensive patterns
Strategy: try-catch
Validate before calling
if (Request.Query.ContainsKey("error")) { var desc = Request.Query["error_description"].ToString(); return Results.Problem($"Login rejected: {Request.Query[\"error\"]} {desc}"); } Try / catch
try { var result = await adapter.AuthenticateCallbackAsync(context); } catch (OpenIdConnectAuthenticationException ex) { logger.LogWarning(ex, "OIDC callback error"); return Challenge(); } Prevention
- Log error and error_description query parameters from every callback.
- Validate redirect URIs and scopes in the provider app registration before deploying.
- Provide users a friendly 'sign-in was cancelled' path and a retry button.
When it happens
Trigger: Calling AuthenticateCallbackAsync with context.Parameters containing an 'error' key (e.g. error=access_denied, error=invalid_request) from the redirect URI callback.
Common situations: User cancels the login page; the provider rejects the request due to a misconfigured redirect URI, unregistered client, or missing user consent; the user's account is locked or lacks access to the application.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- The identity provider callback did not contain an…
- The provider client secret is unavailable.
- The identity provider callback could not be correlated.
- The identity provider callback issuer did not match the…
- The identity provider nonce did not match the initiated…
AI-assisted analysis of elsa-workflows/elsa-core@fe9217bdfa (2026-09-13).
Data as JSON: /api/errors/c4bf06fd04a6ac34.
Report an issue: GitHub.
Appendix: source
Thrown at src/modules/Elsa.ExternalAuthentication.OpenIdConnect/Services/OpenIdConnectExternalAuthenticationAdapter.cs:82
var query = new Dictionary<string, string>
{
["response_type"] = "code",
["client_id"] = settings.ClientId,
["redirect_uri"] = GetCallbackUri(context.Connection, context.Transaction.Purpose).AbsoluteUri,
["scope"] = string.Join(' ', settings.Scopes),
["state"] = context.CorrelationState,
["nonce"] = nonce,
["code_challenge"] = CreateCodeChallenge(verifier),
["code_challenge_method"] = "S256"
};
return new(WithQuery(metadata.AuthorizationEndpoint, query), state);
}
public async ValueTask<ExternalAuthenticationResult> AuthenticateCallbackAsync(ExternalCallbackContext context, CancellationToken cancellationToken = default)
{
if (TryGetParameter(context.Parameters, "error", out _))
throw new OpenIdConnectAuthenticationException("The identity provider rejected the authentication request.");
if (!TryGetParameter(context.Parameters, "state", out var state) || !FixedTimeEquals(state, context.CorrelationState))
throw new OpenIdConnectAuthenticationException("The identity provider callback could not be correlated.");
var settings = await GetSettingsAsync(context.Connection.Connection.AdapterSettings, cancellationToken);
var metadata = await ResolveMetadataAsync(settings, cancellationToken);
var adapterState = ReadAdapterState(context.Transaction.ProtectedPayload);
if (adapterState is not null && !string.Equals(adapterState.Issuer, metadata.Issuer, StringComparison.Ordinal))
throw new OpenIdConnectAuthenticationException("The identity provider callback issuer did not match the initiated request.");
var idToken = await ExchangeCodeAsync(settings, metadata, context, adapterState?.CodeVerifier, cancellationToken);
var principal = await ValidateIdTokenAsync(idToken, settings, metadata, cancellationToken);
var nonce = principal.FindFirst("nonce")?.Value;
var expectedNonce = context.Transaction.ProviderNonce ?? adapterState?.Nonce;
if (string.IsNullOrWhiteSpace(expectedNonce) || !FixedTimeEquals(nonce, expectedNonce))
throw new OpenIdConnectAuthenticationException("The identity provider nonce did not match the initiated request.");
var issuer = principal.FindFirst("iss")?.Value ?? metadata.Issuer;View on GitHub (pinned to fe9217bdfa)