@aamp/protocol 1.1.7 → 1.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/publisher.d.ts +5 -0
- package/dist/publisher.js +36 -1
- package/dist/types.d.ts +1 -0
- package/package.json +8 -1
- package/src/publisher.ts +44 -1
- package/src/types.ts +5 -1
- package/aamp-protocol-1.1.5.tgz +0 -0
package/dist/publisher.d.ts
CHANGED
|
@@ -33,6 +33,11 @@ export declare class AAMPPublisher {
|
|
|
33
33
|
private checkPolicyStrict;
|
|
34
34
|
private verifyRequestLogic;
|
|
35
35
|
private verifyDnsBinding;
|
|
36
|
+
/**
|
|
37
|
+
* NEW: Verify a Broker-Issued Token (JWT)
|
|
38
|
+
* Checks if the request contains a valid "Visa" from the Broker.
|
|
39
|
+
*/
|
|
40
|
+
private verifyBrokerCred;
|
|
36
41
|
private isDomain;
|
|
37
42
|
generateResponseHeaders(origin: ContentOrigin): Promise<Record<string, string>>;
|
|
38
43
|
/**
|
package/dist/publisher.js
CHANGED
|
@@ -6,6 +6,7 @@ import { HEADERS, MAX_CLOCK_SKEW_MS, WELL_KNOWN_AGENT_PATH } from './constants.j
|
|
|
6
6
|
import { exportPublicKey, signData, verifySignature } from './crypto.js';
|
|
7
7
|
import { AccessPurpose } from './types.js';
|
|
8
8
|
import { verifyJwt } from './proof.js';
|
|
9
|
+
import { jwtVerify, createRemoteJWKSet } from 'jose';
|
|
9
10
|
/**
|
|
10
11
|
* Default In-Memory Cache (Fallback only)
|
|
11
12
|
* NOT recommended for high-traffic Serverless production.
|
|
@@ -186,6 +187,19 @@ export class AAMPPublisher {
|
|
|
186
187
|
if (requestHeader.purpose === AccessPurpose.CRAWL_TRAINING && !this.policy.allowTraining) {
|
|
187
188
|
return { allowed: false, status: 403, reason: 'POLICY_DENIED: Training not allowed.', visitorType: 'VERIFIED_AGENT' };
|
|
188
189
|
}
|
|
190
|
+
// 2. BROKER CHECK (New v1.1)
|
|
191
|
+
if (this.policy.monetization?.brokerUrl) {
|
|
192
|
+
const brokerUrl = this.policy.monetization.brokerUrl;
|
|
193
|
+
if (!paymentCredential) {
|
|
194
|
+
return { allowed: false, status: 402, reason: "PAYMENT_REQUIRED: Missing Broker Credential", visitorType: 'UNIDENTIFIED_BOT' };
|
|
195
|
+
}
|
|
196
|
+
const isValid = await this.verifyBrokerCred(paymentCredential, brokerUrl);
|
|
197
|
+
if (!isValid) {
|
|
198
|
+
return { allowed: false, status: 403, reason: "PAYMENT_DENIED: Invalid Broker Token", visitorType: 'UNIDENTIFIED_BOT' };
|
|
199
|
+
}
|
|
200
|
+
// If valid, we record the "Proof Used" so we can settle later
|
|
201
|
+
return { allowed: true, status: 200, reason: "AAMP_PAID", visitorType: "VERIFIED_AGENT", proofUsed: `BROKER_JWT:${paymentCredential.slice(0, 10)}...` };
|
|
202
|
+
}
|
|
189
203
|
if (requestHeader.purpose === AccessPurpose.RAG_RETRIEVAL && !this.policy.allowRAG) {
|
|
190
204
|
return { allowed: false, status: 403, reason: 'POLICY_DENIED: RAG not allowed.', visitorType: 'VERIFIED_AGENT' };
|
|
191
205
|
}
|
|
@@ -275,7 +289,7 @@ export class AAMPPublisher {
|
|
|
275
289
|
return { allowed: false, reason: 'IDENTITY_FAIL: DNS Binding could not be verified.', identityVerified: false };
|
|
276
290
|
}
|
|
277
291
|
// Return verified status so handleAgentStrict can proceed to Policy Check
|
|
278
|
-
return { allowed: true, reason: 'OK', identityVerified:
|
|
292
|
+
return { allowed: true, reason: 'OK', identityVerified: identityVerified };
|
|
279
293
|
}
|
|
280
294
|
async verifyDnsBinding(domain, requestKeySpki) {
|
|
281
295
|
try {
|
|
@@ -312,6 +326,27 @@ export class AAMPPublisher {
|
|
|
312
326
|
return false;
|
|
313
327
|
}
|
|
314
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* NEW: Verify a Broker-Issued Token (JWT)
|
|
331
|
+
* Checks if the request contains a valid "Visa" from the Broker.
|
|
332
|
+
*/
|
|
333
|
+
async verifyBrokerCred(credential, brokerUrl) {
|
|
334
|
+
try {
|
|
335
|
+
// 1. Fetch Broker's Public Keys (JWKS)
|
|
336
|
+
const JWKS = createRemoteJWKSet(new URL(`${brokerUrl}/.well-known/jwks.json`));
|
|
337
|
+
// 2. Verify the Token Signature
|
|
338
|
+
const { payload } = await jwtVerify(credential, JWKS, {
|
|
339
|
+
issuer: brokerUrl, // Ensure it came from THE Broker
|
|
340
|
+
clockTolerance: 5 // Allow 5s clock skew
|
|
341
|
+
});
|
|
342
|
+
console.log(`[BROKER] 💰 Valid Payment Token from ${payload.iss} for amount ${payload.amount}`);
|
|
343
|
+
return true;
|
|
344
|
+
}
|
|
345
|
+
catch (e) {
|
|
346
|
+
console.warn(`[BROKER] ❌ Invalid Token:`, e.message);
|
|
347
|
+
return false;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
315
350
|
isDomain(s) {
|
|
316
351
|
// Basic regex, allows localhost with ports
|
|
317
352
|
return /^[a-zA-Z0-9.-]+(:\d+)?$/.test(s) || /^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(s);
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aamp/protocol",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.9",
|
|
4
4
|
"description": "TypeScript reference implementation of AAMP v1.1",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./dist/index.js",
|
|
9
|
+
"./dist/nextjs": "./dist/nextjs.js",
|
|
10
|
+
"./dist/agent": "./dist/agent.js",
|
|
11
|
+
"./dist/types": "./dist/types.js"
|
|
12
|
+
},
|
|
7
13
|
"type": "module",
|
|
8
14
|
"scripts": {
|
|
9
15
|
"build": "tsc",
|
|
10
16
|
"test": "node --loader ts-node/esm test/handshake.spec.ts"
|
|
11
17
|
},
|
|
12
18
|
"repository": {
|
|
19
|
+
"license": "Apache-2.0",
|
|
13
20
|
"type": "git",
|
|
14
21
|
"url": "https://github.com/aamp-protocol/aamp.git"
|
|
15
22
|
},
|
package/src/publisher.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { HEADERS, MAX_CLOCK_SKEW_MS, WELL_KNOWN_AGENT_PATH } from './constants.j
|
|
|
6
6
|
import { exportPublicKey, signData, verifySignature } from './crypto.js';
|
|
7
7
|
import { AccessPolicy, AccessPurpose, AgentIdentityManifest, ContentOrigin, EvaluationResult, IdentityCache, SignedAccessRequest, UnauthenticatedStrategy } from './types.js';
|
|
8
8
|
import { verifyJwt } from './proof.js';
|
|
9
|
+
import { jwtVerify, createRemoteJWKSet } from 'jose';
|
|
9
10
|
|
|
10
11
|
interface VerificationResult {
|
|
11
12
|
allowed: boolean;
|
|
@@ -248,6 +249,24 @@ export class AAMPPublisher {
|
|
|
248
249
|
if (requestHeader.purpose === AccessPurpose.CRAWL_TRAINING && !this.policy.allowTraining) {
|
|
249
250
|
return { allowed: false, status: 403, reason: 'POLICY_DENIED: Training not allowed.', visitorType: 'VERIFIED_AGENT' };
|
|
250
251
|
}
|
|
252
|
+
|
|
253
|
+
// 2. BROKER CHECK (New v1.1)
|
|
254
|
+
if (this.policy.monetization?.brokerUrl) {
|
|
255
|
+
const brokerUrl = this.policy.monetization.brokerUrl;
|
|
256
|
+
|
|
257
|
+
if (!paymentCredential) {
|
|
258
|
+
return { allowed: false, status: 402, reason: "PAYMENT_REQUIRED: Missing Broker Credential", visitorType: 'UNIDENTIFIED_BOT' };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const isValid = await this.verifyBrokerCred(paymentCredential, brokerUrl);
|
|
262
|
+
|
|
263
|
+
if (!isValid) {
|
|
264
|
+
return { allowed: false, status: 403, reason: "PAYMENT_DENIED: Invalid Broker Token", visitorType: 'UNIDENTIFIED_BOT' };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// If valid, we record the "Proof Used" so we can settle later
|
|
268
|
+
return { allowed: true, status: 200, reason: "AAMP_PAID", visitorType: "VERIFIED_AGENT", proofUsed: `BROKER_JWT:${paymentCredential.slice(0, 10)}...` };
|
|
269
|
+
}
|
|
251
270
|
if (requestHeader.purpose === AccessPurpose.RAG_RETRIEVAL && !this.policy.allowRAG) {
|
|
252
271
|
return { allowed: false, status: 403, reason: 'POLICY_DENIED: RAG not allowed.', visitorType: 'VERIFIED_AGENT' };
|
|
253
272
|
}
|
|
@@ -352,7 +371,7 @@ export class AAMPPublisher {
|
|
|
352
371
|
}
|
|
353
372
|
|
|
354
373
|
// Return verified status so handleAgentStrict can proceed to Policy Check
|
|
355
|
-
return { allowed: true, reason: 'OK', identityVerified:
|
|
374
|
+
return { allowed: true, reason: 'OK', identityVerified: identityVerified };
|
|
356
375
|
}
|
|
357
376
|
|
|
358
377
|
private async verifyDnsBinding(domain: string, requestKeySpki: string): Promise<boolean> {
|
|
@@ -398,6 +417,30 @@ export class AAMPPublisher {
|
|
|
398
417
|
}
|
|
399
418
|
}
|
|
400
419
|
|
|
420
|
+
/**
|
|
421
|
+
* NEW: Verify a Broker-Issued Token (JWT)
|
|
422
|
+
* Checks if the request contains a valid "Visa" from the Broker.
|
|
423
|
+
*/
|
|
424
|
+
private async verifyBrokerCred(credential: string, brokerUrl: string): Promise<boolean> {
|
|
425
|
+
try {
|
|
426
|
+
// 1. Fetch Broker's Public Keys (JWKS)
|
|
427
|
+
const JWKS = createRemoteJWKSet(new URL(`${brokerUrl}/.well-known/jwks.json`));
|
|
428
|
+
|
|
429
|
+
// 2. Verify the Token Signature
|
|
430
|
+
const { payload } = await jwtVerify(credential, JWKS, {
|
|
431
|
+
issuer: brokerUrl, // Ensure it came from THE Broker
|
|
432
|
+
clockTolerance: 5 // Allow 5s clock skew
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
console.log(`[BROKER] 💰 Valid Payment Token from ${payload.iss} for amount ${payload.amount}`);
|
|
436
|
+
return true;
|
|
437
|
+
|
|
438
|
+
} catch (e: any) {
|
|
439
|
+
console.warn(`[BROKER] ❌ Invalid Token:`, e.message);
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
401
444
|
private isDomain(s: string): boolean {
|
|
402
445
|
// Basic regex, allows localhost with ports
|
|
403
446
|
return /^[a-zA-Z0-9.-]+(:\d+)?$/.test(s) || /^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(s);
|
package/src/types.ts
CHANGED
|
@@ -62,7 +62,11 @@ export interface MonetizationConfig {
|
|
|
62
62
|
issuer: string; // e.g. "https://accounts.google.com"
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
-
// Method 3:
|
|
65
|
+
// Method 3: Broker Integration (NEW)
|
|
66
|
+
// For third-party clearing houses (AdSense for Data)
|
|
67
|
+
brokerUrl?: string; // e.g. "https://broker.aamp.network"
|
|
68
|
+
|
|
69
|
+
// Method 4: Payment Credentials (Unified JWT)
|
|
66
70
|
// Verifies "x-aamp-credential" for Broker or Direct payments.
|
|
67
71
|
paymentConfig?: {
|
|
68
72
|
jwksUrl: string; // e.g. "https://my-site.com/.well-known/jwks.json"
|
package/aamp-protocol-1.1.5.tgz
DELETED
|
Binary file
|