Skip to content

feat(guard-identity): add identity guard for unvalidated bearer pass-through#1794

Merged
jfallows merged 2 commits into
developfrom
claude/feat-guard-identity
May 23, 2026
Merged

feat(guard-identity): add identity guard for unvalidated bearer pass-through#1794
jfallows merged 2 commits into
developfrom
claude/feat-guard-identity

Conversation

@jfallows
Copy link
Copy Markdown
Contributor

Summary

Adds a new identity guard that captures the inbound credentials string verbatim and re-emits it via GuardHandler.credentials(sessionId). No validation, no options.

Useful when Zilla is chaining a bearer token to an upstream that performs its own validation:

  • MCP proxies forwarding GitHub PATs to github-mcp-server
  • Internal API gateways trusting an upstream IdP
  • Sidecar / mesh patterns where the gateway is behind a verified perimeter

The current shipped guard (guard-jwt) validates JWT format on capture, so it cannot carry opaque tokens. identity fills that gap without introducing new SPI surface — it implements the existing GuardHandler contract (reauthorize / credentials / deauthorize) and integrates with any binding that supports options.authorization.name, including binding-mcp and binding-http.

Behavior

  • reauthorize(credentials) — interns credentials as the session's identity; returns an auto-generated authorized session id
  • credentials(sessionId) — returns the stored identity verbatim
  • identity(sessionId) — same string (these are the same value for this guard)
  • Sessions are shared per (context, identity) and ref-counted; null credentials produce fresh non-shared sessions
  • expiresAt / expiringAtEXPIRES_NEVER; challengefalse; no preauthorize
  • Schema rejects any options block — the guard is configuration-free (type: identity only)

Usage example

guards:
  passthrough:
    type: identity
bindings:
  north_http_server:
    type: http
    kind: server
    options:
      authorization:
        passthrough:
          credentials:
            headers:
              authorization: Bearer {credentials}
    routes:
      - exit: app
  app_client:
    type: mcp
    kind: client
    options:
      authorization:
        name: passthrough
    routes:
      - exit: net
        with:
          headers:
            :scheme: https
            :authority: upstream.example.com
            :path: /mcp

The client's Authorization: Bearer … header is captured at north_http_server, propagated through the stream's authorization id, and re-stamped on the outbound request from app_client to the upstream.

Test plan

  • ./mvnw checkstyle:check -pl runtime/guard-identity,specs/guard-identity.spec -am — clean
  • ./mvnw clean install -pl runtime/guard-identity,specs/guard-identity.spec — passes including ITs and jacoco coverage check (0.82 ratio)
  • IdentityGuardFactoryTest — factory smoke test
  • IdentityGuardTest — handler unit tests covering capture/return/refcount, shared-vs-fresh session semantics
  • IdentityIT — k3po-driven binding integration test exercising the guard via engine spec network/application scripts
  • SchemaTest — validates a minimal type: identity config against the patched schema

Generated by Claude Code

…through

Adds a guard that captures the inbound credentials string verbatim
and returns it via GuardHandler.credentials(sessionId). Useful when
Zilla is chaining a bearer to an upstream that performs its own
validation (e.g. proxying GitHub PATs to github-mcp-server, sidecars
trusting an upstream IdP, internal gateways behind a verified perimeter).

The guard takes no options. Schema rejects any options block. Sessions
are shared per (context, identity) and ref-counted; null credentials
produce fresh non-shared sessions.

- runtime/guard-identity: IdentityGuard, IdentityGuardContext,
  IdentityGuardHandler, IdentityGuardFactorySpi, plus unit tests
  (factory, handler) and an integration test driven by engine spec
  network/application scripts
- specs/guard-identity.spec: identity.schema.patch.json adds the
  "identity" guard type with options: false, additionalProperties: false;
  SchemaTest validates a minimal positive config
@jfallows jfallows self-assigned this May 23, 2026
Adds guard-identity to cloud/docker-image/pom.xml and zpm.json.template
so the SPI registration is included in ghcr.io/aklivity/zilla images
alongside guard-jwt. Without these entries, type: identity would not
resolve in deployments using the official image.
Copy link
Copy Markdown
Contributor Author

@jfallows jfallows left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jfallows jfallows merged commit b6a9f58 into develop May 23, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants