stacklok / stacklok/toolhive

Integrate SPIFFE principals with OAuth grants and discovery

Open
#6,204 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

authentication authorization enhancement go
Dominant language
Go
Stars
2.2k
Forks
300
Avg merge
1d 15h
Merged PRs (30d)
184

Description

Description

Make both SPIFFE authentication methods produce equivalent OAuth behaviour:
client_credentials tokens whose subject is the workload, RFC 8693 delegation
with the workload as actor, and discovery metadata that advertises exactly the
methods actually available.

This is where the epic's central guarantee is either enforced or quietly lost.
Two credentials for the same SPIFFE ID must yield the same sub, the same
act, the same scopes, audiences, expiry and Cedar inputs. The authentication
method is an audit fact, not an authorization input.

Scope

  • Make client_credentials issue tokens whose subject is the associated SPIFFE
    ID.
  • Make RFC 8693 token exchange use the authenticated SPIFFE principal as
    act.sub.
  • Bind an optional actor token to that same principal.
  • Require explicit client authorization for both client_credentials and token
    exchange.
  • Require and authorize the target MCP resource.
  • Constrain requested scopes and resources by both workload policy and
    source-token authority, whichever is narrower.
  • Add spiffe_x509 and spiffe_jwt to the dynamic discovery-metadata
    mechanism.
  • Record the authentication method for audit without letting it change
    authorization semantics.

What belongs to other issues

This sub-issue has more external dependencies than any other, and its scope is
easy to over-draw. Three pieces are explicitly not to be built here:

  • Actor-token parsing and the id_token subject type belong to #5815.
    Require the binding to the authenticated workload principal here; do not
    re-specify the mechanism.
  • Making discovery metadata dynamic at all is #6082's second blocker:
    discovery currently publishes grant_types_supported: [authorization_code, refresh_token] and token_endpoint_auth_methods_supported: ["none"], so any
    metadata-driven client refuses to attempt the grant regardless of what is
    configured. That fix is shared with the pre-provisioned-client option. Extend
    it with two method names; do not fork it.
  • The external-issuer delegation-consent policy is #6149 / #5989. Note that
    its allowed_delegate_clients field is optional today only because no stable
    confidential client ID can be created. SPIFFE makes the client ID equal to the
    SPIFFE ID, so this work is part of what lets that field become required — or
    better, lets the invariant be enforced from the other side, so every ID named
    must resolve to a declared client. A typo currently reverts silently to
    permissive behaviour.

Acceptance criteria

  • X.509-SVID and JWT-SVID authentication for the same SPIFFE ID produce
    equivalent sub, act, scopes, audiences, expiry and Cedar inputs.
  • Public clients cannot use client_credentials or token exchange.
  • Token exchange is unavailable without an explicitly permitted confidential
    client association.
  • An actor token, when supplied, must be bound to the authenticated workload
    principal.
  • Requested scope and resource cannot exceed workload entitlement or
    source-token authorization.
  • Discovery advertises exactly spiffe_x509, spiffe_jwt, or both, according
    to operational configuration — never an unavailable method.
  • Existing secret-authenticated confidential clients continue to use only their
    registered grants.
  • Public-only deployments' discovery metadata stays byte-identical.

Dependencies

Do not start this until the discovery-metadata and consent pieces have landed or
been explicitly claimed.

  • Sub-issues 3 and 4 (both authentication methods)
  • #6082 blocker 2 — dynamic discovery metadata
  • #6149 / #5989 — delegation consent for external subject tokens
  • #5815 — explicit actor_token and id_token subject type

Related

  • Part of the SPIFFE client-authentication epic
  • #5194 (RFC 8693 token exchange)

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the SPIFFE authentication sub-issues, #6082, #6149/#5989, and #5815; the issue does not name implementation files or tests. Trace the client_credentials and RFC 8693 grant entry points and dynamic discovery configuration. Done means equivalent X.509-SVID and JWT-SVID OAuth outputs, enforced client and resource authorization, and discovery metadata matching configured methods without changing public-only deployments.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
api, authentication, authorization, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.