Summary
OidcProvider::authorize_url() in auth/server/src/provider/oidc.rs produces an authorization request with the openid scope listed twice (scope=openid+openid+profile+email). Strict OIDC providers reject this outright as a malformed request, which blocks OIDC login entirely.
How this was found
Found while configuring OIDC login for Komodo (Core v2.3.3, mogh_auth_server pinned at 1.8.0 per that release's Cargo.lock) against a self-hosted Authentik instance. Clicking "Login with OIDC" never reaches Authentik's login page — Authentik's own logs show:
event: "The request is otherwise malformed"
logger: authentik.providers.oauth2.views.authorize
with the incoming scope parameter being openid+openid+profile+email. Confirmed this isn't an Authentik-side misconfiguration first: redirect_uri and client_id both matched the configured provider exactly, and Authentik's own .well-known/openid-configuration correctly advertises scopes_supported: ["openid", "email", "profile"] with no duplication.
Root cause
Traced directly in source, at the exact pinned version (1.8.0, matches current main as of this issue):
// auth/server/src/provider/oidc.rs, authorize_url()
.add_scope(Scope::new("openid".to_string()))
.add_scope(Scope::new("profile".to_string()))
.add_scope(Scope::new("email".to_string()))
.add_scopes(
self.additional_scopes.iter().cloned().map(Scope::new),
)
The underlying openidconnect crate's Client::authorize_url() already includes openid automatically by default — it's only omitted if .insecure_disable_openid_scope() is called first, which doesn't happen anywhere in this file. The explicit .add_scope(Scope::new("openid".to_string())) call above is therefore redundant and produces the duplicate.
additional_scopes() (used for the last .add_scopes(...) call) does filter out "openid"/"profile"/"email" from user-configured additional scopes, so it can't be the source of a second openid - it's specifically the explicit call shown above stacking on top of the library's own default.
Suggested fix
Either:
- Drop the explicit
.add_scope(Scope::new("openid".to_string())) call (the underlying client already adds it), or
- Call
.insecure_disable_openid_scope() before building the authorize URL if explicit control over that scope is wanted
Either should remove the duplicate without changing the actual requested scope set.
Disclosure
I used Claude (Anthropic's Claude Code) to help trace this from the observed symptom down to the exact source line and confirm the mechanism against the pinned dependency version - flagging that for transparency since the investigation (not just the writeup) leaned on it.
Summary
OidcProvider::authorize_url()inauth/server/src/provider/oidc.rsproduces an authorization request with theopenidscope listed twice (scope=openid+openid+profile+email). Strict OIDC providers reject this outright as a malformed request, which blocks OIDC login entirely.How this was found
Found while configuring OIDC login for Komodo (Core
v2.3.3,mogh_auth_serverpinned at1.8.0per that release'sCargo.lock) against a self-hosted Authentik instance. Clicking "Login with OIDC" never reaches Authentik's login page — Authentik's own logs show:with the incoming
scopeparameter beingopenid+openid+profile+email. Confirmed this isn't an Authentik-side misconfiguration first:redirect_uriandclient_idboth matched the configured provider exactly, and Authentik's own.well-known/openid-configurationcorrectly advertisesscopes_supported: ["openid", "email", "profile"]with no duplication.Root cause
Traced directly in source, at the exact pinned version (
1.8.0, matches currentmainas of this issue):The underlying
openidconnectcrate'sClient::authorize_url()already includesopenidautomatically by default — it's only omitted if.insecure_disable_openid_scope()is called first, which doesn't happen anywhere in this file. The explicit.add_scope(Scope::new("openid".to_string()))call above is therefore redundant and produces the duplicate.additional_scopes()(used for the last.add_scopes(...)call) does filter out"openid"/"profile"/"email"from user-configured additional scopes, so it can't be the source of a secondopenid- it's specifically the explicit call shown above stacking on top of the library's own default.Suggested fix
Either:
.add_scope(Scope::new("openid".to_string()))call (the underlying client already adds it), or.insecure_disable_openid_scope()before building the authorize URL if explicit control over that scope is wantedEither should remove the duplicate without changing the actual requested scope set.
Disclosure
I used Claude (Anthropic's Claude Code) to help trace this from the observed symptom down to the exact source line and confirm the mechanism against the pinned dependency version - flagging that for transparency since the investigation (not just the writeup) leaned on it.