Skip to content

Commit 3ca2997

Browse files
Add A2A-OID4VP Demo + related updates for Heka Wallet
Signed-off-by: Alexander Shenshin <alexander.shenshin@dsr-corporation.com>
1 parent 0f0c9ca commit 3ca2997

27 files changed

Lines changed: 9193 additions & 172 deletions

demo/a2a-oid4vp/.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
OPENAI_API_KEY=your_api_key_here
2+
DEMO_AGENT_PORT=10003
3+
CLI_CLIENT_PORT=3010
4+
IDENTITY_SERVICE_URL=http://localhost:3000
5+
IDENTITY_SERVICE_ACCESS_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlcyI6WyJBZG1pbiJdLCJuYW1lIjoiZGVtbyIsInR5cGUiOiJhY2Nlc3MiLCJpYXQiOjE3NzE5ODA5MjAsImV4cCI6MzI4NzU5ODA5MjAsImF1ZCI6Ikhla2EgSWRlbnRpdHkgU2VydmljZSIsImlzcyI6Ikhla2EiLCJzdWIiOiI1YjQwZDIwMi0yMmI2LTQ2ZDMtOWY0NC04YmY3ZjEwYzNmNGUifQ.j8v7QFYkpwgtPbDU-aIMayMsMo_vLQ9v9h3dBELqBeo
6+
HOLDER_PUBLIC_DID=did:peer:2.Vz6MkoWbqNzyX3BaTpECoQsCkKrww2n2pu6F7ZUYq7msD8q5P.Ez6LShhHdY2PSw9QRStKsPoEYDZyfDV8pTGuWTbdc6a2VdsnT.SeyJzIjoid3NzOi8vY2EuZGV2LjIwNjAuaW8iLCJ0IjoiZGlkLWNvbW11bmljYXRpb24iLCJwcmlvcml0eSI6MCwicmVjaXBpZW50S2V5cyI6WyIja2V5LTEiXSwiciI6WyJkaWQ6a2V5Ono2TWtyZ2lmbW1nN1ZWOHQzUXdKTGJnaVJEZnF4UFVyWXZQd25Qcm9aeEQ4cTduTCN6Nk1rcmdpZm1tZzdWVjh0M1F3SkxiZ2lSRGZxeFBVcll2UHduUHJvWnhEOHE3bkwiXX0

demo/a2a-oid4vp/.prettierrc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"printWidth": 120,
3+
"tabWidth": 2,
4+
"useTabs": false,
5+
"semi": false,
6+
"singleQuote": true,
7+
"quoteProps": "as-needed",
8+
"jsxSingleQuote": false,
9+
"trailingComma": "es5",
10+
"bracketSpacing": true,
11+
"bracketSameLine": false,
12+
"arrowParens": "always",
13+
"endOfLine": "lf",
14+
"proseWrap": "preserve"
15+
}

demo/a2a-oid4vp/.yarn/releases/yarn-4.9.4.cjs

Lines changed: 942 additions & 0 deletions
Large diffs are not rendered by default.

demo/a2a-oid4vp/.yarnrc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
nodeLinker: node-modules
2+
3+
yarnPath: .yarn/releases/yarn-4.9.4.cjs

demo/a2a-oid4vp/README.md

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
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.

demo/a2a-oid4vp/package.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "a2a-oid4vp-demo",
3+
"version": "0.1.0",
4+
"description": "Demo for A2A OID4VP In-Task Auth that leverages Heka Identity Platform.",
5+
"scripts": {
6+
"agent": "tsx src/agent/index.ts",
7+
"client": "tsx src/cli.ts",
8+
"format": "prettier --write ."
9+
},
10+
"license": "Apache-2.0",
11+
"dependencies": {
12+
"@a2a-js/sdk": "^0.3.10",
13+
"@credo-ts/askar": "^0.6.2",
14+
"@credo-ts/core": "^0.6.2",
15+
"@credo-ts/didcomm": "^0.6.2",
16+
"@credo-ts/node": "^0.6.2",
17+
"@genkit-ai/compat-oai": "^1.28.0",
18+
"@openwallet-foundation/askar-nodejs": "^0.4.3",
19+
"@openwallet-foundation/askar-shared": "^0.4.3",
20+
"@types/express": "^5.0.6",
21+
"axios": "^1.13.5",
22+
"dotenv": "^17.3.1",
23+
"express": "^5.2.1",
24+
"genkit": "^1.28.0",
25+
"prettier": "^3.8.1",
26+
"tsx": "^4.21.0",
27+
"typescript": "^5.9.3",
28+
"ws": "^8.19.0"
29+
},
30+
"packageManager": "yarn@4.9.4"
31+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { AgentExtension, ExtensionURI } from '@a2a-js/sdk'
2+
3+
export const IN_TASK_OID4VP_EXTENSION_URI: ExtensionURI =
4+
'https://github.com/DSRCorporation/a2a-oid4vp-in-task-auth-extension/tree/main/v1'
5+
6+
export interface InTaskOpenId4VpAuthorizationRequest {
7+
client_id: string
8+
request_uri: string
9+
}
10+
11+
export interface InTaskOpenId4VpMessageMetadata {
12+
authorizationRequest: InTaskOpenId4VpAuthorizationRequest
13+
}
14+
15+
export interface InTaskOpenId4VpExtension extends AgentExtension {
16+
params: { oid4vpVersions: string[] }
17+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{{role "system_instruction"}}
2+
You are an expert in decentralized identity protocols.
3+
You MUST understand DID as Decentralized Identifier, VC as Verifiable Credential, OID4VC as OpenId for Verifiable Credentials.
4+
5+
Your output should consist of a short answer to the user's question.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { openAI } from '@genkit-ai/compat-oai/openai'
2+
import { genkit } from 'genkit'
3+
import { dirname } from 'path'
4+
import { fileURLToPath } from 'url'
5+
6+
export const ai = genkit({
7+
plugins: [openAI()],
8+
model: openAI.model('gpt-3.5-turbo'),
9+
promptDir: dirname(fileURLToPath(import.meta.url)),
10+
})
11+
12+
export { z } from 'genkit'

0 commit comments

Comments
 (0)