|
| 1 | +# Agent-to-Agent (A2A) + OID4V integration demo |
| 2 | + |
| 3 | +This demo is built around one of the relevant use cases for Agentic AI identity – VC-based authentication for interaction with Agents. |
| 4 | +It leverages [Agent-to-Agent (A2A)](https://a2a-protocol.org/latest/specification/) and [OpenID for Verifiable Presentations](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html) protocols, specifically demonstrating how to use OID4VP for A2A Task Authentication by implementing [OID4VP In-Task Authentication extension for A2A](https://github.com/DSRCorporation/a2a-oid4vp-in-task-auth-extension/blob/main/v1/spec.md). |
| 5 | + |
| 6 | +The demo is built using [Genkit](https://genkit.dev/) with the OpenAI API. |
| 7 | +Heka Identity Platform is used as a decentralized identity wallet / agent providing support for OID4VP (for both Holder and Verifier parties). |
| 8 | + |
| 9 | +This is a demo code not intended for production-quality usage. |
| 10 | + |
| 11 | +## Scenario |
| 12 | + |
| 13 | +This demo showcases how an AI agent can request additional authentication from a user using the **OID4VP** protocol and how Heka Identity Platform enables such capabilities. |
| 14 | + |
| 15 | +The **Demo Agent** acts as an AI-powered assistant capable of processing user queries and generating responses using Genkit and the OpenAI API. |
| 16 | +The agent is configured to require the user to present a verifiable credential via OID4VP before fulfilling any requests. |
| 17 | + |
| 18 | +The following mapping applies for roles/parties described in extension spec: |
| 19 | +- A2A Client → [CLI client](src/cli.ts) |
| 20 | +- A2A Server → [Demo Agent Server](src/agent/index.ts) |
| 21 | +- OID4VP Wallet → [Heka Mobile Wallet](../../heka-wallet) |
| 22 | +- OID4VP Verifier → [Heka Identity Service](../../heka-identity-service) |
| 23 | + |
| 24 | +```mermaid |
| 25 | +sequenceDiagram |
| 26 | + participant User |
| 27 | + participant Wallet as Heka Wallet |
| 28 | + participant CLI as CLI Client |
| 29 | + participant Agent as Demo Agent |
| 30 | + participant HIS as Heka Identity Service |
| 31 | + participant LLM as OpenAI |
| 32 | +
|
| 33 | + User->>CLI: Sends message (Task Initiation) |
| 34 | + CLI->>Agent: Send Message Request (A2A) |
| 35 | + Agent->>HIS: Create Verification Session (OID4VP) |
| 36 | + HIS-->>Agent: Authorization Request Metadata |
| 37 | + Agent->>CLI: Status Update (state: auth-required + metadata) |
| 38 | + CLI->>Wallet: Invoke Wallet (Out-of-band / DidComm) |
| 39 | + Wallet->>User: Display Authorization Request |
| 40 | + User->>Wallet: Confirm Presentation |
| 41 | + Wallet->>HIS: Submit Verifiable Presentation (OID4VP direct_post) |
| 42 | + HIS->>Agent: Notify Verification Status (Webhook/WebSocket) |
| 43 | + Agent->>LLM: Process Task (with verified context) |
| 44 | + LLM-->>Agent: AI Response |
| 45 | + Agent->>CLI: Status Update (state: completed + response) |
| 46 | + CLI->>User: Display Agent's Response |
| 47 | +``` |
| 48 | + |
| 49 | +1. **Task Initiation**: A user sends a message to the Demo Agent via the A2A CLI. |
| 50 | +2. **In-Task Authentication Request**: The Demo Agent determines that the context/task requires authentication. It invokes Heka Identity Service API to generate OID4VP authorization request, then sends CLI Client a `status-update` with the `auth-required` state that also includes OID4VP authorization request metadata. |
| 51 | +3. **OID4VP Flow Initiation**: The CLI client detects the OID4VP request and invokes Heka Wallet to present the requested credentials. |
| 52 | +4. **Sharing Verifiable Presentation**: Heka Wallet receives OID4VP authorization request, displays requested credentials / claims to a user. After receiving a confirmation, the wallet sends authorization response (containing Verifiable Presentation) to Heka Identity Service verifier endpoint (OID4VP `direct_post.jwt` response mode). |
| 53 | +5. **Verification**: Heka Identity Service receives and validates the presentation, then sends an out-of-band notification with verification status to the Demo Agent. |
| 54 | +6. **In-Task Authentication Completion**: The Demo Agent receives notification and makes a decision on proceeding with a task based on verification status. |
| 55 | +7. **Task Execution**: Once In-Task authentication is successfully completed, the Demo Agent proceeds with the task and generates a response. |
| 56 | + |
| 57 | +## Running the Demo |
| 58 | + |
| 59 | +### 1. Install prerequisites |
| 60 | + |
| 61 | +- Node.js (v18 or higher) |
| 62 | +- yarn v4.9.4 |
| 63 | +- Docker |
| 64 | +- An OpenAI API key |
| 65 | + |
| 66 | +### 2. Create an env file |
| 67 | + |
| 68 | +Copy the `.env.example` file to `.env`: |
| 69 | + |
| 70 | +```bash |
| 71 | +cp .env.example .env |
| 72 | +``` |
| 73 | + |
| 74 | +You can use `.env` file to define environment-specific and general settings for the demo. |
| 75 | +Most values defined in `.env.example` follow default values used by Heka Identity Platform and can be kept as is. |
| 76 | + |
| 77 | +However, there are values that need to be manually set up: |
| 78 | +- `OPENAI_API_KEY` - add your OpenAI API key there |
| 79 | +- `HOLDER_PUBLIC_DID` - needs to be added after setting up the Heka Wallet app (see the [Run Heka Wallet section](#run-heka-wallet-on-mobile-device)) |
| 80 | + |
| 81 | +Other supported values: |
| 82 | +- `DEMO_AGENT_PORT` - Port to be used by the Demo Agent server, defaults to `10003` |
| 83 | +- `CLI_CLIENT_PORT` - Port to be used by CLI Client inbound transport (DidComm inbound transport, used for Mobile Wallet invocation), defaults to `3010` |
| 84 | +- `IDENTITY_SERVICE_URL` - URL of local instance of Heka Identity Service, defaults to `http://localhost:3000`. Must be changed if host, port or API prefix configuration of the instance differs from default values |
| 85 | +- `IDENTITY_SERVICE_ACCESS_TOKEN` - Heka Identity Service API token, default value is a demo token with extremely long validity period. Must be changed if JWT configuration for Heka Identity Service instance was changed |
| 86 | + |
| 87 | +### 3. Setup Heka Identity Platform |
| 88 | + |
| 89 | +#### Run Heka Identity Service |
| 90 | + |
| 91 | +Before running Heka Identity Service instance locally, you need to set up a local instance of Postgres DB. |
| 92 | +This can be done using the following command: |
| 93 | + |
| 94 | +```bash |
| 95 | +docker run --name heka-identity-service-postgres -e POSTGRES_DB=heka-identity-service -e POSTGRES_USER=heka -e POSTGRES_PASSWORD=heka1 -p 5432:5432 -d postgres |
| 96 | +``` |
| 97 | + |
| 98 | +To run the service instance itself, go to [Heka Identity Service folder](../../heka-identity-service), install dependencies, set up the DB migrations and run the app: |
| 99 | + |
| 100 | +```bash |
| 101 | +yarn install && yarn migration:up |
| 102 | +yarn start |
| 103 | +``` |
| 104 | + |
| 105 | +#### Run Heka Wallet on mobile device |
| 106 | + |
| 107 | +It's strongly recommended to use Android device for running the demo since ADB allows convenient port reversing to localhost. |
| 108 | + |
| 109 | +If you'd like to use an iOS device, you'll need to expose Heka Identity Service ports so they're available for the Heka Wallet app on the mobile device. |
| 110 | +This can be done by using your local network IP address in the Identity Service configuration or leveraging services such as [ngrok](https://ngrok.com). |
| 111 | + |
| 112 | +Install dependencies in `heka-wallet` folder: |
| 113 | + |
| 114 | +```bash |
| 115 | +yarn install |
| 116 | +``` |
| 117 | + |
| 118 | +Open `.env` file in `heka-wallet/app` folder and set `ENABLE_EXAMPLE_CREDENTIAL` value to `true`. |
| 119 | + |
| 120 | +(Android only) Enable TCP port reversal to enable access to `localhost` OID4VC endpoints of Heka Identity Service: |
| 121 | + |
| 122 | +```bash |
| 123 | +adb devices |
| 124 | +# Find your device id in "adb devices" output |
| 125 | +adb -s <your-device-id> reverse tcp:3003 tcp:3003 |
| 126 | +``` |
| 127 | + |
| 128 | +Run the application: |
| 129 | + |
| 130 | +```bash |
| 131 | +# For Android |
| 132 | +yarn run:android |
| 133 | + |
| 134 | +# For iOS |
| 135 | +yarn run:ios |
| 136 | +``` |
| 137 | + |
| 138 | +Keep Heka Wallet logs open, complete wallet onboarding process and find a log in the following format: `Public DID: did:peer:...`. |
| 139 | +Copy `<public-did-peer>` value and put it into the demo `.env` file as `HOLDER_PUBLIC_DID` value. |
| 140 | +The public DID value is persistent and will be relevant until you fully reset your Heka Wallet app (by removing application data or reinstalling it completely). |
| 141 | + |
| 142 | +Example did:peer value: `did:peer:2.Vz6MkoWbqNzyX3BaTpECoQsCkKrww2n2pu6F7ZUYq7msD8q5P.Ez6LShhHdY2PSw9QRStKsPoEYDZyfDV8pTGuWTbdc6a2VdsnT.SeyJzIjoid3NzOi8vY2EuZGV2LjIwNjAuaW8iLCJ0IjoiZGlkLWNvbW11bmljYXRpb24iLCJwcmlvcml0eSI6MCwicmVjaXBpZW50S2V5cyI6WyIja2V5LTEiXSwiciI6WyJkaWQ6a2V5Ono2TWtyZ2lmbW1nN1ZWOHQzUXdKTGJnaVJEZnF4UFVyWXZQd25Qcm9aeEQ4cTduTCN6Nk1rcmdpZm1tZzdWVjh0M1F3SkxiZ2lSRGZxeFBVcll2UHduUHJvWnhEOHE3bkwiXX0` |
| 143 | + |
| 144 | +### 4. Install demo dependencies |
| 145 | + |
| 146 | +Install dependencies in `demo` folder: |
| 147 | + |
| 148 | +```bash |
| 149 | +yarn install |
| 150 | +``` |
| 151 | + |
| 152 | +### 5. Run the Agent |
| 153 | + |
| 154 | +In one terminal, start the Demo Agent: |
| 155 | + |
| 156 | +```bash |
| 157 | +yarn agent |
| 158 | +``` |
| 159 | + |
| 160 | +The agent will start an A2A server (port 10003, can be changed using `DEMO_AGENT_PORT` env variable). |
| 161 | + |
| 162 | +### 6. Run the CLI Client |
| 163 | + |
| 164 | +In a second terminal, start the CLI Client: |
| 165 | + |
| 166 | +```bash |
| 167 | +yarn client |
| 168 | +``` |
| 169 | + |
| 170 | +The CLI Client will start an inbound DidComm transport that will use port 3010 (can be changed using `CLI_CLIENT_PORT` env variable). |
| 171 | + |
| 172 | +### 7. Try out integration with the Agent |
| 173 | + |
| 174 | +You can now interact with the Demo Agent. The first message you send will trigger the OID4VP authentication flow. |
| 175 | +Heka Wallet app on your mobile device will display the OID4VP authorization request shortly after – you need to explicitly accept it in the app to pass additional auth requested by A2A Server. |
| 176 | + |
| 177 | +## Disclaimer |
| 178 | +Important: The code provided is for demonstration purposes and illustrates the |
| 179 | +mechanics of leveraging Heka Identity Platform for Agent-to-Agent (A2A) protocol flow with OID4VP In-Task Authentication Extension. When building production applications, |
| 180 | +it is critical to treat any agent operating outside of your direct control as a |
| 181 | +potentially untrusted entity. |
| 182 | + |
| 183 | +All data received from an external agent—including but not limited to its AgentCard, |
| 184 | +messages, artifacts, and task statuses—should be handled as untrusted input. For |
| 185 | +example, a malicious agent could provide an AgentCard containing crafted data in its |
| 186 | +fields (e.g., description, name, skills.description). If this data is used without |
| 187 | +sanitization to construct prompts for a Large Language Model (LLM), it could expose |
| 188 | +your application to prompt injection attacks. Failure to properly validate and |
| 189 | +sanitize this data before use can introduce security vulnerabilities into your |
| 190 | +application. |
| 191 | + |
| 192 | +Developers are responsible for implementing appropriate security measures, such as |
| 193 | +input validation and secure handling of credentials to protect their systems and users. |
0 commit comments