Skip to main content

Get started

This tutorial starts with a fresh clone and ends with an agent tool call. You grant access in the browser, inspect the stored grant, and send a broker token through Agentgateway. The mock MCP server shows which provider claims it receives after token exchange.

Docker Compose seeds sample agents, services, and permission sets automatically. The demo uses mock providers, not real GitHub or Google accounts.

Before you start​

You need Docker with Docker Compose v2, Git, curl, and OpenSSL. The host-side key-generation script requires OpenSSL. The grant lookup also uses jq.

The project uses just as a command runner. Install it with brew install just or cargo install just, or use the plain Compose commands in Step 1.

git clone https://github.com/zalando-incubator/agentic-identity-broker.git
cd agentic-identity-broker

You do not need Go, Node.js, PostgreSQL, or cloud credentials on your host. The stack uses an in-memory store and generates local encryption keys at startup. This development stack trusts a simulated user identity. Do not expose it to other machines.

Step 1: Start the stack​

From the repository root:

just compose-up-detached

Without just, run:

test -f .env.compose || cp .env.compose.example .env.compose
IDENTITY_BROKER_JWE_SIGNING_KEY="$(./scripts/generate-jwe-key.sh)" \
IDENTITY_BROKER_ENCRYPTION_MEMORY_RAW_KEY="$(./scripts/generate-jwe-key.sh)" \
docker compose --env-file .env.compose -f docker-compose.yml up -d --build --wait --wait-timeout 600

The first run builds eight service images, including the Go backend and Vite frontend. Startup depends on your machine, network, and build cache. A clean-machine cold-start time is not yet measured. Startup waits for service health, including the frontend. The frontend runs npm ci to synchronize its dependency volume before Vite starts. Broker health alone does not mean that sample-data seeding has finished. Wait for the agents in Step 2 and enabled login buttons on the sample client.

The just command prints these URLs after its health summary:

Service URLs:
- Browser UI (Vite proxy includes development identity): http://localhost:3000/
- End-user broker (protected API requires upstream auth): http://localhost:8000/
- Admin API: http://localhost:14000/api/agents
- Admin health: http://localhost:14000/health
- Sample OAuth2 client: http://localhost:9002/
- Agentgateway MCP endpoint: http://localhost:4000/mcp
ServiceURLRole
Consent UIhttp://localhost:3000/Browser interface and development identity proxy
Broker — end-user APIhttp://localhost:8000/Consent, provider sessions, and OAuth2 endpoints
Broker — admin APIhttp://localhost:14000/Agent and service configuration
Sample agenthttp://localhost:9002/OAuth2 client and broker-token display
Agentgatewayhttp://localhost:4000/mcpJWT validation and transparent token exchange
Mock MCP serverhttp://localhost:9003/mcpTool backend; call it through the gateway
Mock OAuth2 providershttp://localhost:9000/, http://localhost:9001/Provider tokens and upstream authorization
note

The Vite proxy adds X-Remote-User: dev@example.com to browser requests. It simulates an authenticating reverse proxy. The broker trusts that asserted identity; it does not authenticate users itself.

Step 2: Review the seeded data​

List the agents through the admin API:

curl --fail-with-body http://localhost:14000/api/agents

The response is a JSON array. Wait until it includes Local Research Agent. If startup fails, inspect docker compose --env-file .env.compose -f docker-compose.yml logs.

Step 3: Start the sample agent's authorization request​

Open http://localhost:9002/ in your browser. Select Login as Local Client. This flow returns a broker-issued token. Proxy Client instead returns a token from the mock upstream authorization server.

The sample client redirects you to the broker's consent interface at http://localhost:3000. The interface shows Local Research Agent and its requested permission sets.

Select the optional Identity Access permission set. Connect Mock OAuth2 Service (Dev) before you submit consent. Complete the mock provider authorization in the browser. This stores the provider token in the broker, not the agent.

Review your selection, then submit consent. The broker redirects you to the sample client. Its Access Token Claims table describes the broker-issued token.

Step 5: View the stored delegation​

The admin API lists agent configuration, not user grants. Find the agent UUID there, then read the grant from the authenticated end-user API through the development proxy:

AGENT_ID=$(curl --fail --silent http://localhost:14000/api/agents \
| jq -er '.[] | select(.display_name == "Local Research Agent") | .id')
curl --fail-with-body "http://localhost:3000/api/consent/agents/$AGENT_ID/grants"

The response's data array contains grant objects. Each grant contains its ID, principal, agent_id, granted_permission_sets, and timestamps. The principal is dev@example.com. A grant with an expiry also includes valid_until. The response does not contain provider credentials.

Step 6: Call a tool through the gateway​

On the sample client page, select Call MCP Tool: whoami (allowed). The sample client sends your logged-in Local Client token through the configured gateway. It handles MCP initialization and session headers automatically. You do not need to copy the token into a shell.

The result shows Token Exchange Successful!, the tool response, the gateway URL, and JWT Claims. The tool response contains auth_scheme=Bearer and jwt_claims=... from the token visible to the MCP server. Compare those provider claims with the Access Token Claims table on the same page.

ClaimBroker token sent by the agentProvider token received by the MCP server
isshttp://localhost:3000http://third-party-oauth2:9000
audtoken-exchange-brokermcp-server
azpThe Local Research Agent UUIDmock-oauth2-client-dev

The gateway validates the broker JWT; ExtProc exchanges it for the stored provider token before forwarding the request. The mock returns decoded claims for inspection, not the reusable provider token. Its claim decoder is not a signature verifier.

A 401 indicates a JWT validation problem, such as an expired token or the wrong client flow. A session-recovery error means that the broker needs a usable provider session in addition to the grant. Return to the consent UI to connect the mock provider, then retry.

Step 7: Tear down​

just compose-down

Without just:

docker compose --env-file .env.compose -f docker-compose.yml down

The in-memory store discards the seeded data, provider sessions, and grants when the broker stops.

Where to go next​