Skip to content

feat(auth): add OIDC/Gitea userinfo support for OAuth2 login - #727

Open
achille wants to merge 1 commit into
kubero-dev:release/v3.1.2from
achille:gitea-oauth2-support
Open

feat(auth): add OIDC/Gitea userinfo support for OAuth2 login#727
achille wants to merge 1 commit into
kubero-dev:release/v3.1.2from
achille:gitea-oauth2-support

Conversation

@achille

@achille achille commented Feb 4, 2026

Copy link
Copy Markdown

The passport-oauth2 strategy doesn't fetch user profile data by default, which breaks authentication with OIDC providers like Gitea that don't embed user info in the access token.

this pr is written via ai (claude+gemini) and manually verified

Changes:

  • Override userProfile on strategy instance when OAUTH2_CLIENT_USERINFO_URL is set
  • Map OIDC standard claims (sub, preferred_username, email, picture) to passport profile
  • Support Gitea API fields (login, full_name, avatar_url) as fallbacks
  • Use stable identifiers for username (never display name) to prevent collisions
  • Add UserProfile interface for type safety
  • Throw clear error on missing required config instead of silent early return
  • Replace disabled test file with comprehensive working tests

See: https://docs.gitea.com/development/oauth2-provider

Description

Support for login via gitea/forgejo OIDC.

Type of change

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

  • ai assisted unit tests (multiple rounds) + manual review

  • depoyed and tested locally on my homlab

  • I've built the image and tested it on a kubernetes cluster

Test Configuration:

  • Operator Version: v0.2.2 (ghcr.io/kubero-dev/kubero-operator/kuberoapp:v0.2.2)
  • Kubernetes Version: v1.34.2+k3s1
  • Kubero CLI Version: N/A (not installed)

Checklist:

  • I removed unnecessary debug logs (verified - no console.log or DEBUG found)
  • My code follows the style guidelines of this project (uses existing patterns)
  • I have performed a self-review of my code
  • I documented my code, particularly in hard-to-understand areas (comments explain OIDC/Gitea fallback logic)
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works (306 lines of tests added)
  • New and existing unit tests pass locally with my changes

The passport-oauth2 strategy doesn't fetch user profile data by default,
which breaks authentication with OIDC providers like Gitea that don't
embed user info in the access token.

Changes:
- Override userProfile on strategy instance when OAUTH2_CLIENT_USERINFO_URL is set
- Map OIDC standard claims (sub, preferred_username, email, picture) to passport profile
- Support Gitea API fields (login, full_name, avatar_url) as fallbacks
- Use stable identifiers for username (never display name) to prevent collisions
- Add UserProfile interface for type safety
- Throw clear error on missing required config instead of silent early return
- Replace disabled test file with comprehensive working tests

Username mapping priority: preferred_username > login > email > sub/id

See: https://docs.gitea.com/development/oauth2-provider
@mms-gianni mms-gianni added this to the v3.1.2 milestone Apr 15, 2026
@mms-gianni
mms-gianni changed the base branch from main to release/v3.1.2 April 15, 2026 07:14
@versus

versus commented Jul 27, 2026

Copy link
Copy Markdown

Hi! We're deploying Kubero v3.1.1 with Authentik as OIDC provider and hit the same issue this PR fixes.

The root cause is two-fold:

  1. oauth2.strategy.js - validate() receives an empty profile {} because passport-oauth2 doesn't fetch userinfo for OIDC providers. The profile needs to be populated from the userinfo
    endpoint.
  2. auth.service.js:88 - reqUser.emails[0].value crashes with TypeError: Cannot read properties of undefined (reading '0') because OIDC returns flat email field, not a GitHub-style
    emails[] array.

We applied a runtime patch (ConfigMap + volumeMount) as a workaround to unblock our deployment. Would love to see this PR merged
it's the only thing blocking standard OIDC/OAuth2 integration in Kubero.

Tested with: K3s v1.36.2, Kubero Operator v0.2.2, Authentik SSO.

Also note: the CR field names for OAuth2 config are id/secret/authUrl/tokenUrl/callbackUrl (camelCase), not clientID/clientSecret/authURL etc. -- this isn't documented and caused. confusion. The correct callback path is /api/auth/oauth2/callback.

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.

3 participants