Skip to content

authorize_url() requests the "openid" scope twice, breaking strict OIDC providers (e.g. Authentik) #10

Description

@travi

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions