feat: Oauth2 to Admin - #1542
Conversation
There was a problem hiding this comment.
🟡 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.
| case ProviderTypeOIDC: | ||
| if _, err := validateHTTPURL(provider.Issuer); err != nil { | ||
| return fmt.Errorf("auth provider %q: invalid issuer: %w", id, err) | ||
| } |
There was a problem hiding this comment.
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.
| 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") | ||
| } |
There was a problem hiding this comment.
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.
| 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) |
There was a problem hiding this comment.
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.
| // Persist consumption before contacting the Provider so failures cannot be replayed. | ||
| if err := session.Save(); err != nil { | ||
| writeSessionError(c, err) | ||
| return | ||
| } |
There was a problem hiding this comment.
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.
| if len(c.Methods) == 0 { | ||
| c.Methods = []string{MethodPassword} | ||
| } |
There was a problem hiding this comment.
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.
- 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
|






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 legacyuservalue remain supported and are converted to a localPrincipalwhen read.The Console authentication configuration now supports:
The following Console APIs are added:
GET /api/v1/auth/providersGET /api/v1/auth/providers/:provider/loginGET /api/v1/auth/providers/:provider/callbackGET /api/v1/auth/userinfoThe 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/userinfoso the header displays the authenticated provider username. Empty ornullprovider 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:
methodsis omitted.Validation performed:
go test ./...git diff --cached --checkTo help us figure out who should review this PR, please put an X in all the areas that this PR affects.
Please check any characteristics that apply to this pull request.