Skip to content

kagenti-entity-provider: Migrate KeycloakAuthClient to Backstage cacheService (issue 17 after 15) #3654

Description

@gabemontero

Labels: ready-to-code
Depends on: Issue 13 (#3309)

Refactor KeycloakAuthClient in boost-node to use Backstage cacheService for token caching instead of private instance fields, and add HTTPS validation for tokenEndpoint. This aligns with boost design principle 1 ("All operational caches use Backstage cacheService") and the PRD cache migration table which lists KeycloakAuthClient as P1 for cacheService migration.

Context

PR #3661 extracted KeycloakAuthClient from kagenti-entity-provider and boost-backend-module-kagenti into boost-node as a shared implementation. The current implementation uses in-memory token caching (private cachedToken and tokenExpiresAt fields) with in-flight deduplication. This works correctly but deviates from the architectural principle that all operational caches use cacheService.

The boost-backend-module-kagenti package already has a KeycloakTokenCache class wrapping cacheService. The refactored KeycloakAuthClient should compose with this pattern rather than duplicating it.

Additionally, KeycloakAuthClient.getBearerToken() sends clientId:clientSecret as a Basic auth header to tokenEndpoint without validating the URL scheme is HTTPS. The Zod schema validates URL format (z.string().url()) but not HTTPS. In production, sending credentials over HTTP exposes them in transit.

Tasks

  • 17.6 Extract KeycloakAuthClient to boost-node so both boost-backend-module-kagenti and kagenti-entity-provider share one implementation (done in PR feat(#3309): add Kagenti auth, 401 retry, and user header #3661)
  • 17.1 Add coreServices.cache to the kagenti-entity-provider module deps
  • 17.2 Refactor KeycloakAuthClient constructor to accept a CacheService instance
  • 17.3 Replace private cachedToken/tokenExpiresAt fields with cacheService.get()/cacheService.set() using TTL derived from token expiry minus buffer
  • 17.4 Update module.ts to pass cache (with namespace) to KeycloakAuthClient
  • 17.5 Update tests to mock cacheService instead of relying on in-memory state
  • 17.7 Add HTTPS validation for tokenEndpoint in KeycloakAuthClient constructor — reject HTTP URLs unless security mode is development-only-no-auth
  • 17.8 Remove KeycloakTokenCache and its test from boost-backend-module-kagenti — it becomes redundant once KeycloakAuthClient uses cacheService directly. Also remove the void keycloakTokenCache placeholder in module.ts.
  • 17.9 Remove stale task-number references in KagentiProviderFactory JSDoc (references "task 3.3, 3.4, 3.7" from an older numbering scheme)

Specifications

  • specifications/boost-context.md — Design Principle 1 (Backstage cacheService from Day One)
  • specifications/prd/pluggable-ai-platform-architecture.md — Cache migration table (KeycloakAuthClient row)
  • openspec/changes/security-safety-governance/specs/access-control/spec.md — Service-account auth scenarios
  • openspec/changes/platform-operations-deployment/specs/cache-migration/spec.md

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions