Skip to content

Commit 6f4c2d1

Browse files
gabemonteroclaude
andcommitted
docs(boost): clarify X-Backstage-User scope in auth specs
X-Backstage-User header only applies to user-initiated requests via KagentiApiClient (chat, agent operations), not entity provider background polling which has no user context. Updated access-control spec, security design doc, and boost-context to make this distinction explicit. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: gabemontero <gmontero@redhat.com>
1 parent 6b33811 commit 6f4c2d1

4 files changed

Lines changed: 9 additions & 7 deletions

File tree

workspaces/boost/openspec/changes/security-safety-governance/design.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ The `IS_NOT_CREATOR` permission rule is the primary enforcement mechanism. A rou
4242

4343
### Decision 4: Service-account auth with KeycloakAuthClient
4444

45-
`KeycloakAuthClient` acquires tokens via OAuth2 Client Credentials Grant, caches them with a configurable expiry buffer (`tokenExpiryBufferSeconds`, default: 60), and automatically refreshes before expiry. On 401 responses, the token is refreshed and the request retried once (max-1-retry). User identity is propagated via `X-Backstage-User` header for audit trails. This is deliberately simple: service-account auth provides consistent authentication without per-user token management complexity.
45+
`KeycloakAuthClient` acquires tokens via OAuth2 Client Credentials Grant, caches them with a configurable expiry buffer (`tokenExpiryBufferSeconds`, default: 60), and automatically refreshes before expiry. On 401 responses, the token is refreshed and the request retried once (max-1-retry). For user-initiated requests via `KagentiApiClient`, user identity is propagated via `X-Backstage-User` header for audit trails; entity provider background polling omits this header (no user context). This is deliberately simple: service-account auth provides consistent authentication without per-user token management complexity.
4646

4747
### Decision 5: Separation of authorization concerns
4848

workspaces/boost/openspec/changes/security-safety-governance/specs/access-control/spec.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ Inference responses are not stored on the server when ZDR is enabled.
8383

8484
### Requirement: Service-Account Keycloak Authentication for Kagenti
8585

86-
Kagenti API calls MUST be authenticated via OAuth2 Client Credentials Grant using `KeycloakAuthClient` for service-account authentication. User identity is propagated via the `X-Backstage-User` header for audit purposes.
86+
Kagenti API calls MUST be authenticated via OAuth2 Client Credentials Grant using `KeycloakAuthClient` for service-account authentication. For user-initiated requests (chat, agent operations via `KagentiApiClient`), user identity is propagated via the `X-Backstage-User` header for audit purposes. Entity provider background polling has no user context and omits this header.
8787

8888
#### Scenario: Token acquisition
8989

@@ -105,11 +105,12 @@ Kagenti API calls MUST be authenticated via OAuth2 Client Credentials Grant usin
105105
- **AND** the request is retried with the new token
106106
- **AND** if the retried request also returns 401, the error is propagated to the caller
107107

108-
#### Scenario: User identity propagation
108+
#### Scenario: User identity propagation (KagentiApiClient only)
109109

110-
- **WHEN** a Kagenti API call is made on behalf of a user
111-
- **THEN** the `X-Backstage-User` header is set to the user's identity
110+
- **WHEN** a user-initiated Kagenti API call is made via `KagentiApiClient` (chat, agent operations)
111+
- **THEN** the `X-Backstage-User` header is set to the user's Backstage identity
112112
- **AND** the service-account bearer token is used for authentication (not the user's token)
113+
- **AND** entity provider background polling omits this header (no user context available)
113114

114115
#### Scenario: Service-account auth configuration
115116

workspaces/boost/specifications/boost-context.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ _Augment lesson: Pivoted from 5-stage to 4-stage model mid-development, requirin
105105

106106
### 10. Service-Account Keycloak Authentication
107107

108-
Kagenti authentication uses OAuth2 Client Credentials Grant via `KeycloakAuthClient` for service-account authentication from the start. The token manager handles token acquisition, caching with configurable expiry buffer, and automatic refresh. User identity is propagated via the `X-Backstage-User` header for audit purposes.
108+
Kagenti authentication uses OAuth2 Client Credentials Grant via `KeycloakAuthClient` for service-account authentication from the start. The token manager handles token acquisition, caching with configurable expiry buffer, and automatic refresh. For user-initiated requests via `KagentiApiClient`, user identity is propagated via the `X-Backstage-User` header for audit purposes; entity provider background polling omits this header.
109109

110110
_Augment lesson: All Kagenti requests used a shared service-account token. `X-Backstage-User` header was informational only. Per-user audit trail impossible at the provider level._
111111

workspaces/boost/staged-issues.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -508,7 +508,7 @@ https://github.com/redhat-developer/rhdh-plugins/issues/3654
508508
**Labels:** `ready-to-code`
509509
**Depends on:** Issue 13 (#3309)
510510

511-
Refactor `KeycloakAuthClient` in `kagenti-entity-provider` to use Backstage `cacheService` for token caching instead of private instance fields. Aligns with design principle 1 and the PRD cache migration table.
511+
Refactor `KeycloakAuthClient` in `kagenti-entity-provider` to use Backstage `cacheService` for token caching instead of private instance fields, and add HTTPS validation for `tokenEndpoint`. Aligns with design principle 1 and the PRD cache migration table.
512512

513513
### Tasks
514514

@@ -518,6 +518,7 @@ Refactor `KeycloakAuthClient` in `kagenti-entity-provider` to use Backstage `cac
518518
- 17.4 Update `module.ts` to pass `cache` (with namespace) to `KeycloakAuthClient`
519519
- 17.5 Update tests to mock `cacheService` instead of relying on in-memory state
520520
- 17.6 Consider extracting `KeycloakAuthClient` to a shared location (e.g., `boost-node`) so `boost-backend-module-kagenti` can reuse it for task 7.5b
521+
- 17.7 Add HTTPS validation for `tokenEndpoint` in `KeycloakAuthClient` constructor — reject HTTP URLs unless security mode is `development-only-no-auth`
521522

522523
### Specifications
523524

0 commit comments

Comments
 (0)