Skip to content

Add support k8s static auth#372

Merged
celdrake merged 5 commits into
flightctl:mainfrom
celdrake:temp-k8s-static-auth
Nov 13, 2025
Merged

Add support k8s static auth#372
celdrake merged 5 commits into
flightctl:mainfrom
celdrake:temp-k8s-static-auth

Conversation

@celdrake

@celdrake celdrake commented Nov 7, 2025

Copy link
Copy Markdown
Collaborator

The Flight Control UI will soon add support for multiple authentication providers.

Currently, the Backend have added support for a new statically configured auth provider "k8s" which is based on an existing token. This PR allows the UI to work with this new authentication provider.

Summary by CodeRabbit

  • New Features

    • New login page with token-based authentication and live token validation
    • Support for Kubernetes/service-account token authentication
    • Added localized authentication UI messages and "Auth provider" resource label
    • Device status now exposes systemd unit status
  • Bug Fixes

    • Improved authentication error handling, session clearing, and correct response handling during login/refresh
    • Prevents unwanted redirects when already on the login page

@coderabbitai

coderabbitai Bot commented Nov 7, 2025

Copy link
Copy Markdown

Walkthrough

Adds a token-based Kubernetes auth provider and backend handling, a new frontend LoginPage with JWT-format validation and submit flow, routing for /login, related auth-context/api adjustments to avoid redirects on /login, many generated auth/type/systemd model changes, artifact-app removal, and toolchain/container image bumps.

Changes

Cohort / File(s) Summary
Frontend — Login UI & routing
apps/standalone/src/app/components/Login/LoginPage.tsx, apps/standalone/src/app/routes.tsx
New LoginPage component with token textarea, live JWT-format validation (isValidJwtTokenFormat), submit handling (POST {token} to login API), localStorage expiration/org management, redirect on success; new /login route registered.
Frontend — Auth context & API utils
apps/standalone/src/app/context/AuthContext.ts, apps/standalone/src/app/utils/apiCalls.ts
Skip auth checks/refresh scheduling and avoid redirectWhenAlreadyOn /login; redirectToLogin defaults to /login.
Backend — k8s token auth provider & handlers
proxy/auth/k8s.go, proxy/auth/auth.go, proxy/auth/common.go
New TokenAuthProvider validating tokens against k8s backend, extracting username/exp from JWT claims; auth initialization now extracts provider info and branches per provider type; added cookie-clear and JSON error helpers; added token-based login path for k8s providers.
Types — auth, k8s, systemd models
libs/types/... (e.g. models/AapProviderSpec.ts, models/K8sProviderSpec.ts, models/AuthProvider*.ts, models/*Auth*.ts, models/Systemd*.ts, index.ts)
Large generated changes: new provider specs/unions (OIDC/OAuth2/AAP/K8s), many Auth* assignment types, removed ArtifactApplicationProviderSpec and AuthOrganizationsConfig, added systemd enums/types, updated DeviceStatus to include systemd, updated exports in index.ts.
UI components & types adjustments
libs/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.ts, libs/ui-components/src/types/deviceSpec.ts, libs/ui-components/src/types/extraTypes.ts, libs/ui-components/src/components/OverviewPage/Cards/Alerts/AlertsCard.tsx
Removed artifact-app/provider handling and isArtifactAppProvider guard; unified image/inline app mapping and patching; added ResourceKind.AUTH_PROVIDER label case.
i18n translations
libs/i18n/locales/en/translation.json
Added English strings for token login UI, validation, security notes and auth provider labels.
Go toolchain, deps, container images, docs
proxy/go.mod, Containerfile, Containerfile.ocp, README.md
Bumped Go toolchain (1.23 → 1.24), updated flightctl dependency and indirect modules; updated base image tags in Containerfile/Containerfile.ocp; README Go minimum updated.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Frontend as Frontend\n(LoginPage)
    participant ProxyAuth as Proxy Auth
    participant K8sBackend as K8s Backend

    User->>Frontend: Paste token, click Login
    Frontend->>Frontend: isValidJwtTokenFormat(token)
    alt Invalid format
        Frontend-->>User: show validation error
    else Valid format
        Frontend->>ProxyAuth: POST /login { token }
        activate ProxyAuth
        ProxyAuth->>ProxyAuth: extract default provider info
        alt provider == k8s (token)
            ProxyAuth->>K8sBackend: GET /api/v1/auth/validate (Bearer token)
            alt 2xx
                K8sBackend-->>ProxyAuth: OK + user info
                ProxyAuth-->>Frontend: 200 + token + expiresIn
            else 401/403
                K8sBackend-->>ProxyAuth: Unauthorized
                ProxyAuth->>ProxyAuth: try extract exp from token claims
                ProxyAuth-->>Frontend: 401 + error
            end
        else other provider
            ProxyAuth->>ProxyAuth: perform OAuth flow / redirect
        end
        deactivate ProxyAuth
        alt Success
            Frontend->>Frontend: store expiration, redirect to /
        else Failure
            Frontend-->>User: show submit/auth error
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

  • Areas needing focused review:
    • proxy/auth/k8s.go: JWT parsing, expiration extraction, HTTP validation call and edge-case error handling.
    • proxy/auth/auth.go & proxy/auth/common.go: provider extraction logic, Login/Refresh/GetUserInfo cookie clearing and 401 semantics.
    • libs/types changes and removal of ArtifactApplicationProviderSpec — check consumers and downstream type compatibility.
    • Frontend LoginPage: token validation, localStorage side effects, submit/error state and redirect behavior.

Possibly related PRs

Suggested reviewers

  • rawagner
  • hexfusion

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 38.46% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add support k8s static auth' directly and specifically describes the main change: adding support for Kubernetes static token authentication provider in the UI.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cb4340f and 2d3fdb1.

⛔ Files ignored due to path filters (1)
  • proxy/go.sum is excluded by !**/*.sum
📒 Files selected for processing (41)
  • Containerfile (1 hunks)
  • Containerfile.ocp (1 hunks)
  • README.md (1 hunks)
  • apps/standalone/src/app/components/Login/LoginPage.tsx (1 hunks)
  • apps/standalone/src/app/context/AuthContext.ts (3 hunks)
  • apps/standalone/src/app/routes.tsx (2 hunks)
  • apps/standalone/src/app/utils/apiCalls.ts (2 hunks)
  • libs/i18n/locales/en/translation.json (2 hunks)
  • libs/types/index.ts (4 hunks)
  • libs/types/models/AapProviderSpec.ts (1 hunks)
  • libs/types/models/ApplicationProviderSpec.ts (1 hunks)
  • libs/types/models/ArtifactApplicationProviderSpec.ts (0 hunks)
  • libs/types/models/AuthConfig.ts (1 hunks)
  • libs/types/models/AuthDynamicOrganizationAssignment.ts (1 hunks)
  • libs/types/models/AuthDynamicRoleAssignment.ts (1 hunks)
  • libs/types/models/AuthOrganizationAssignment.ts (1 hunks)
  • libs/types/models/AuthOrganizationsConfig.ts (0 hunks)
  • libs/types/models/AuthPerUserOrganizationAssignment.ts (1 hunks)
  • libs/types/models/AuthProvider.ts (1 hunks)
  • libs/types/models/AuthProviderList.ts (1 hunks)
  • libs/types/models/AuthProviderSpec.ts (1 hunks)
  • libs/types/models/AuthRoleAssignment.ts (1 hunks)
  • libs/types/models/AuthStaticOrganizationAssignment.ts (1 hunks)
  • libs/types/models/AuthStaticRoleAssignment.ts (1 hunks)
  • libs/types/models/DeviceStatus.ts (2 hunks)
  • libs/types/models/K8sProviderSpec.ts (1 hunks)
  • libs/types/models/OAuth2ProviderSpec.ts (1 hunks)
  • libs/types/models/OIDCProviderSpec.ts (1 hunks)
  • libs/types/models/ResourceKind.ts (1 hunks)
  • libs/types/models/SystemdActiveStateType.ts (1 hunks)
  • libs/types/models/SystemdEnableStateType.ts (1 hunks)
  • libs/types/models/SystemdLoadStateType.ts (1 hunks)
  • libs/types/models/SystemdUnitStatus.ts (1 hunks)
  • libs/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.ts (1 hunks)
  • libs/ui-components/src/components/OverviewPage/Cards/Alerts/AlertsCard.tsx (1 hunks)
  • libs/ui-components/src/types/deviceSpec.ts (0 hunks)
  • libs/ui-components/src/types/extraTypes.ts (1 hunks)
  • proxy/auth/auth.go (5 hunks)
  • proxy/auth/common.go (3 hunks)
  • proxy/auth/k8s.go (1 hunks)
  • proxy/go.mod (2 hunks)
💤 Files with no reviewable changes (3)
  • libs/ui-components/src/types/deviceSpec.ts
  • libs/types/models/ArtifactApplicationProviderSpec.ts
  • libs/types/models/AuthOrganizationsConfig.ts
🚧 Files skipped from review as they are similar to previous changes (22)
  • libs/types/models/ResourceKind.ts
  • libs/ui-components/src/components/OverviewPage/Cards/Alerts/AlertsCard.tsx
  • libs/types/models/SystemdEnableStateType.ts
  • apps/standalone/src/app/context/AuthContext.ts
  • libs/types/models/OAuth2ProviderSpec.ts
  • libs/types/models/AuthDynamicRoleAssignment.ts
  • apps/standalone/src/app/routes.tsx
  • proxy/auth/auth.go
  • libs/types/models/SystemdUnitStatus.ts
  • apps/standalone/src/app/components/Login/LoginPage.tsx
  • libs/types/models/AuthProviderSpec.ts
  • libs/types/models/AapProviderSpec.ts
  • libs/types/models/K8sProviderSpec.ts
  • libs/types/models/AuthStaticRoleAssignment.ts
  • proxy/auth/common.go
  • Containerfile
  • Containerfile.ocp
  • libs/types/models/AuthPerUserOrganizationAssignment.ts
  • libs/types/models/AuthStaticOrganizationAssignment.ts
  • libs/types/models/DeviceStatus.ts
  • libs/ui-components/src/components/Device/EditDeviceWizard/deviceSpecUtils.ts
  • libs/ui-components/src/types/extraTypes.ts
🧰 Additional context used
🧠 Learnings (10)
📓 Common learnings
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 371
File: libs/types/models/AppType.ts:10-10
Timestamp: 2025-10-29T16:47:29.614Z
Learning: PR #371 (flightctl/flightctl-ui) adds the AppTypeQuadlet enum member and related types as a preparatory change. Full implementation of quadlet application support in the UI will be added later, after backend support is available.
📚 Learning: 2025-03-12T08:41:34.720Z
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 227
File: libs/ui-components/src/components/Device/EditDeviceWizard/steps/ReviewTrackedSystemdServices.tsx:3-3
Timestamp: 2025-03-12T08:41:34.720Z
Learning: In the flightctl-ui codebase, SystemdUnitsFormValues is defined as { systemdUnits: SystemdUnitFormValue[] }, allowing for direct destructuring of the systemdUnits property in component props.

Applied to files:

  • libs/types/models/SystemdActiveStateType.ts
  • libs/types/index.ts
  • libs/types/models/SystemdLoadStateType.ts
📚 Learning: 2025-03-19T08:55:03.335Z
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 240
File: libs/ui-components/src/components/Device/DeviceDetails/DeviceApplications.tsx:44-50
Timestamp: 2025-03-19T08:55:03.335Z
Learning: In FlightCtl, the name field is required for Inline applications but optional for Image-based applications. This requirement is enforced by validation logic even though TypeScript type definitions might not explicitly show this distinction.

Applied to files:

  • libs/types/models/ApplicationProviderSpec.ts
📚 Learning: 2025-03-20T12:37:36.986Z
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 240
File: libs/ui-components/src/types/deviceSpec.ts:0-0
Timestamp: 2025-03-20T12:37:36.986Z
Learning: In the FlightCtl UI project, `name` is required for inline applications but optional for image applications. This is enforced at the type level in the `InlineAppForm` type.

Applied to files:

  • libs/types/models/ApplicationProviderSpec.ts
📚 Learning: 2025-09-17T12:24:09.201Z
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 346
File: libs/ui-components/src/components/common/OrganizationGuard.tsx:54-62
Timestamp: 2025-09-17T12:24:09.201Z
Learning: In the Flight Control UI proxy, organization feature detection uses a 501 (Not Implemented) status code to explicitly signal when organizations are disabled via the ORGANIZATIONS_ENABLED setting. Any other status code (including errors like 404, 500) should be treated as organizations being enabled. The logic `organizationsEnabled = response.status !== 501` is correct and more resilient than checking `response.ok`.

Applied to files:

  • proxy/auth/k8s.go
📚 Learning: 2025-02-17T08:41:57.993Z
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 0
File: :0-0
Timestamp: 2025-02-17T08:41:57.993Z
Learning: All files in `libs/types/models` are auto-generated using OpenAPI Generator from the schema defined in https://github.com/flightctl/flightctl/blob/main/api/v1alpha1/openapi.yaml. Changes to these files should be made in the schema instead of modifying the generated files directly.

Applied to files:

  • libs/types/index.ts
  • proxy/go.mod
📚 Learning: 2025-10-10T11:35:04.458Z
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 0
File: :0-0
Timestamp: 2025-10-10T11:35:04.458Z
Learning: In the flightctl-ui repository, TypeScript types are generated using hey-api/openapi-ts and output to a single index.ts file (previously used openapi-typescript-codegen with one file per type under /libs/types/models).

Applied to files:

  • libs/types/index.ts
📚 Learning: 2025-03-20T12:34:33.199Z
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 240
File: libs/types/models/FileSpec.ts:8-8
Timestamp: 2025-03-20T12:34:33.199Z
Learning: Files in the types directory are autogenerated from the OpenAPI spec in the flightctl project and should not be directly modified.

Applied to files:

  • libs/types/index.ts
📚 Learning: 2025-10-29T16:47:29.614Z
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 371
File: libs/types/models/AppType.ts:10-10
Timestamp: 2025-10-29T16:47:29.614Z
Learning: PR #371 (flightctl/flightctl-ui) adds the AppTypeQuadlet enum member and related types as a preparatory change. Full implementation of quadlet application support in the UI will be added later, after backend support is available.

Applied to files:

  • proxy/go.mod
📚 Learning: 2025-01-07T10:11:14.375Z
Learnt from: rawagner
Repo: flightctl/flightctl-ui PR: 181
File: proxy/config/ocp.go:16-16
Timestamp: 2025-01-07T10:11:14.375Z
Learning: In the flightctl-ui repository, the `RBACNs` variable used in `proxy/config/ocp.go` is defined in `proxy/config/config.go` as a package-level variable that retrieves its value from the environment variable `K8S_RBAC_NS`.

Applied to files:

  • proxy/go.mod
🧬 Code graph analysis (11)
libs/types/models/AuthProviderList.ts (2)
libs/types/index.ts (3)
  • AuthProviderList (23-23)
  • ListMeta (130-130)
  • AuthProvider (22-22)
libs/types/models/AuthProvider.ts (1)
  • AuthProvider (10-21)
libs/types/models/AuthDynamicOrganizationAssignment.ts (1)
libs/types/index.ts (1)
  • AuthDynamicOrganizationAssignment (18-18)
libs/types/models/AuthProvider.ts (3)
proxy/auth/common.go (1)
  • AuthProvider (28-34)
libs/types/index.ts (3)
  • AuthProvider (22-22)
  • ObjectMeta (135-135)
  • AuthProviderSpec (24-24)
libs/types/models/AuthProviderSpec.ts (1)
  • AuthProviderSpec (9-9)
libs/types/models/AuthOrganizationAssignment.ts (3)
libs/types/models/AuthStaticOrganizationAssignment.ts (1)
  • AuthStaticOrganizationAssignment (8-17)
libs/types/models/AuthDynamicOrganizationAssignment.ts (1)
  • AuthDynamicOrganizationAssignment (8-25)
libs/types/models/AuthPerUserOrganizationAssignment.ts (1)
  • AuthPerUserOrganizationAssignment (8-21)
libs/types/models/OIDCProviderSpec.ts (3)
libs/types/index.ts (3)
  • OIDCProviderSpec (137-137)
  • AuthOrganizationAssignment (20-20)
  • AuthRoleAssignment (25-25)
libs/types/models/AuthOrganizationAssignment.ts (1)
  • AuthOrganizationAssignment (11-11)
libs/types/models/AuthRoleAssignment.ts (1)
  • AuthRoleAssignment (10-10)
libs/types/models/SystemdActiveStateType.ts (1)
libs/types/index.ts (1)
  • SystemdActiveStateType (167-167)
libs/types/models/ApplicationProviderSpec.ts (2)
libs/types/models/ImageApplicationProviderSpec.ts (1)
  • ImageApplicationProviderSpec (6-11)
libs/types/models/InlineApplicationProviderSpec.ts (1)
  • InlineApplicationProviderSpec (7-12)
proxy/auth/k8s.go (4)
proxy/auth/common.go (2)
  • LoginParameters (24-26)
  • TokenData (18-22)
proxy/config/config.go (1)
  • FctlApiUrl (10-10)
proxy/log/log.go (1)
  • GetLogger (17-19)
proxy/bridge/common.go (1)
  • GetTlsConfig (13-38)
libs/types/models/SystemdLoadStateType.ts (1)
libs/types/index.ts (1)
  • SystemdLoadStateType (169-169)
libs/types/models/AuthRoleAssignment.ts (3)
libs/types/index.ts (3)
  • AuthRoleAssignment (25-25)
  • AuthStaticRoleAssignment (27-27)
  • AuthDynamicRoleAssignment (19-19)
libs/types/models/AuthStaticRoleAssignment.ts (1)
  • AuthStaticRoleAssignment (8-17)
libs/types/models/AuthDynamicRoleAssignment.ts (1)
  • AuthDynamicRoleAssignment (8-17)
libs/types/models/AuthConfig.ts (2)
proxy/auth/common.go (1)
  • AuthProvider (28-34)
libs/types/models/AuthProvider.ts (1)
  • AuthProvider (10-21)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: integration-tests
  • GitHub Check: Lint
🔇 Additional comments (20)
README.md (1)

7-7: LGTM! Documentation aligns with toolchain update.

The Go version requirement update is consistent with the toolchain bump in proxy/go.mod.

apps/standalone/src/app/utils/apiCalls.ts (2)

58-64: LGTM! Dual authentication mode support implemented correctly.

The logic properly handles both token-based (k8s) and OAuth authentication flows. When the backend returns an empty URL, the UI redirects to /login for token-based auth; otherwise, it redirects to the external OAuth provider.


77-82: LGTM! Redirect loop prevention is correct.

The guard prevents redirect loops by checking if the user is already on the login page before calling redirectToLogin().

libs/types/models/ApplicationProviderSpec.ts (1)

1-15: LGTM! Auto-generated type updated to remove ArtifactApplicationProviderSpec.

The type now only supports ImageApplicationProviderSpec | InlineApplicationProviderSpec. This is an auto-generated file from the OpenAPI schema, and the removal of ArtifactApplicationProviderSpec appears to be a deliberate schema change reflected across the codebase.

Based on learnings

libs/types/models/SystemdLoadStateType.ts (1)

1-16: LGTM! Auto-generated systemd load state enum.

The enum defines standard systemd load states (stub, loaded, not-found, bad-setting, error, merged, masked) and is used by the SystemdUnitStatus type.

Based on learnings

libs/types/models/AuthProvider.ts (1)

1-22: LGTM! Auto-generated Kubernetes-style auth provider resource.

The type follows standard Kubernetes resource conventions with apiVersion, kind, metadata, and spec fields, supporting the new authentication provider model.

Based on learnings

proxy/go.mod (4)

3-5: LGTM! Go toolchain upgraded to 1.24.

The toolchain update is consistent with the README.md prerequisite change.


8-8: LGTM! FlightCtl module updated to main branch.

The dependency update to v1.0.0-main.0.20251113083308-3f1bc5ade635 brings in the backend support for the new k8s authentication provider.


12-12: LGTM! JWT library version confirmed secure.

The lestrrat-go/jwx/v2 at v2.1.4 is a valid and secure version, as confirmed in the previous review discussion.


17-66: LGTM! Indirect dependencies updated appropriately.

The indirect dependency updates align with the flightctl module upgrade and Go 1.24 toolchain requirements.

libs/types/models/AuthProviderList.ts (1)

1-25: LGTM! Auto-generated Kubernetes-style list resource.

The type follows standard Kubernetes list conventions with apiVersion, kind, metadata, and items fields for managing collections of AuthProvider resources.

Based on learnings

libs/types/models/AuthDynamicOrganizationAssignment.ts (1)

1-26: LGTM! Auto-generated dynamic organization assignment type.

The type supports claim-based organization assignment with configurable name prefix/suffix, enabling flexible organization mapping from authentication provider claims.

Based on learnings

libs/i18n/locales/en/translation.json (1)

16-27: LGTM!

The new translation keys provide clear, user-friendly messaging for the K8s token authentication flow. The security warning and JWT format validation message are particularly helpful for users.

Also applies to: 699-699

libs/types/models/AuthOrganizationAssignment.ts (1)

1-11: LGTM!

This is auto-generated code from the OpenAPI specification. The union type correctly combines the three organization assignment variants.

libs/types/models/OIDCProviderSpec.ts (1)

1-45: LGTM!

This is auto-generated code from the OpenAPI specification. The OIDC provider spec is well-structured with clear documentation.

libs/types/models/AuthRoleAssignment.ts (1)

1-10: LGTM!

This is auto-generated code from the OpenAPI specification. The union type correctly combines the two role assignment variants.

libs/types/models/AuthConfig.ts (1)

1-23: LGTM!

This is auto-generated code from the OpenAPI specification. The updated AuthConfig structure supports multiple authentication providers, which aligns with the PR's goal of adding K8s static auth support.

libs/types/models/SystemdActiveStateType.ts (1)

1-17: LGTM!

This is auto-generated code from the OpenAPI specification. The enum correctly represents systemd active states.

libs/types/index.ts (1)

6-6: LGTM!

This is auto-generated code from the OpenAPI specification. The updated exports correctly surface the new authentication provider types and systemd-related types introduced in this PR.

Also applies to: 18-27, 126-126, 134-134, 137-137, 167-170

proxy/auth/k8s.go (1)

1-230: LGTM!

The K8s token authentication provider implementation is well-structured with proper error handling, TLS configuration, and Kubernetes-specific token claim extraction. The token validation logic correctly restricts to 2xx responses (addressing the previous review feedback), and the username extraction includes appropriate fallbacks for different K8s token formats.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@celdrake celdrake force-pushed the temp-k8s-static-auth branch from 77e285d to 1c9ed16 Compare November 7, 2025 09:30

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/standalone/src/app/components/Login/LoginPage.tsx (1)

115-127: Consider the UX impact of immediate trimming.

The token value is trimmed on every change, which means if a user pastes a token with leading/trailing whitespace or tries to type a space at the beginning, it will be immediately removed from the input. While this prevents whitespace-related authentication errors, it might be slightly surprising to users.

This behavior is acceptable for a token input field where whitespace is never valid, but consider whether you want to allow untrimmed input in the UI and only trim on submission for a more familiar UX.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between edd2687 and 1c9ed16.

📒 Files selected for processing (8)
  • apps/standalone/src/app/components/Login/LoginPage.tsx (1 hunks)
  • apps/standalone/src/app/context/AuthContext.ts (1 hunks)
  • apps/standalone/src/app/routes.tsx (2 hunks)
  • apps/standalone/src/app/utils/apiCalls.ts (1 hunks)
  • libs/i18n/locales/en/translation.json (1 hunks)
  • proxy/auth/auth.go (3 hunks)
  • proxy/auth/common.go (3 hunks)
  • proxy/auth/k8s.go (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 371
File: libs/types/models/AppType.ts:10-10
Timestamp: 2025-10-29T16:47:29.614Z
Learning: PR #371 (flightctl/flightctl-ui) adds the AppTypeQuadlet enum member and related types as a preparatory change. Full implementation of quadlet application support in the UI will be added later, after backend support is available.
🧬 Code graph analysis (5)
apps/standalone/src/app/routes.tsx (1)
apps/standalone/src/app/components/Login/LoginPage.tsx (1)
  • LoginPage (42-175)
proxy/auth/auth.go (2)
proxy/auth/k8s.go (2)
  • TokenAuthProvider (17-20)
  • TokenLoginParameters (22-24)
proxy/log/log.go (1)
  • GetLogger (17-19)
proxy/auth/common.go (3)
proxy/common/const.go (1)
  • CookieSessionName (4-4)
proxy/config/config.go (1)
  • TlsCertPath (15-15)
proxy/log/log.go (1)
  • GetLogger (17-19)
apps/standalone/src/app/components/Login/LoginPage.tsx (3)
libs/ui-components/src/hooks/useTranslation.ts (1)
  • useTranslation (5-8)
libs/ui-components/src/utils/organizationStorage.ts (1)
  • ORGANIZATION_STORAGE_KEY (1-1)
apps/standalone/src/app/utils/apiCalls.ts (1)
  • loginAPI (17-17)
proxy/auth/k8s.go (4)
proxy/auth/common.go (2)
  • LoginParameters (24-26)
  • TokenData (18-22)
proxy/config/config.go (1)
  • FctlApiUrl (10-10)
proxy/log/log.go (1)
  • GetLogger (17-19)
proxy/bridge/common.go (1)
  • GetTlsConfig (13-38)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: integration-tests
🔇 Additional comments (17)
apps/standalone/src/app/utils/apiCalls.ts (1)

61-63: LGTM!

The conditional redirect logic correctly distinguishes between token-based (k8s) and OAuth authentication flows with clear comments.

apps/standalone/src/app/context/AuthContext.ts (1)

37-41: LGTM!

Correctly skips authentication checks on the login page, preventing unnecessary API calls during token-based login flow.

proxy/auth/common.go (3)

21-21: LGTM!

Adding the Provider field to TokenData enables tracking which authentication provider issued the token, useful for multi-provider scenarios.


53-64: LGTM!

The clearCookie helper correctly invalidates the session cookie by setting MaxAge: -1, maintaining consistency with the existing setCookie implementation.


135-151: LGTM!

The respondWithError helper provides centralized JSON error response handling with appropriate logging on failures.

proxy/auth/k8s.go (4)

85-143: LGTM!

The JWT parsing and expiration extraction logic correctly handles the JWT structure and various claim type representations without external dependencies.


145-187: LGTM!

The username extraction logic provides appropriate Kubernetes-specific fallbacks, including handling both nested and flat claim structures, and extracting the service account name from the full system:serviceaccount:namespace:name format.


189-216: LGTM!

The GetUserInfo implementation correctly checks token expiration and extracts the username from JWT claims, returning appropriate error responses.


218-248: LGTM!

The placeholder methods for RefreshToken, Logout, and GetLoginRedirectURL appropriately indicate that these operations are not applicable for token-based authentication, and the factory function correctly initializes the provider with TLS config.

proxy/auth/auth.go (3)

48-49: LGTM!

The k8s authentication type is correctly integrated into the provider initialization switch.


69-92: LGTM!

The token-based authentication flow correctly validates the token format, calls the validation provider, and returns appropriate HTTP status codes (400 for bad requests, 401 for authentication failures).


165-165: LGTM!

Clearing the session cookie on authentication errors is a good security practice that prevents stale or invalid sessions from persisting.

Also applies to: 173-184

apps/standalone/src/app/routes.tsx (1)

27-27: LGTM!

The /login route is correctly positioned before the main application routes and renders the LoginPage component outside the authenticated AppLayout, which is appropriate for a login flow.

Also applies to: 345-348

libs/i18n/locales/en/translation.json (1)

16-27: LGTM!

The translation keys provide clear, user-friendly messaging for the Kubernetes token authentication flow, including helpful guidance, validation feedback, and security warnings.

apps/standalone/src/app/components/Login/LoginPage.tsx (3)

33-40: LGTM!

The JWT format validation correctly checks for three dot-separated parts using the base64url character set, providing appropriate client-side validation before submission.


49-88: LGTM!

The submission handler correctly clears previous state, sends the token to the backend, handles success/error responses, stores expiration data, and redirects on successful authentication.


90-174: LGTM!

The LoginPage UI provides clear instructions, appropriate security warnings, live validation feedback, and proper form state management with disabled states during submission.

Comment thread proxy/auth/k8s.go
Comment thread proxy/auth/k8s.go Outdated
}}

// Call a basic API endpoint to validate the token
validateUrl := config.FctlApiUrl + "/api/v1/fleets?limit=1"

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Is there a better way for the UI to validate the token is accepted on the API side?
cc @asafbennatan @fzdarsky

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

/api/v1/auth/validate

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Totally missed it, thanks!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
proxy/auth/k8s.go (2)

70-83: Status code validation correctly fixed.

The validation now properly restricts to 2xx responses only, addressing the previous review concern.

Optional optimization: the extractTokenExpiration call at line 81 duplicates work from the earlier auth failure check. You could cache the result if you want to avoid re-parsing the token, though the performance impact is minimal.


189-216: Consider a more idiomatic error handling approach.

The method creates synthetic http.Response objects (lines 199-203, 211-213) rather than actual HTTP responses. While this may be for consistency with other authentication provider interfaces, it's somewhat unconventional and could be confusing since *http.Response typically represents actual server responses.

If this pattern is required for interface compatibility with OAuth providers, it's acceptable. Otherwise, consider using custom error types or status codes in the error message rather than fabricating Response objects.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c9ed16 and 5d0ea1e.

📒 Files selected for processing (2)
  • apps/standalone/src/app/components/Login/LoginPage.tsx (1 hunks)
  • proxy/auth/k8s.go (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 371
File: libs/types/models/AppType.ts:10-10
Timestamp: 2025-10-29T16:47:29.614Z
Learning: PR #371 (flightctl/flightctl-ui) adds the AppTypeQuadlet enum member and related types as a preparatory change. Full implementation of quadlet application support in the UI will be added later, after backend support is available.
📚 Learning: 2025-09-17T12:24:09.201Z
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 346
File: libs/ui-components/src/components/common/OrganizationGuard.tsx:54-62
Timestamp: 2025-09-17T12:24:09.201Z
Learning: In the Flight Control UI proxy, organization feature detection uses a 501 (Not Implemented) status code to explicitly signal when organizations are disabled via the ORGANIZATIONS_ENABLED setting. Any other status code (including errors like 404, 500) should be treated as organizations being enabled. The logic `organizationsEnabled = response.status !== 501` is correct and more resilient than checking `response.ok`.

Applied to files:

  • proxy/auth/k8s.go
🧬 Code graph analysis (2)
proxy/auth/k8s.go (4)
proxy/auth/common.go (2)
  • LoginParameters (24-26)
  • TokenData (18-22)
proxy/config/config.go (1)
  • FctlApiUrl (10-10)
proxy/log/log.go (1)
  • GetLogger (17-19)
proxy/bridge/common.go (1)
  • GetTlsConfig (13-38)
apps/standalone/src/app/components/Login/LoginPage.tsx (3)
libs/ui-components/src/hooks/useTranslation.ts (1)
  • useTranslation (5-8)
libs/ui-components/src/utils/organizationStorage.ts (1)
  • ORGANIZATION_STORAGE_KEY (1-1)
apps/standalone/src/app/utils/apiCalls.ts (1)
  • loginAPI (17-17)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: integration-tests
  • GitHub Check: Lint
  • GitHub Check: Build ocp plugin
  • GitHub Check: Build
🔇 Additional comments (13)
apps/standalone/src/app/components/Login/LoginPage.tsx (4)

1-26: LGTM!

Imports are well-organized and all necessary dependencies are properly included.


33-40: LGTM!

The JWT format validation is appropriately scoped for client-side validation. The three-part structure check and base64url character validation ([A-Za-z0-9_-]) will catch obvious malformed tokens before submission, while the backend will perform full cryptographic validation.


49-88: LGTM!

The submission flow is well-structured with proper error handling:

  • Clears stale data before authentication
  • Handles both HTTP errors and network failures
  • Defensively checks for expiresIn before storing expiration
  • Provides user-friendly error messages

90-173: LGTM!

The UI implementation follows PatternFly best practices with:

  • Live validation feedback as users type
  • Clear error messaging for both validation and authentication failures
  • Appropriate loading states and button disable logic
  • Security warning to remind users about token sensitivity
  • Proper i18n integration throughout
proxy/auth/k8s.go (9)

1-31: LGTM!

The package structure, imports, and type definitions are clean and well-organized. The TokenAuthProvider properly encapsulates TLS configuration for secure API communication.


33-36: LGTM!

Correctly indicates that token authentication does not use OAuth code flow.


85-120: LGTM!

The expiration extraction logic is robust:

  • Handles multiple numeric types for the exp claim
  • Properly calculates seconds until expiration
  • Returns 0 for expired tokens (when expiration is in the past)
  • Returns nil when no expiration claim exists

122-143: LGTM!

The JWT claims extraction is implemented correctly:

  • Validates three-part structure
  • Uses base64.RawURLEncoding which is the correct encoding for JWT (base64url without padding)
  • Provides clear error messages for debugging

145-172: LGTM!

The username extraction implements a thoughtful fallback chain for Kubernetes service account tokens:

  1. Modern nested claim structure (kubernetes.io.serviceaccount.name)
  2. Legacy flat claim format
  3. Standard sub claim with intelligent parsing to extract just the service account name from the full system:serviceaccount:namespace:name format

This ensures compatibility across different Kubernetes versions and token formats.


174-187: LGTM!

Clean public API that composes the internal claim extraction functions with clear error handling.


218-232: LGTM!

These methods correctly indicate that OAuth-specific operations (refresh, login redirect) are not applicable for static token authentication. The Logout method appropriately returns success with no action needed (token invalidation happens client-side by discarding the token).


234-248: LGTM!

The factory function properly initializes the TokenAuthProvider with TLS configuration and supports both external and internal auth URLs.


61-68: Potential nil pointer dereference.

Line 64 dereferences expiresIn without checking if it's nil. If extractTokenExpiration returns nil (which it does when the token has no expiration claim or parsing fails), dereferencing it will panic.

Apply this diff to safely check for expired tokens:

 	if resp.StatusCode == http.StatusUnauthorized || resp.StatusCode == http.StatusForbidden {
 		// Check if the token is expired by examining the exp claim
 		expiresIn := extractTokenExpiration(token)
-		if expiresIn != nil && *expiresIn == 0 {
+		if expiresIn != nil && *expiresIn <= 0 {
 			return TokenData{}, nil, fmt.Errorf("Token has expired")
 		}
 		return TokenData{}, nil, fmt.Errorf("Token is invalid or unauthorized")
 	}

Note: Changed == 0 to <= 0 to handle any negative values that might slip through (defense in depth).

⛔ Skipped due to learnings
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 357
File: proxy/auth/auth.go:228-237
Timestamp: 2025-10-21T13:53:29.934Z
Learning: In proxy/auth/auth.go, the token cleanup cycles in `startTokenCleanup` and `cleanupExpiredTokens` are designed for memory management of unretrieved tokens, not as a primary security control. The single-use deletion in `getSingleUseApiTokenMapping` provides the security guarantee. TTL enforcement on retrieval is intentionally not implemented because tokens are expected to be retrieved immediately after creation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/standalone/src/app/context/AuthContext.ts (1)

37-41: Consider extracting the login path to a constant.

The /login path is hard-coded in three locations (lines 38, 84, and 110). Extracting it to a constant would improve maintainability if the path needs to change in the future.

For example, at the top of the file:

+const LOGIN_PATH = '/login';
+
 const AUTH_DISABLED_STATUS_CODE = 418;

Then use LOGIN_PATH in the comparisons:

-if (window.location.pathname === '/login') {
+if (window.location.pathname === LOGIN_PATH) {

Also applies to: 83-86, 109-112

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5d0ea1e and 166bfb8.

📒 Files selected for processing (3)
  • apps/standalone/src/app/context/AuthContext.ts (3 hunks)
  • apps/standalone/src/app/utils/apiCalls.ts (2 hunks)
  • proxy/auth/auth.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/standalone/src/app/utils/apiCalls.ts
  • proxy/auth/auth.go
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 371
File: libs/types/models/AppType.ts:10-10
Timestamp: 2025-10-29T16:47:29.614Z
Learning: PR #371 (flightctl/flightctl-ui) adds the AppTypeQuadlet enum member and related types as a preparatory change. Full implementation of quadlet application support in the UI will be added later, after backend support is available.
🧬 Code graph analysis (1)
apps/standalone/src/app/context/AuthContext.ts (1)
apps/standalone/src/app/utils/apiCalls.ts (1)
  • redirectToLogin (58-64)
🔇 Additional comments (3)
apps/standalone/src/app/context/AuthContext.ts (3)

37-41: LGTM! Prevents unnecessary auth check on login page.

The early return correctly skips authentication checks when the user is on the login page, avoiding an unnecessary API call that would result in a 401 response. Setting loading to false ensures the UI doesn't remain in a loading state.


83-86: LGTM! Valid defensive check after async operation.

The guard against redirecting when already on /login is appropriate here, even though there's an early return at line 38. Since this check occurs after the async fetch operation (lines 74-76), the pathname could theoretically change during that time, making this a valid defensive re-check that prevents redirect loops.


109-112: LGTM! Prevents token refresh scheduling on login page.

The guard correctly prevents scheduling token refresh operations when the user is on the login page, where such operations are not needed. This works well with the loading state management in the first effect.


// Redirect to home page after successful login
window.location.href = '/';
} catch (err) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I wonder if we should show the error somewhere ? Otherwise it will be really hard to debug

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I'll do.
In the full branch the UI proxy returns different error messages and the UI shows them, but it's also worth having it here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Added the invalid/expired token. Will address more use cases if needed in the full branch.

Comment thread proxy/auth/k8s.go Outdated
}}

// Call a basic API endpoint to validate the token
validateUrl := config.FctlApiUrl + "/api/v1/fleets?limit=1"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

/api/v1/auth/validate

Comment thread proxy/auth/k8s.go Outdated
}

// extractJwtTokenClaims extracts the claims from a JWT token
func extractJwtTokenClaims(token string) (map[string]interface{}, error) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we could use github.com/lestrrat-go/jwx for handling the JWT tokens

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
proxy/auth/k8s.go (1)

178-185: Consider extracting token expiration check to reduce duplication.

The token expiration check logic appears in both ValidateToken (lines 62-65) and GetUserInfo (lines 179-185). While not critical, extracting this to a helper function could improve maintainability.

Example helper function:

// checkTokenExpired returns an error if the token is expired
func checkTokenExpired(token string) error {
	expiresIn := extractTokenExpiration(token)
	if expiresIn != nil && *expiresIn == 0 {
		return fmt.Errorf("token has expired")
	}
	return nil
}

Then use in both methods:

-	expiresIn := extractTokenExpiration(token)
-	if expiresIn != nil && *expiresIn == 0 {
-		return TokenData{}, nil, fmt.Errorf("Token has expired")
-	}
+	if err := checkTokenExpired(token); err != nil {
+		return TokenData{}, nil, err
+	}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 166bfb8 and d1dbc8f.

⛔ Files ignored due to path filters (1)
  • proxy/go.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • proxy/auth/k8s.go (1 hunks)
  • proxy/go.mod (2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 371
File: libs/types/models/AppType.ts:10-10
Timestamp: 2025-10-29T16:47:29.614Z
Learning: PR #371 (flightctl/flightctl-ui) adds the AppTypeQuadlet enum member and related types as a preparatory change. Full implementation of quadlet application support in the UI will be added later, after backend support is available.
📚 Learning: 2025-09-17T12:24:09.201Z
Learnt from: celdrake
Repo: flightctl/flightctl-ui PR: 346
File: libs/ui-components/src/components/common/OrganizationGuard.tsx:54-62
Timestamp: 2025-09-17T12:24:09.201Z
Learning: In the Flight Control UI proxy, organization feature detection uses a 501 (Not Implemented) status code to explicitly signal when organizations are disabled via the ORGANIZATIONS_ENABLED setting. Any other status code (including errors like 404, 500) should be treated as organizations being enabled. The logic `organizationsEnabled = response.status !== 501` is correct and more resilient than checking `response.ok`.

Applied to files:

  • proxy/auth/k8s.go
🧬 Code graph analysis (1)
proxy/auth/k8s.go (4)
proxy/auth/common.go (2)
  • LoginParameters (24-26)
  • TokenData (18-22)
proxy/config/config.go (1)
  • FctlApiUrl (10-10)
proxy/log/log.go (1)
  • GetLogger (17-19)
proxy/bridge/common.go (1)
  • GetTlsConfig (13-38)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: integration-tests
  • GitHub Check: Build
  • GitHub Check: Lint
  • GitHub Check: Build ocp plugin
🔇 Additional comments (1)
proxy/auth/k8s.go (1)

1-230: Well-implemented token authentication provider.

The k8s token authentication implementation is well-structured and properly handles JWT token validation and claim extraction. The use of the /api/v1/auth/validate endpoint and the status code validation logic align with previous review feedback. The multiple fallback strategies for username extraction ensure compatibility with various k8s token formats.

Comment thread proxy/go.mod Outdated
@celdrake celdrake force-pushed the temp-k8s-static-auth branch from d1dbc8f to cb4340f Compare November 13, 2025 08:46
@celdrake celdrake requested a review from rawagner November 13, 2025 08:47
@celdrake celdrake force-pushed the temp-k8s-static-auth branch from cb4340f to c2f27d6 Compare November 13, 2025 11:09
@celdrake celdrake force-pushed the temp-k8s-static-auth branch from c2f27d6 to 2d3fdb1 Compare November 13, 2025 11:14
@celdrake celdrake mentioned this pull request Nov 13, 2025
@celdrake celdrake merged commit ce054d1 into flightctl:main Nov 13, 2025
6 checks passed
@celdrake celdrake deleted the temp-k8s-static-auth branch November 13, 2025 11:46
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