Skip to content

[Feature]: API Key -> JWT Exchange #33

Description

@alexlovelltroy

Describe the feature

Support exchanging user-managed tokens (passed via X-Token header) for short-lived JWTs, matching token-service's primary authentication flow.

This addition is needed to support tokensmith in a wormhole context and is a companion for #32

In wormhole, the standard jwt exchange url is GET /token/jwt.

The same functionality is more common as an extension to the oauth 2.0 standard (RFC 6749 4.5 Extension Grant Mechanism) with a custom grant type. We may be able to extend our RFC 8693 featureset to deliver the same functionality using POST /oauth/token if the wormhole clients can leverage it. Supporting both during transition would be fairly trivial.

Request Format

Headers:

Content-Type: application/x-www-form-urlencoded

Body Parameters:

grant_type=urn:x-oath:params:oauth:grant-type:api-key
&subject_token={id}.{value}
&subject_token_type=urn:x-oath:params:oauth:token-type:api-key
&scope=read write
&resource=https://backend.example.com/api

Alternative (Simpler):

grant_type=api_key
&api_key={id}.{value}
&scope=read write

Response Format (Standard OAuth 2.0)

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6InRodW1icHJpbnQifQ...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "read write",
  "issued_token_type": "urn:ietf:params:oauth:token-type:jwt"
}
sequenceDiagram
    participant Client as CLI/Service
    participant Tokensmith as TokenSmith (STS)
    participant DB as Token Database
    participant Backend as Backend API

    Client->>Tokensmith: POST /oauth/token<br/>grant_type=api_key<br/>api_key={id}.{value}
    Tokensmith->>DB: Lookup token by ID<br/>Verify bcrypt(value)
    DB-->>Tokensmith: Token valid, load user + scopes
    Tokensmith->>Tokensmith: Issue JWT (1h TTL)<br/>claims: sub, scopes, groups
    Tokensmith-->>Client: 200 OK<br/>{"access_token": "eyJ...", "expires_in": 3600}
    
    Client->>Backend: GET /api/resource<br/>Authorization: Bearer eyJ...
    Backend->>Backend: Verify JWT signature (JWKS)<br/>Check exp, scopes, groups
    Backend-->>Client: 200 OK + data
Loading

Why do you want this feature?

Token-Service Pattern:

# User creates long-lived API key
curl -X POST https://token-service/token \
  -H "Cookie: session=..." \
  -d "name=my-api-key&scopes=read,write"
# Returns: {"id": 1, "value": "MQ==.dGVzdF90b2tlbl92YWx1ZV9oZXJl"}

# Later: Exchange API key for JWT
curl https://token-service/token/jwt \
  -H "X-Token: MQ==.dGVzdF90b2tlbl92YWx1ZV9oZXJl"
# Returns: {"access_token": "eyJhbGc...", "token_type": "Bearer", "expires_in": 3600}

Tokensmith Gap: No endpoint for X-Token → JWT exchange. Only supports RFC 8693 bootstrap token exchange.

Alternatives you've considered

I considered doing...

Additional context

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions