Skip to content

Migrate KKP dashboard auth from implicit flow to OAuth authorization code flow#8053

Open
ahmadhamzh wants to merge 16 commits intokubermatic:mainfrom
ahmadhamzh:7940-oauth-authorization-code-flow-migration
Open

Migrate KKP dashboard auth from implicit flow to OAuth authorization code flow#8053
ahmadhamzh wants to merge 16 commits intokubermatic:mainfrom
ahmadhamzh:7940-oauth-authorization-code-flow-migration

Conversation

@ahmadhamzh
Copy link
Copy Markdown
Contributor

What this PR does / why we need it:
Re-submission of #7960 with production fixes applied.

Introduces OAuth Authorization Code flow with PKCE and replaces the in-memory state store with a signed and encrypted cookie, allowing the flow to work reliably across multiple replicas.

Fixes incorrect redirect URI handling behind TLS-terminating ingress by deriving the correct scheme and host from the configured redirect URI instead of the request.

Implements proper OIDC nonce handling by including it in the auth request and validating it against the ID token to meet the OIDC specification.

Which issue(s) this PR fixes:
Fixes #7940

What type of PR is this?
/kind feature

Does this PR introduce a user-facing change? Then add your Release Note here:

Migrate KKP dashboard authentication from OAuth implicit flow to authorization code flow with PKCE.

Documentation:

TBD

Test issue:

https://github.com/kubermatic/dashboard/issues/7982

@kubermatic-bot kubermatic-bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. docs/tbd Denotes a PR that needs documentation (change) that will be done later. kind/feature Categorizes issue or PR as related to a new feature. test-issue/provided Denotes a PR that has a valid test issue reference. sig/api Denotes a PR or issue as being assigned to SIG API. labels May 5, 2026
@kubermatic-bot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign waseem826 for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubermatic-bot kubermatic-bot added dco-signoff: yes Denotes that all commits in the pull request have the valid DCO signoff message. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels May 5, 2026
@ahmadhamzh ahmadhamzh force-pushed the 7940-oauth-authorization-code-flow-migration branch from d8f5946 to 2611b3b Compare May 6, 2026 02:52
@ahmadhamzh ahmadhamzh force-pushed the 7940-oauth-authorization-code-flow-migration branch from 2611b3b to bb0252a Compare May 6, 2026 04:01
@ahmadhamzh
Copy link
Copy Markdown
Contributor Author

/retest

2 similar comments
@ahmadhamzh
Copy link
Copy Markdown
Contributor Author

/retest

@ahmadhamzh
Copy link
Copy Markdown
Contributor Author

/retest

@ahmadhamzh ahmadhamzh requested a review from KhizerRehan May 6, 2026 09:47
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR migrates KKP Dashboard authentication from the legacy browser-side implicit flow to a backend-driven OAuth 2.0 Authorization Code flow with PKCE, moving token handling to secure cookies and adding dedicated v2 auth endpoints (/api/v2/auth/*) to better support multi-replica deployments and OIDC spec requirements (nonce validation).

Changes:

  • Adds new API v2 authflow endpoints for login/callback/refresh/logout/status and extends OIDC issuer interfaces for PKCE + nonce support.
  • Updates the Angular app to initiate login via /api/v2/auth/login, handle cookie-based sessions, and refresh tokens on 401 responses.
  • Removes obsolete frontend implicit-flow/token/nonce plumbing (env OIDC URLs, token service, check-token interceptor, cookie DI tokens) and adjusts affected UI/components/tests.

Reviewed changes

Copilot reviewed 39 out of 39 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
modules/web/src/test/services/auth-mock.ts Updates auth mock to match new logout response shape.
modules/web/src/environments/environment.ts Removes implicit-flow OIDC environment fields.
modules/web/src/environments/environment.prod.ts Removes implicit-flow OIDC environment fields.
modules/web/src/environments/environment.e2e.ts Removes implicit-flow OIDC environment fields.
modules/web/src/environments/environment.e2e.mock.ts Removes implicit-flow OIDC environment fields.
modules/web/src/environments/environment.e2e.local.ts Removes implicit-flow OIDC environment fields.
modules/web/src/app/shared/model/Config.ts Removes OIDC provider enum no longer used by frontend.
modules/web/src/app/shared/components/openstack-credentials/default/component.ts Uses UserService for default username instead of auth token parsing.
modules/web/src/app/project/component.ts Removes cookie-based “autoredirect” landing redirect logic.
modules/web/src/app/pages/frontpage/template.html Login button now points directly to /api/v2/auth/login.
modules/web/src/app/pages/frontpage/component.ts Simplifies frontpage login initiation for code flow.
modules/web/src/app/pages/api-docs/component.ts Removes bearer-token injection; relies on cookie auth and simplifies back navigation.
modules/web/src/app/module.ts Ensures auth init runs before user/datacenter/config initialization.
modules/web/src/app/core/services/user.ts Switches user initialization gating from token service to auth status.
modules/web/src/app/core/services/user.spec.ts Updates tests after removal of TokenService/cookie DI usage.
modules/web/src/app/core/services/token.ts Removes legacy client-side JWT parsing/token storage service.
modules/web/src/app/core/services/auth/service.ts Replaces implicit-flow logic with status/refresh/logout API calls + refresh scheduling.
modules/web/src/app/core/services/auth/service.spec.ts Updates tests after removal of TokenService/cookie DI usage.
modules/web/src/app/core/services/auth/guard.ts Route guard now redirects unauthenticated users to / instead of starting implicit login.
modules/web/src/app/core/module.ts Removes TokenService, cookie DI provider, and CheckTokenInterceptor.
modules/web/src/app/core/interceptors/index.ts Removes export of deleted CheckTokenInterceptor.
modules/web/src/app/core/interceptors/error-notifications.ts Adds refresh-cookie-missing error text to the silenced error list and improves plain-text error handling.
modules/web/src/app/core/interceptors/check-token.ts Removes legacy interceptor that redirected when token missing/expired.
modules/web/src/app/core/interceptors/auth.ts Implements 401-triggered refresh + retry using cookie-based session.
modules/web/src/app/core/components/user-panel/component.ts Logout now uses backend response redirect instead of frontend OIDC-logout composition.
modules/web/src/app/core/components/user-panel/component.spec.ts Adjusts logout test expectations for new redirect-based behavior.
modules/web/src/app/config.ts Removes cookie DI token/constants used by the legacy implicit flow.
modules/web/cypress/intercept/root.ts Removes nonce cookie setup from e2e helpers.
modules/api/pkg/provider/auth/types/types.go Extends OIDC issuer Exchange for optional PKCE verifier; adds nonce to token claims.
modules/api/pkg/handler/v2/routing.go Wires OIDCIssuerVerifier into v2 routing.
modules/api/pkg/handler/v2/routes_v2.go Registers the new authflow routes under v2.
modules/api/pkg/handler/v2/authflow/routing.go Adds router install for `/auth/login
modules/api/pkg/handler/v2/authflow/handler.go Implements authorization code + PKCE flow, secure state cookie, nonce validation, refresh, logout redirect, and cookie chunking.
modules/api/pkg/handler/test/fake_auth.go Updates fake issuer Exchange signature for PKCE-compatible interface.
modules/api/pkg/handler/routing.go Adds OIDCIssuerVerifier to routing params for v2 authflow wiring.
modules/api/pkg/handler/auth/oidc.go Adds nonce claim extraction and PKCE verifier support to token exchange.
modules/api/hack/run-api.sh Updates dev run script to use a different OIDC authenticator client ID.
modules/api/cmd/kubermatic-api/options.go Adds provider field for OIDCIssuerVerifier.
modules/api/cmd/kubermatic-api/main.go Passes OIDCIssuerVerifier into handler routing params.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

clearNamedCookie(w, idTokenCookieName, "/", secureMode)
clearNamedCookie(w, refreshTokenCookieName, "/api/v2/auth", secureMode)
// Clear potential chunks (token-1, token-2, etc.)
for i := range maxNumOfTokenCookies {
Comment on lines +101 to +103
nonce := apimachineryrand.String(apimachineryrand.IntnRange(10, 15))
state := apimachineryrand.String(apimachineryrand.IntnRange(10, 15))

setNamedCookie(w, idTokenCookieName, tokenValue, "/", tokenMaxAge, oidcConfig.CookieSecureMode)
} else {
// Chunked cookies: token-1, token-2, etc.
chunks := chunkString(tokenValue, maxCookieSize)
Comment on lines +351 to +355
tokenValue, err := a.tokenExtractor.Extract(r)
if err != nil {
http.Error(w, "missing token cookie", http.StatusBadRequest)
return
}
// 8. Redirect to frontend landing page.
userInfo, err := a.userProvider.UserByEmail(r.Context(), claims.Email)
if err != nil {
fmt.Println("failed to get user info", err)
}
}
if rawNonce, found := claims["nonce"]; found {
oidcClaims.Nonce = rawNonce.(string)
return next.handle(req).pipe(
catchError((error: HttpErrorResponse) => {
// Only handle 401s for API requests, and don't retry the refresh call itself.
if (error.status === HttpStatusCode.Unauthorized && !req.url.startsWith(this._refreshUrl)) {
Comment on lines +97 to +105
func (a *authHandler) loginHandler() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
oidcConfig := a.oidcIssuerVerifier.OIDCConfig()

nonce := apimachineryrand.String(apimachineryrand.IntnRange(10, 15))
state := apimachineryrand.String(apimachineryrand.IntnRange(10, 15))

codeVerifier := oauth2.GenerateVerifier()

Comment on lines +57 to +62
this._expiresAt = response?.expires_at ?? 0;
const msUntilExpiry = this._expiresAt * SECONDS_TO_MS - Date.now();
if (msUntilExpiry <= this._refreshBufferMs) {
this._refreshToken(resolve);
return;
}
Comment on lines +73 to +75
// Fallback: check if token cookie is readable (non-HttpOnly environments like e2e tests).
// In production the cookie is HttpOnly so this returns false, relying on the status endpoint.
return !!this._cookieService.get('token');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Denotes that all commits in the pull request have the valid DCO signoff message. docs/tbd Denotes a PR that needs documentation (change) that will be done later. kind/feature Categorizes issue or PR as related to a new feature. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/api Denotes a PR or issue as being assigned to SIG API. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. test-issue/provided Denotes a PR that has a valid test issue reference.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OAuth Authorization Code Flow Migration

3 participants