Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Demo: RFC 8693 OBO token exchange with HBAC

Location: contrib/demo/obo/

Demonstrates ahdapa’s full RFC 8693 On-Behalf-Of (OBO) token exchange flow with HBAC policy enforcement, actor token validation, act claim chains, and delegation target guards. Runs on a single node over plain HTTP with SQLite and static users — no Kerberos, LDAP, or TLS setup required.

What it shows

  1. Basic OBO with act claim chain — A pipeline agent performs token exchange on behalf of a frontend service. The issued JWT carries an act claim with sub set to the agent’s client_id and workload_type set from the agent’s registered client profile.

  2. Delegation target guard — The HBAC rule restricts which Kerberos service principals the agent may delegate to (delegation_targets). A request with the matching target_service is allowed; a request with a non-matching SPN is denied with access_denied.

  3. OBO actor gate — Clients must have allow_token_exchange_actor = true to supply an actor_token. A rogue service without this flag receives access_denied immediately, before HBAC evaluation.

  4. Three-way scope narrowing — The granted scope is the intersection of the requested scopes, the subject token’s scopes, and the acting client’s registered scopes. Requesting a scope the agent is not registered for yields invalid_scope.

  5. HBAC client-axis deny — The HBAC rule’s clients list includes only the pipeline agent. A service that omits actor_token is still blocked by HBAC when it attempts token exchange as a different client.

Prerequisites

ToolPurpose
python3obo-hbac-demo.py; stdlib only, no extra packages needed
ahdapaIn $PATH, or built automatically by run.sh

Running

# Non-interactive: exits 0 on pass, 1 on failure
contrib/demo/obo/run.sh

# Interactive: keeps node running until Ctrl-C
contrib/demo/obo/run.sh --interactive

Run the Python script manually against an already-running node:

python3 contrib/demo/obo/obo-hbac-demo.py \
    --base-url http://127.0.0.1:8080 \
    --admin-user alice \
    --admin-password alice123

Files

FileDescription
node.tomlSingle-node config: HTTP, SQLite, static users
users.tomlStatic user list (alice, admin)
run.shDemo / CI script; starts ahdapa, runs scenarios, cleans up
obo-hbac-demo.pyPython script that exercises all five scenarios

Expected output

PASS  scenario 1: basic OBO — act claim present and workload_type correct
PASS  scenario 2: delegation target allowed (host/backend.example.com)
PASS  scenario 3: delegation target denied (host/untrusted.example.com)
PASS  scenario 4: actor gate — rogue service rejected (access_denied)
PASS  scenario 5: scope narrowing — invalid_scope for unregistered scope

Key configuration concepts demonstrated

allow_token_exchange_actor must be true on a client for it to supply actor_token. This is a client-level gate independent of HBAC.

workload_type is set on the client registration and embedded in act.workload_type in OBO tokens issued when that client is the actor.

delegation_targets on an HBAC rule is a list of Kerberos SPNs the rule permits as target_service. Only rules that already match user, client, scope, and network axes are considered for the delegation check.

delegation_target_category = true on an HBAC rule is a wildcard: any target_service value is permitted by that rule.

mfa_bypass = true is required for M2M rules. DWRegister (the CRDT type backing mfa_bypass) defaults to false when no tags have been recorded. A rule without an explicit mfa_bypass=true returns mfa_required=true from HBAC evaluation, and the token exchange handler rejects the request because OBO and CC flows carry no AMR.

HBAC rule structure

The demo creates two HBAC rules rather than one:

demo-cc-base — covers all clients for plain client credentials: client_category=all, user_category=all, scope_category=all, mfa_bypass=true, delegation_targets=["_cc_only"]. The _cc_only sentinel prevents this rule from granting OBO delegation to any real service principal: when a token exchange carries a real target_service, the delegation check filters this rule out.

demo-obo-policy — explicit OBO grant for the agent: clients=[agent_id], user_category=all, scope_category=all, mfa_bypass=true, delegation_targets=["host/correct-server.example.com"].

Scenario 5 supplies target_service="host/correct-server.example.com" so the delegation axis is evaluated. The _cc_only sentinel rule is excluded in the delegation phase, and only the OBO rule satisfies the request.