|
| 1 | +# ACK-ID: A2A Identity & Auth Demo |
| 2 | + |
| 3 | +**ACK-ID** is a protocol built on W3C Standards designed to bring verifiable, secure, compliant identity, reputation, and service discovery to agents. |
| 4 | + |
| 5 | +**A2A** (Agent2Agent) is a protocol developed by Google to standardize communication between multiple agents. |
| 6 | + |
| 7 | +This interactive command-line demo showcases how two A2A-compatible agents can use ACK-ID to verify each other's identity and trust that they are communicating with the expected agent. |
| 8 | + |
| 9 | +## Getting started |
| 10 | + |
| 11 | +Before starting, please follow the [Getting Started](../../README.md#getting-started) guide at the root of this monorepo. |
| 12 | + |
| 13 | +### Running the demo |
| 14 | + |
| 15 | +You can use the demo by running the following command from the root of this repository: |
| 16 | + |
| 17 | +```sh |
| 18 | +pnpm run demo:identity-a2a |
| 19 | +``` |
| 20 | + |
| 21 | +Alternatively, you can run the demo from this directory with: |
| 22 | + |
| 23 | +```sh |
| 24 | +pnpm run demo |
| 25 | +``` |
| 26 | + |
| 27 | +## Overview |
| 28 | + |
| 29 | +This demo showcases mutual authentication flow between a Bank Customer Agent and a Bank Teller Agent using ACK-ID DIDs and JWTs exchanged within A2A message bodies. The demo walks through the following authentication flow. |
| 30 | + |
| 31 | +### 1. Initial Contact - Customer Agent Initiates |
| 32 | + |
| 33 | +The Customer Agent sends an authentication request as an A2A message containing a signed JWT with a nonce: |
| 34 | + |
| 35 | +```jsonc |
| 36 | +{ |
| 37 | + "role": "user", |
| 38 | + "kind": "message", |
| 39 | + "messageId": "f1f54f9d-6db2-4d78-8b38-4e50d77c8b19", |
| 40 | + "parts": [ |
| 41 | + { |
| 42 | + "type": "data", |
| 43 | + "data": { |
| 44 | + "jwt": "<signed-JWT-from-customer>" |
| 45 | + } |
| 46 | + } |
| 47 | + ] |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +The JWT payload includes: |
| 52 | + |
| 53 | +```jsonc |
| 54 | +{ |
| 55 | + "iss": "did:web:customer.example.com", // Customer's DID |
| 56 | + "aud": "did:web:bank.example.com", // Bank's expected DID |
| 57 | + "nonce": "c-128bit-random", // Customer's random nonce |
| 58 | + "iat": 1718476800, |
| 59 | + "jti": "0e94d7ec-...", // Unique JWT ID |
| 60 | + "exp": 1718477100 // 5-minute expiry |
| 61 | +} |
| 62 | +``` |
| 63 | + |
| 64 | +### 2. Bank Teller Agent Response |
| 65 | + |
| 66 | +The Bank Teller Agent verifies the customer's JWT signature and responds with its own signed JWT, including both the customer's nonce and a new server nonce: |
| 67 | + |
| 68 | +```jsonc |
| 69 | +{ |
| 70 | + "role": "agent", |
| 71 | + "kind": "message", |
| 72 | + "messageId": "f1f54f9d-6db2-4d78-8b38-4e50d77c8b19", |
| 73 | + "parts": [ |
| 74 | + { |
| 75 | + "type": "data", |
| 76 | + "data": { |
| 77 | + "jwt": "<signed-JWT-from-bank>" |
| 78 | + } |
| 79 | + } |
| 80 | + ] |
| 81 | +} |
| 82 | +``` |
| 83 | + |
| 84 | +The Bank's JWT payload: |
| 85 | + |
| 86 | +```jsonc |
| 87 | +{ |
| 88 | + "iss": "did:web:bank.example.com", // Bank's DID |
| 89 | + "aud": "did:web:customer.example.com", // Customer's DID |
| 90 | + "nonce": "c-128bit-random", // Echo customer's nonce |
| 91 | + "replyNonce": "b-128bit-random", // Bank's new nonce |
| 92 | + "jti": "1f85c8fa-...", // Unique JWT ID |
| 93 | + "iat": 1718476805, |
| 94 | + "exp": 1718477105 // Short expiry |
| 95 | +} |
| 96 | +``` |
| 97 | + |
| 98 | +### 3. Subsequent Communications |
| 99 | + |
| 100 | +After successful mutual authentication, all subsequent messages include a signature in the metadata: |
| 101 | + |
| 102 | +```jsonc |
| 103 | +{ |
| 104 | + "role": "user", |
| 105 | + "kind": "message", |
| 106 | + "messageId": "89f2e11b-5b0a-4c3b-b49d-14628e5d30fb", |
| 107 | + "parts": [ |
| 108 | + { |
| 109 | + "type": "text", |
| 110 | + "text": "Please check the balance for account #12345" |
| 111 | + } |
| 112 | + ], |
| 113 | + "metadata": { |
| 114 | + "sig": "eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9...Q" // JWT signature of the parts array |
| 115 | + } |
| 116 | +} |
| 117 | +``` |
| 118 | + |
| 119 | +The signature is a JWT with the payload of `{ "message": <the-message-object-without-metadata> }`, with `aud` and `iss` properly set for the counterparty and sender's DID, respectively. |
| 120 | + |
| 121 | +### Security Benefits |
| 122 | + |
| 123 | +This authentication flow provides several security advantages: |
| 124 | + |
| 125 | +- **Mutual Authentication:** Both parties prove their identity through cryptographic signatures |
| 126 | +- **Replay Attack Prevention:** Nonces and JWT IDs ensure messages cannot be replayed |
| 127 | +- **Man-in-the-Middle (MITM) Protection:** The aud and iss fields are pinned in the JWTs, preventing tampering. An attacker cannot modify requests or responses without invalidating the signatures |
| 128 | +- **Short-lived Tokens:** 5-minute expiry limits the window for potential attacks |
| 129 | +- **Verifiable Identity:** DID-based authentication ensures cryptographic proof of identity |
| 130 | + |
| 131 | +## Learn More |
| 132 | + |
| 133 | +- [Agent Commerce Kit](https://www.agentcommercekit.com) Documentation |
| 134 | +- [ACK-ID](https://www.agentcommercekit.com/ack-id) Documentation |
| 135 | +- [A2A](https://github.com/google-a2a/A2A) Documentation |
0 commit comments