Skip to content

feat: add OIDC SSO authentication#1107

Merged
frankrousseau merged 2 commits into
cgwire:mainfrom
mxatmx:oidc-sso-upstream
Jun 14, 2026
Merged

feat: add OIDC SSO authentication#1107
frankrousseau merged 2 commits into
cgwire:mainfrom
mxatmx:oidc-sso-upstream

Conversation

@mxatmx

@mxatmx mxatmx commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

What

Adds OpenID Connect (OIDC) single sign-on, mirroring the existing SAML flow. A deployer configures a single OIDC provider via env vars; users get a "Login with " button that redirects through the provider and returns with the same JWT cookies the app already uses.

Backend changes

  • config: OIDC_ENABLED, OIDC_IDP_NAME, OIDC_DISCOVERY_URL, OIDC_CLIENT_ID, OIDC_CLIENT_SECRET, OIDC_SCOPES, overridable claim names, OIDC_SKIP_2FA
  • utils/oidc.py: Authlib client factory + claim-mapping/email-verified helpers
  • app init: register the OIDC client on app.extensions when enabled
  • routes: /auth/oidc/login (PKCE redirect) and /auth/oidc/callback (validate ID token -> match by email or auto-provision -> set JWT cookies)
  • honour ENFORCE_2FA unless OIDC_SKIP_2FA; reject email_verified == false
  • expose oidc_enabled / oidc_idp_name via /api/config
  • add Authlib dependency; tests; document env vars in specs/configuration.md

Design

  • Linking: match by email claim, auto-provision a user-role account on first login
  • 2FA: configurable via OIDC_SKIP_2FA (off = ENFORCE_2FA applies; on = trust IdP)
  • Claims: standard OIDC claims by default, overridable for Azure AD/Okta/etc.

Companion PR

Backend half - pairs with the Kitsu frontend PR cgwire/kitsu#2051 (OIDC login button). Merge together.

Add OpenID Connect single sign-on, mirroring the existing SAML flow.

- config: OIDC_ENABLED, OIDC_IDP_NAME, OIDC_DISCOVERY_URL, OIDC_CLIENT_ID,
  OIDC_CLIENT_SECRET, OIDC_SCOPES, configurable claim names and OIDC_SKIP_2FA
- utils/oidc.py: Authlib client factory + claim-mapping helpers
- app init: register the OIDC client on app.extensions when enabled
- auth routes: /auth/oidc/login (redirect with PKCE) and /auth/oidc/callback
  (validate ID token, match user by email or auto-provision, set JWT cookies)
- honour ENFORCE_2FA unless OIDC_SKIP_2FA is set
- reject logins whose email_verified claim is explicitly false
- expose oidc_enabled / oidc_idp_name via /api/config
- add Authlib dependency
- tests for claim mapping, provisioning/linking, email-verified and 2FA gating
- document the OIDC configuration variables

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Authlib 1.7.x depends on joserfc, which requires cryptography>=45. pysaml2
caps pyopenssl<24.3.0, and every pyopenssl in that range caps cryptography<44.
The resolver reconciles this by falling back to the ancient pyopenssl 22.0.0
(no upper cryptography bound) + cryptography 48, a pair that is broken at
runtime (ImportError on OpenSSL X509 flags) and made the whole test suite
INTERNALERROR at import time.

Authlib 1.6.x has no joserfc dependency (requires only 'cryptography'), so the
resolver settles on pyopenssl 24.2.1 + cryptography 43.x, which is compatible.
The OIDC code uses only stable flask_client APIs present in 1.6.x.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@frankrousseau frankrousseau merged commit fbe9bb6 into cgwire:main Jun 14, 2026
14 checks passed
@frankrousseau

frankrousseau commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Thank you for your contribution!

@mxatmx

mxatmx commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

@frankrousseau You got it! Just something I coded for my studio that's useful for others. Side note: are you guys planning on redoing the docs site soon? There's a bunch of stuff that I feel like just isn't covered at all on the docs site that would be super helpful (obviously as well as this new feature and config reference). I would have proposed changes myself but couldn't find the docs repo.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants