Skip to content

feat: Oauth2 to Admin - #1542

Open
nagisa-kunhah wants to merge 7 commits into
apache:developfrom
nagisa-kunhah:feat/oauth-login
Open

feat: Oauth2 to Admin#1542
nagisa-kunhah wants to merge 7 commits into
apache:developfrom
nagisa-kunhah:feat/oauth-login

Conversation

@nagisa-kunhah

Copy link
Copy Markdown

Please provide a description of this PR:

This PR adds configurable GitHub OAuth and OpenID Connect (OIDC) login support to the Dubbo Admin Console while preserving the existing username/password login flow.

The backend now provides a unified authentication model based on Principal. Password, GitHub, and OIDC identities are stored in the existing Admin session using the same representation. Existing sessions containing the legacy user value remain supported and are converted to a local Principal when read.

The Console authentication configuration now supports:

  • Explicit login methods, with password login enabled by default for backward compatibility.
  • Multiple named GitHub or OIDC providers.
  • Provider display names, client credentials, redirect URLs, post-login redirect URLs, and scopes.
  • A configurable session secret and secure-cookie option.
  • Validation for provider IDs, provider types, callback URLs, OIDC issuers, scopes, and production session secrets.

The following Console APIs are added:

  • GET /api/v1/auth/providers
  • GET /api/v1/auth/providers/:provider/login
  • GET /api/v1/auth/providers/:provider/callback
  • GET /api/v1/auth/userinfo

The OAuth/OIDC flow includes state validation, PKCE with S256, single-use login transactions, and OIDC nonce validation. GitHub identities are loaded from the GitHub user APIs, including verified-email fallback. OIDC providers are discovered from their issuer metadata, and their ID Tokens are validated before claims are mapped to a Principal.

The Vue login page now loads the enabled login methods from the Console, conditionally displays the password form, and renders buttons for configured providers. After authentication, the UI reads the current identity from /auth/userinfo so the header displays the authenticated provider username. Empty or null provider responses are handled safely for password-only deployments.

This change does not add AI-service authentication, Admin-issued access tokens, JWKS endpoints, RBAC, refresh tokens, or user-specific AI session isolation.

Backward compatibility is preserved:

  • Password login remains the default when methods is omitted.
  • Existing password-only deployments may continue using the legacy default session secret.
  • OAuth/OIDC configuration is optional.
  • Existing legacy Admin sessions remain readable.

Validation performed:

  • go test ./...
  • Focused Vue unit tests for the login page and authentication session utilities.
  • ESLint and Prettier checks for the changed frontend files.
  • git diff --cached --check

To help us figure out who should review this PR, please put an X in all the areas that this PR affects.

  • Docs
  • Installation
  • User Experience
  • Dubboctl
  • Console
  • Core Component

Please check any characteristics that apply to this pull request.

  • Adds a backward-compatible feature
  • Adds or changes Console configuration
  • Changes authentication or security-sensitive behavior
  • Adds backend tests
  • Adds frontend tests
  • Introduces a breaking change
  • Requires a data migration
  • Changes Dubboctl behavior
  • Changes Core Component behavior

@nagisa-kunhah
nagisa-kunhah marked this pull request as ready for review September 2, 2026 16:26
@robocanic
robocanic requested a balanced review from Copilot September 3, 2026 06:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Four critical and four moderate authentication and security issues remain unresolved.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds configurable GitHub OAuth and OIDC authentication while retaining password login and legacy-session compatibility.

Changes:

  • Adds principal-based sessions, provider configuration, and protected routes.
  • Implements GitHub/OIDC flows with PKCE, state, and nonce validation.
  • Updates the Vue login experience and authentication tests.
File summaries
File Review
ui-vue3/src/mocks/handlers/login.ts Mocks authentication APIs.
ui-vue3/src/main.ts Adds authentication route guards.
ui-vue3/src/Login.vue Renders configured login methods.
ui-vue3/src/Login.test.ts Tests login behavior.
ui-vue3/src/layout/header/layout_header.vue Synchronizes displayed identity.
ui-vue3/src/auth/session.ts Adds frontend session helpers.
ui-vue3/src/auth/session.test.ts Tests provider URL generation.
ui-vue3/src/api/service/login.ts Defines authentication API contracts.
pkg/console/session_options_test.go Tests session cookie options.
pkg/console/router/router.go Separates public and protected routes.
pkg/console/router/router_test.go Tests route protection.
pkg/console/handler/auth.go Implements authentication handlers. Critical (2 votes): Cookie-backed transactions can be replayed using the original cookie; use atomically consumed server-side state.
pkg/console/handler/auth_test.go Tests password and provider flows.
pkg/console/component.go Configures sessions and router startup.
pkg/console/auth/session.go Stores principals and OAuth transactions.
pkg/console/auth/session_test.go Tests session compatibility and consumption.
pkg/console/auth/service.go Coordinates provider authentication.
pkg/console/auth/provider.go Defines the provider interface.
pkg/console/auth/provider_test.go Tests provider coordination.
pkg/console/auth/principal.go Defines authenticated principals.
pkg/console/auth/oidc.go Implements OIDC authentication. Critical (2 votes): Multi-audience tokens lack azp validation. Moderate (2 votes each): Optional JWK alg is incorrectly required; HTTP requests lack bounded timeouts.
pkg/console/auth/oidc_test.go Tests OIDC validation.
pkg/console/auth/middleware.go Loads and requires principals.
pkg/console/auth/middleware_test.go Tests authentication middleware.
pkg/console/auth/github.go Implements GitHub OAuth. Moderate (1 vote): Email fallback fails when user:email was not granted; require the scope or skip the fallback.
pkg/console/auth/github_test.go Tests GitHub identity mapping.
pkg/config/display_test.go Tests secret sanitization.
pkg/config/console/config.go Adds production authentication validation. Critical (2 votes): Provider-enabled release deployments accept low-entropy session secrets; enforce adequate key length.
pkg/config/console/config_test.go Tests production configuration rules.
pkg/config/console/auth/config.go Defines provider configuration and validation. Critical (2 votes): OIDC issuers and discovered endpoints may use insecure HTTP; require HTTPS. Moderate (2 votes): Explicitly empty methods incorrectly re-enable password login.
pkg/config/console/auth/config_test.go Tests authentication defaults and validation.
go.mod Promotes OAuth and JOSE dependencies.
Review details
  • Files reviewed: 32/32 changed files
  • Comments generated: 8
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +131 to +134
case ProviderTypeOIDC:
if _, err := validateHTTPURL(provider.Issuer); err != nil {
return fmt.Errorf("auth provider %q: invalid issuer: %w", id, err)
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. OIDC issuers and discovered authorization, token, JWKS, and UserInfo endpoints now require HTTPS by default. An explicit allowInsecureHTTP option is available for local development and tests, and release mode rejects configurations that enable it.

Comment thread pkg/config/console/config.go Outdated
Comment on lines +81 to +83
if c.GinMode == ReleaseMode && len(c.Auth.Providers) > 0 && c.Auth.SessionSecret == auth.DefaultSessionSecret {
return bizerror.New(bizerror.ConfigError, "auth sessionSecret must be explicitly configured when providers are enabled in release mode")
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Provider-enabled release deployments now require sessionSecret to contain at least 32 bytes, rather than with multiple audiences must include a matching azp. Tests cover missing, mismatched, and valid authorized-party claims.

Comment thread pkg/console/auth/oidc.go Outdated
Comment on lines +167 to +170
if err := claims.ValidateWithLeeway(josejwt.Expected{
Issuer: p.issuer, AnyAudience: josejwt.Audience{p.clientID}, Time: time.Now(),
}, 0); err != nil {
return josejwt.Claims{}, oidcProfile{}, fmt.Errorf("validate OIDC ID Token issuer, audience, or expiration: %w", err)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. The ID Token parser now reads the azp claim. A present azp must match the configured client ID, and tokens with multiple audiences must include a matching azp. Tests cover missing, mismatched, and valid authorized-party claims.

Comment thread pkg/console/handler/auth.go Outdated
Comment on lines +125 to +129
// Persist consumption before contacting the Provider so failures cannot be replayed.
if err := session.Save(); err != nil {
writeSessionError(c, err)
return
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept the cookie-backed transaction design here. Replaying the original cookie may reach the token exchange again, but the authorization code is single-use and the Provider rejects the second exchange, so it cannot create another authenticated session. A server-side transaction cache would also introduce shared-state and cleanup requirements for multi-instance deployments. I updated the misleading comment and test name so they only claim that the updated browser cookie clears the transaction.

Comment thread pkg/config/console/auth/config.go Outdated
Comment on lines +74 to +76
if len(c.Methods) == 0 {
c.Methods = []string{MethodPassword}
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Password login is now enabled by default only when methods is omitted (nil). An explicitly configured empty list remains empty, allowing provider-only deployments to disable the password login endpoint.

Comment thread pkg/console/auth/github.go
Comment thread pkg/console/auth/oidc.go
Comment thread pkg/console/auth/oidc.go Outdated
 - store PKCE verifiers and OIDC nonces in an expiring server-side transaction store
 - consume OAuth transactions atomically to prevent callback replay
 - require session secrets of at least 32 bytes for release deployments with external providers
  - require HTTPS for OIDC issuers and discovered endpoints while allowing loopback HTTP for local development
  - use go-oidc for provider discovery, ID token verification, and UserInfo retrieval
  - enforce bounded OIDC HTTP timeouts, RS256 signing, audience, azp, nonce, and subject validation
  - allow JWKS keys without an optional alg field while rejecting conflicting algorithms
  - skip the GitHub email endpoint when the user:email scope is not configured
  - preserve explicitly empty login methods and return an empty JSON array for provider-only login
  - add regression tests for configuration, OAuth transactions, GitHub, OIDC, sessions, and handlers
@nagisa-kunhah

nagisa-kunhah commented Sep 3, 2026

Copy link
Copy Markdown
Author
图片 图片 图片

@sonarqubecloud

sonarqubecloud Bot commented Sep 3, 2026

Copy link
Copy Markdown

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