Skip to content

feat: Add scope forwarding to go-processor for per-user access control #139

Description

@mrsabath

Summary

The go-processor (AuthProxy ext_proc) currently uses a static TARGET_SCOPES environment variable for all outbound token exchanges. This means every exchanged token gets the same set of scopes regardless of what scopes the original user token contained.

For scope-based access control to work (e.g., Alice with public access vs Bob with privileged access), the go-processor must forward the original token's scopes through the token exchange, not use a fixed set.

Current Behavior

  1. TARGET_SCOPES is set in the authbridge-config ConfigMap (e.g., "openid github-tool-aud github-full-access")
  2. When any user's request reaches the agent, AuthBridge exchanges the token using the static TARGET_SCOPES
  3. The exchanged token always contains github-full-access, even if the original user (e.g., Alice) did not have that scope
  4. The downstream tool always sees github-full-access and uses the privileged PAT for all users

Expected Behavior

The go-processor should extract the scope claim from the incoming JWT (subject token) and intersect it with TARGET_SCOPES before making the token exchange request:

  • If the incoming token has scope: "openid email profile" and TARGET_SCOPES is "openid github-tool-aud github-full-access", the exchange should request scope=openid github-tool-aud (intersection, plus required scopes like github-tool-aud)
  • If the incoming token has scope: "openid email profile github-full-access", the exchange should request scope=openid github-tool-aud github-full-access

This preserves per-user scope differentiation through the exchange.

Proposed Implementation

Add a new configuration option to go-processor:

  • SCOPE_FORWARDING (env var, default: "disabled")
    • "disabled" — current behavior: use static TARGET_SCOPES for all exchanges
    • "intersect" — extract scopes from subject token, intersect with TARGET_SCOPES
    • "forward" — extract scopes from subject token, merge with TARGET_SCOPES

Implementation in handleOutbound():

  1. Parse the incoming JWT's scope claim (decode without full validation — the token was already validated inbound)
  2. Split into a set of scopes
  3. Apply the selected strategy (intersect or forward) with TARGET_SCOPES
  4. Pass the resulting scope set to exchangeToken()

Use Case

The GitHub Issue Agent demo Step 10 shows two users:

  • Alice gets a token without github-full-access — should result in PUBLIC_ACCESS_PAT at the tool
  • Bob gets a token with github-full-access — should result in PRIVILEGED_ACCESS_PAT at the tool

Without scope forwarding, both users get github-full-access in the exchanged token because TARGET_SCOPES is static.

Affected Files

  • AuthBridge/AuthProxy/go-processor/main.gohandleOutbound() and loadConfig()
  • AuthBridge/demos/github-issue/k8s/configmaps.yaml — add SCOPE_FORWARDING: "intersect" to authbridge-config

Metadata

Metadata

Assignees

Type

No type

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions