Skip to content

[BE-59] Implement API Keys — generate and manage long-lived keys for external integrations #932

Description

@yusuftomilola

Overview

Third-party integrations and automation scripts need a stable, long-lived credential that doesn't require user login. An API key system provides this as an alternative to JWT tokens. Enables FE-26 (Developer portal API key management UI).

Context

  • API keys should be scoped (read-only vs full access) so integrations only get the permissions they need
  • Only the raw key is shown at creation time — the stored value is a bcrypt hash (like a password)
  • The key is passed via Authorization: Bearer ak_<key> header — the JwtStrategy detects the ak_ prefix and validates via ApiKeyStrategy instead

Acceptance Criteria

  • Create ApiKey entity: id, userId, name, keyHash (bcrypt hash of the raw key), prefix (first 8 chars, shown in list for identification), scopes (text array: ['read:assets', 'write:assets', 'read:reports', ...]), lastUsedAt, expiresAt (nullable), isActive, createdAt
  • POST /api-keys body: { name, scopes, expiresAt? } — generates a crypto.randomBytes(32).toString('hex') key, returns it once in the response, stores only the hash
  • GET /api-keys — list user's keys showing prefix, name, scopes, lastUsedAt (never the full key)
  • DELETE /api-keys/:id — revokes key immediately
  • Create ApiKeyStrategy for Passport — validates ak_ prefixed bearer tokens against stored hashes, updates lastUsedAt
  • Update JwtAuthGuard to support both JWT and API key authentication

Metadata

Metadata

Assignees

Labels

Type

No type
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