@kya-os/mcp 1.5.0 → 1.6.0
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/CHANGELOG.md +67 -0
- package/dist/authz/accountability.d.ts +35 -0
- package/dist/authz/accountability.d.ts.map +1 -0
- package/dist/authz/accountability.js +28 -0
- package/dist/authz/accountability.js.map +1 -0
- package/dist/authz/adapter.d.ts +47 -0
- package/dist/authz/adapter.d.ts.map +1 -0
- package/dist/authz/adapter.js +10 -0
- package/dist/authz/adapter.js.map +1 -0
- package/dist/authz/examples/inmemory-oidc.d.ts +29 -0
- package/dist/authz/examples/inmemory-oidc.d.ts.map +1 -0
- package/dist/authz/examples/inmemory-oidc.js +68 -0
- package/dist/authz/examples/inmemory-oidc.js.map +1 -0
- package/dist/authz/index.d.ts +19 -0
- package/dist/authz/index.d.ts.map +1 -0
- package/dist/authz/index.js +19 -0
- package/dist/authz/index.js.map +1 -0
- package/dist/authz/oidc/authorize.d.ts +25 -0
- package/dist/authz/oidc/authorize.d.ts.map +1 -0
- package/dist/authz/oidc/authorize.js +24 -0
- package/dist/authz/oidc/authorize.js.map +1 -0
- package/dist/authz/oidc/metadata.d.ts +43 -0
- package/dist/authz/oidc/metadata.d.ts.map +1 -0
- package/dist/authz/oidc/metadata.js +32 -0
- package/dist/authz/oidc/metadata.js.map +1 -0
- package/dist/authz/oidc/oidc-adapter.d.ts +52 -0
- package/dist/authz/oidc/oidc-adapter.d.ts.map +1 -0
- package/dist/authz/oidc/oidc-adapter.js +131 -0
- package/dist/authz/oidc/oidc-adapter.js.map +1 -0
- package/dist/authz/oidc/pkce.d.ts +20 -0
- package/dist/authz/oidc/pkce.d.ts.map +1 -0
- package/dist/authz/oidc/pkce.js +29 -0
- package/dist/authz/oidc/pkce.js.map +1 -0
- package/dist/authz/registry.d.ts +29 -0
- package/dist/authz/registry.d.ts.map +1 -0
- package/dist/authz/registry.js +48 -0
- package/dist/authz/registry.js.map +1 -0
- package/dist/authz/requirement.d.ts +38 -0
- package/dist/authz/requirement.d.ts.map +1 -0
- package/dist/authz/requirement.js +45 -0
- package/dist/authz/requirement.js.map +1 -0
- package/dist/delegation/chain-enforcement.d.ts +86 -0
- package/dist/delegation/chain-enforcement.d.ts.map +1 -0
- package/dist/delegation/chain-enforcement.js +224 -0
- package/dist/delegation/chain-enforcement.js.map +1 -0
- package/dist/delegation/holder-binding.d.ts +128 -0
- package/dist/delegation/holder-binding.d.ts.map +1 -0
- package/dist/delegation/holder-binding.js +175 -0
- package/dist/delegation/holder-binding.js.map +1 -0
- package/dist/delegation/index.d.ts +2 -0
- package/dist/delegation/index.d.ts.map +1 -1
- package/dist/delegation/index.js +2 -0
- package/dist/delegation/index.js.map +1 -1
- package/dist/errors.d.ts +1 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +1 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/with-kya-os.d.ts +35 -1
- package/dist/middleware/with-kya-os.d.ts.map +1 -1
- package/dist/middleware/with-kya-os.js +94 -192
- package/dist/middleware/with-kya-os.js.map +1 -1
- package/dist/providers/grant-store.d.ts +98 -0
- package/dist/providers/grant-store.d.ts.map +1 -0
- package/dist/providers/grant-store.js +92 -0
- package/dist/providers/grant-store.js.map +1 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/runtime-fetch.d.ts +14 -0
- package/dist/providers/runtime-fetch.d.ts.map +1 -1
- package/dist/providers/runtime-fetch.js +22 -0
- package/dist/providers/runtime-fetch.js.map +1 -1
- package/dist/providers/web-crypto.d.ts +35 -0
- package/dist/providers/web-crypto.d.ts.map +1 -0
- package/dist/providers/web-crypto.js +91 -0
- package/dist/providers/web-crypto.js.map +1 -0
- package/package.json +25 -16
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { base64url } from 'jose';
|
|
2
|
+
import { createNeedsAuthorizationError, } from '../../types/protocol.js';
|
|
3
|
+
import { requirementMatchesAdapter } from '../adapter.js';
|
|
4
|
+
import { buildAuthorizeUrl } from './authorize.js';
|
|
5
|
+
import { computeS256Challenge } from './pkce.js';
|
|
6
|
+
/**
|
|
7
|
+
* Reference generic-OIDC authorization-server adapter.
|
|
8
|
+
*
|
|
9
|
+
* Implements {@link AuthorizationServerAdapter} for a standards-only OpenID
|
|
10
|
+
* Connect / OAuth 2.1 provider. No named vendor identity provider appears
|
|
11
|
+
* here; concrete commercial providers are downstream adapters binding the same
|
|
12
|
+
* port. The pure pieces (authorize URL, PKCE) run inline; the single IdP HTTP
|
|
13
|
+
* call (token
|
|
14
|
+
* exchange) goes through an injectable fetch seam, so the adapter is fully
|
|
15
|
+
* deterministic under test with no network.
|
|
16
|
+
*
|
|
17
|
+
* The PKCE code verifier is held server-side keyed by the resume token and is
|
|
18
|
+
* never placed in the authorization URL — only the S256 challenge travels.
|
|
19
|
+
*/
|
|
20
|
+
export class GenericOidcAdapter {
|
|
21
|
+
config;
|
|
22
|
+
type = 'oauth';
|
|
23
|
+
pending = new Map();
|
|
24
|
+
fetchImpl;
|
|
25
|
+
constructor(config) {
|
|
26
|
+
this.config = config;
|
|
27
|
+
this.fetchImpl = config.fetchImpl ?? ((url, init) => fetch(url, init));
|
|
28
|
+
}
|
|
29
|
+
isRequired(protection) {
|
|
30
|
+
return requirementMatchesAdapter(this.type, protection);
|
|
31
|
+
}
|
|
32
|
+
async initiateFlow(params) {
|
|
33
|
+
const requiredScopes = params.protection.requirement.type === 'oauth'
|
|
34
|
+
? (params.protection.requirement.requiredScopes ?? this.config.scopes)
|
|
35
|
+
: this.config.scopes;
|
|
36
|
+
const scopes = unique([...this.config.scopes, ...requiredScopes]);
|
|
37
|
+
const codeVerifier = randomToken(32);
|
|
38
|
+
const codeChallenge = await computeS256Challenge(codeVerifier);
|
|
39
|
+
const resumeToken = randomToken(24);
|
|
40
|
+
this.pending.set(resumeToken, {
|
|
41
|
+
agentDid: params.agentDid,
|
|
42
|
+
scopes,
|
|
43
|
+
state: params.state,
|
|
44
|
+
codeVerifier,
|
|
45
|
+
redirectUri: params.redirectUri,
|
|
46
|
+
});
|
|
47
|
+
const authorizationUrl = buildAuthorizeUrl({
|
|
48
|
+
authorizationEndpoint: this.config.authorizationEndpoint,
|
|
49
|
+
clientId: this.config.clientId,
|
|
50
|
+
redirectUri: params.redirectUri,
|
|
51
|
+
scopes,
|
|
52
|
+
state: params.state,
|
|
53
|
+
codeChallenge,
|
|
54
|
+
resource: this.config.resource,
|
|
55
|
+
});
|
|
56
|
+
return createNeedsAuthorizationError({
|
|
57
|
+
message: `Authorization required for "${params.protection.toolName}".`,
|
|
58
|
+
authorizationUrl,
|
|
59
|
+
resumeToken,
|
|
60
|
+
expiresAt: nowMs() + (this.config.resumeTokenTtlMs ?? 600_000),
|
|
61
|
+
scopes,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async verifyAuthorization(flowState, result) {
|
|
65
|
+
const pending = this.pending.get(flowState);
|
|
66
|
+
if (!pending) {
|
|
67
|
+
return { valid: false, reason: 'unknown or expired resume token' };
|
|
68
|
+
}
|
|
69
|
+
const { code, state } = (result ?? {});
|
|
70
|
+
if (!code) {
|
|
71
|
+
return { valid: false, reason: 'missing authorization code' };
|
|
72
|
+
}
|
|
73
|
+
if (state !== pending.state) {
|
|
74
|
+
return { valid: false, reason: 'state mismatch' };
|
|
75
|
+
}
|
|
76
|
+
const body = new URLSearchParams({
|
|
77
|
+
grant_type: 'authorization_code',
|
|
78
|
+
code,
|
|
79
|
+
redirect_uri: pending.redirectUri,
|
|
80
|
+
client_id: this.config.clientId,
|
|
81
|
+
code_verifier: pending.codeVerifier,
|
|
82
|
+
});
|
|
83
|
+
if (this.config.resource)
|
|
84
|
+
body.set('resource', this.config.resource);
|
|
85
|
+
if (this.config.clientSecret)
|
|
86
|
+
body.set('client_secret', this.config.clientSecret);
|
|
87
|
+
let token;
|
|
88
|
+
try {
|
|
89
|
+
const response = await this.fetchImpl(this.config.tokenEndpoint, {
|
|
90
|
+
method: 'POST',
|
|
91
|
+
headers: { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' },
|
|
92
|
+
body: body.toString(),
|
|
93
|
+
});
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
return { valid: false, reason: `token endpoint returned ${response.status}` };
|
|
96
|
+
}
|
|
97
|
+
token = (await response.json());
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
return { valid: false, reason: `token exchange failed: ${error.message}` };
|
|
101
|
+
}
|
|
102
|
+
// One-time use: a resume token is consumed on verification.
|
|
103
|
+
this.pending.delete(flowState);
|
|
104
|
+
const grantedScopes = token.scope ? token.scope.split(' ') : pending.scopes;
|
|
105
|
+
return {
|
|
106
|
+
valid: true,
|
|
107
|
+
credential: {
|
|
108
|
+
agent_did: pending.agentDid,
|
|
109
|
+
user_did: '',
|
|
110
|
+
scopes: grantedScopes,
|
|
111
|
+
authorization: { type: 'oauth', provider: 'generic-oidc' },
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/** Test/inspection seam: the pending code verifier for a resume token, if any. */
|
|
116
|
+
pendingVerifierFor(resumeToken) {
|
|
117
|
+
return this.pending.get(resumeToken)?.codeVerifier;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function randomToken(byteLength) {
|
|
121
|
+
const bytes = new Uint8Array(byteLength);
|
|
122
|
+
globalThis.crypto.getRandomValues(bytes);
|
|
123
|
+
return base64url.encode(bytes);
|
|
124
|
+
}
|
|
125
|
+
function unique(values) {
|
|
126
|
+
return [...new Set(values)];
|
|
127
|
+
}
|
|
128
|
+
function nowMs() {
|
|
129
|
+
return Date.now();
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=oidc-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oidc-adapter.js","sourceRoot":"","sources":["../../../src/authz/oidc/oidc-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PKCE (RFC 7636), S256 only.
|
|
3
|
+
*
|
|
4
|
+
* KYA-OS mandates the S256 challenge method — `plain` is never accepted. These
|
|
5
|
+
* helpers are runtime-neutral and dependency-free beyond jose's base64url and
|
|
6
|
+
* the Web Crypto API (available in Node 20+, edge runtimes, and browsers). No
|
|
7
|
+
* Node-specific import, matching the package's runtime-neutral convention.
|
|
8
|
+
*/
|
|
9
|
+
export type S256 = 'S256';
|
|
10
|
+
/** True only for the S256 challenge method. */
|
|
11
|
+
export declare function isS256ChallengeMethod(method: string): method is S256;
|
|
12
|
+
/** Compute the S256 code challenge for a verifier: BASE64URL(SHA-256(verifier)). */
|
|
13
|
+
export declare function computeS256Challenge(codeVerifier: string): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Verify a code verifier against its S256 challenge. Returns false on any
|
|
16
|
+
* mismatch; never throws. The compare is length-checked and constant-time over
|
|
17
|
+
* the challenge string.
|
|
18
|
+
*/
|
|
19
|
+
export declare function verifyS256Challenge(codeVerifier: string, codeChallenge: string): Promise<boolean>;
|
|
20
|
+
//# sourceMappingURL=pkce.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.d.ts","sourceRoot":"","sources":["../../../src/authz/oidc/pkce.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,MAAM,MAAM,IAAI,GAAG,MAAM,CAAC;AAE1B,+CAA+C;AAC/C,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,IAAI,CAEpE;AAED,oFAAoF;AACpF,wBAAsB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAGhF;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,OAAO,CAAC,CAGlB"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { base64url } from 'jose';
|
|
2
|
+
/** True only for the S256 challenge method. */
|
|
3
|
+
export function isS256ChallengeMethod(method) {
|
|
4
|
+
return method === 'S256';
|
|
5
|
+
}
|
|
6
|
+
/** Compute the S256 code challenge for a verifier: BASE64URL(SHA-256(verifier)). */
|
|
7
|
+
export async function computeS256Challenge(codeVerifier) {
|
|
8
|
+
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(codeVerifier));
|
|
9
|
+
return base64url.encode(new Uint8Array(digest));
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Verify a code verifier against its S256 challenge. Returns false on any
|
|
13
|
+
* mismatch; never throws. The compare is length-checked and constant-time over
|
|
14
|
+
* the challenge string.
|
|
15
|
+
*/
|
|
16
|
+
export async function verifyS256Challenge(codeVerifier, codeChallenge) {
|
|
17
|
+
const expected = await computeS256Challenge(codeVerifier);
|
|
18
|
+
return timingSafeEqual(expected, codeChallenge);
|
|
19
|
+
}
|
|
20
|
+
/** Length-checked constant-time string compare. */
|
|
21
|
+
function timingSafeEqual(a, b) {
|
|
22
|
+
if (a.length !== b.length)
|
|
23
|
+
return false;
|
|
24
|
+
let diff = 0;
|
|
25
|
+
for (let i = 0; i < a.length; i++)
|
|
26
|
+
diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
27
|
+
return diff === 0;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=pkce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../../src/authz/oidc/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAajC,+CAA+C;AAC/C,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,OAAO,MAAM,KAAK,MAAM,CAAC;AAC3B,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,YAAoB;IAC7D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7F,OAAO,SAAS,CAAC,MAAM,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,YAAoB,EACpB,aAAqB;IAErB,MAAM,QAAQ,GAAG,MAAM,oBAAoB,CAAC,YAAY,CAAC,CAAC;IAC1D,OAAO,eAAe,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;AAClD,CAAC;AAED,mDAAmD;AACnD,SAAS,eAAe,CAAC,CAAS,EAAE,CAAS;IAC3C,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,IAAI,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC7E,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AuthorizationServerAdapter } from './adapter.js';
|
|
2
|
+
import type { AuthorizationRequirement, ToolProtection } from './requirement.js';
|
|
3
|
+
/**
|
|
4
|
+
* Routes a tool's protection to exactly one {@link AuthorizationServerAdapter},
|
|
5
|
+
* keyed by requirement type. Mirrors the provider-registry lifecycle (register
|
|
6
|
+
* / get / list / resolve / seal) so the authorization seam composes the same
|
|
7
|
+
* pluggable, sealed way the rest of the protocol does. In-memory and
|
|
8
|
+
* dependency-free.
|
|
9
|
+
*/
|
|
10
|
+
export declare class AuthorizationServerRegistry {
|
|
11
|
+
private readonly adapters;
|
|
12
|
+
private sealed;
|
|
13
|
+
/** Register an adapter for its requirement type. Throws on duplicate or when sealed. */
|
|
14
|
+
register(adapter: AuthorizationServerAdapter): void;
|
|
15
|
+
/** The adapter registered for a requirement type, if any. */
|
|
16
|
+
get(type: AuthorizationRequirement['type']): AuthorizationServerAdapter | undefined;
|
|
17
|
+
/** All registered adapters, in registration order. */
|
|
18
|
+
list(): AuthorizationServerAdapter[];
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the adapter that must run for a tool protection. Returns undefined
|
|
21
|
+
* when the tool needs no authorization (`type: 'none'`) or no adapter is
|
|
22
|
+
* registered for its requirement type.
|
|
23
|
+
*/
|
|
24
|
+
resolve(protection: ToolProtection): AuthorizationServerAdapter | undefined;
|
|
25
|
+
/** Freeze the registry; subsequent registration throws. */
|
|
26
|
+
seal(): void;
|
|
27
|
+
isSealed(): boolean;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/authz/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,KAAK,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEjF;;;;;;GAMG;AACH,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2E;IACpG,OAAO,CAAC,MAAM,CAAS;IAEvB,wFAAwF;IACxF,QAAQ,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI;IAUnD,6DAA6D;IAC7D,GAAG,CAAC,IAAI,EAAE,wBAAwB,CAAC,MAAM,CAAC,GAAG,0BAA0B,GAAG,SAAS;IAInF,sDAAsD;IACtD,IAAI,IAAI,0BAA0B,EAAE;IAIpC;;;;OAIG;IACH,OAAO,CAAC,UAAU,EAAE,cAAc,GAAG,0BAA0B,GAAG,SAAS;IAM3E,2DAA2D;IAC3D,IAAI,IAAI,IAAI;IAIZ,QAAQ,IAAI,OAAO;CAGpB"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Routes a tool's protection to exactly one {@link AuthorizationServerAdapter},
|
|
3
|
+
* keyed by requirement type. Mirrors the provider-registry lifecycle (register
|
|
4
|
+
* / get / list / resolve / seal) so the authorization seam composes the same
|
|
5
|
+
* pluggable, sealed way the rest of the protocol does. In-memory and
|
|
6
|
+
* dependency-free.
|
|
7
|
+
*/
|
|
8
|
+
export class AuthorizationServerRegistry {
|
|
9
|
+
adapters = new Map();
|
|
10
|
+
sealed = false;
|
|
11
|
+
/** Register an adapter for its requirement type. Throws on duplicate or when sealed. */
|
|
12
|
+
register(adapter) {
|
|
13
|
+
if (this.sealed) {
|
|
14
|
+
throw new Error('AuthorizationServerRegistry is sealed; cannot register further adapters.');
|
|
15
|
+
}
|
|
16
|
+
if (this.adapters.has(adapter.type)) {
|
|
17
|
+
throw new Error(`An adapter for type "${adapter.type}" is already registered.`);
|
|
18
|
+
}
|
|
19
|
+
this.adapters.set(adapter.type, adapter);
|
|
20
|
+
}
|
|
21
|
+
/** The adapter registered for a requirement type, if any. */
|
|
22
|
+
get(type) {
|
|
23
|
+
return this.adapters.get(type);
|
|
24
|
+
}
|
|
25
|
+
/** All registered adapters, in registration order. */
|
|
26
|
+
list() {
|
|
27
|
+
return [...this.adapters.values()];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the adapter that must run for a tool protection. Returns undefined
|
|
31
|
+
* when the tool needs no authorization (`type: 'none'`) or no adapter is
|
|
32
|
+
* registered for its requirement type.
|
|
33
|
+
*/
|
|
34
|
+
resolve(protection) {
|
|
35
|
+
if (protection.requirement.type === 'none')
|
|
36
|
+
return undefined;
|
|
37
|
+
const adapter = this.adapters.get(protection.requirement.type);
|
|
38
|
+
return adapter?.isRequired(protection) ? adapter : undefined;
|
|
39
|
+
}
|
|
40
|
+
/** Freeze the registry; subsequent registration throws. */
|
|
41
|
+
seal() {
|
|
42
|
+
this.sealed = true;
|
|
43
|
+
}
|
|
44
|
+
isSealed() {
|
|
45
|
+
return this.sealed;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/authz/registry.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,MAAM,OAAO,2BAA2B;IACrB,QAAQ,GAAG,IAAI,GAAG,EAAgE,CAAC;IAC5F,MAAM,GAAG,KAAK,CAAC;IAEvB,wFAAwF;IACxF,QAAQ,CAAC,OAAmC;QAC1C,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,IAAI,0BAA0B,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAED,6DAA6D;IAC7D,GAAG,CAAC,IAAsC;QACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,sDAAsD;IACtD,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACH,OAAO,CAAC,UAA0B;QAChC,IAAI,UAAU,CAAC,WAAW,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,SAAS,CAAC;QAC7D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC/D,OAAO,OAAO,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/D,CAAC;IAED,2DAA2D;IAC3D,IAAI;QACF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;IACrB,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const AuthorizationRequirementSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
3
|
+
type: z.ZodLiteral<"oauth">;
|
|
4
|
+
provider: z.ZodString;
|
|
5
|
+
requiredScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
6
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
7
|
+
type: z.ZodLiteral<"mdl">;
|
|
8
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
9
|
+
type: z.ZodLiteral<"idv">;
|
|
10
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
11
|
+
type: z.ZodLiteral<"credential">;
|
|
12
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
13
|
+
type: z.ZodLiteral<"none">;
|
|
14
|
+
}, z.core.$strip>], "type">;
|
|
15
|
+
export type AuthorizationRequirement = z.infer<typeof AuthorizationRequirementSchema>;
|
|
16
|
+
/**
|
|
17
|
+
* Binds a tool to the authorization it requires. The PEP consults the
|
|
18
|
+
* requirement before dispatching a tool, and an adapter turns an unmet
|
|
19
|
+
* requirement into a `needs_authorization` challenge.
|
|
20
|
+
*/
|
|
21
|
+
export declare const ToolProtectionSchema: z.ZodObject<{
|
|
22
|
+
toolName: z.ZodString;
|
|
23
|
+
requirement: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
24
|
+
type: z.ZodLiteral<"oauth">;
|
|
25
|
+
provider: z.ZodString;
|
|
26
|
+
requiredScopes: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
27
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
28
|
+
type: z.ZodLiteral<"mdl">;
|
|
29
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
30
|
+
type: z.ZodLiteral<"idv">;
|
|
31
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
32
|
+
type: z.ZodLiteral<"credential">;
|
|
33
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
34
|
+
type: z.ZodLiteral<"none">;
|
|
35
|
+
}, z.core.$strip>], "type">;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
export type ToolProtection = z.infer<typeof ToolProtectionSchema>;
|
|
38
|
+
//# sourceMappingURL=requirement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirement.d.ts","sourceRoot":"","sources":["../../src/authz/requirement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+BxB,eAAO,MAAM,8BAA8B;;;;;;;;;;;;2BAMzC,CAAC;AAEH,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAEtF;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;iBAG/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Authorization requirement vocabulary.
|
|
4
|
+
*
|
|
5
|
+
* An {@link AuthorizationRequirement} describes *what kind* of authorization a
|
|
6
|
+
* tool needs, independent of any concrete authorization server. It is the
|
|
7
|
+
* neutral input an {@link AuthorizationServerAdapter} dispatches on — the same
|
|
8
|
+
* separation the policy layer draws between a neutral request and a pluggable
|
|
9
|
+
* engine. Concrete adapters (a generic-OIDC reference adapter ships in this
|
|
10
|
+
* package; vendor adapters live downstream) implement the behavior for a given
|
|
11
|
+
* `type`.
|
|
12
|
+
*
|
|
13
|
+
* The variants mirror the authorization methods the protocol anticipates:
|
|
14
|
+
* `oauth` (an authorization-code/OIDC flow), `mdl` (an ISO mDL presentation),
|
|
15
|
+
* `idv` (an identity-verification flow), `credential` (a directly held
|
|
16
|
+
* verifiable credential), and `none` (no authorization required).
|
|
17
|
+
*/
|
|
18
|
+
const oauthRequirement = z.object({
|
|
19
|
+
type: z.literal('oauth'),
|
|
20
|
+
/** The provider id an adapter registry resolves to a concrete adapter. */
|
|
21
|
+
provider: z.string().min(1),
|
|
22
|
+
/** Scopes the flow must obtain; omitted means the adapter's default set. */
|
|
23
|
+
requiredScopes: z.array(z.string()).optional(),
|
|
24
|
+
});
|
|
25
|
+
const mdlRequirement = z.object({ type: z.literal('mdl') });
|
|
26
|
+
const idvRequirement = z.object({ type: z.literal('idv') });
|
|
27
|
+
const credentialRequirement = z.object({ type: z.literal('credential') });
|
|
28
|
+
const noneRequirement = z.object({ type: z.literal('none') });
|
|
29
|
+
export const AuthorizationRequirementSchema = z.discriminatedUnion('type', [
|
|
30
|
+
oauthRequirement,
|
|
31
|
+
mdlRequirement,
|
|
32
|
+
idvRequirement,
|
|
33
|
+
credentialRequirement,
|
|
34
|
+
noneRequirement,
|
|
35
|
+
]);
|
|
36
|
+
/**
|
|
37
|
+
* Binds a tool to the authorization it requires. The PEP consults the
|
|
38
|
+
* requirement before dispatching a tool, and an adapter turns an unmet
|
|
39
|
+
* requirement into a `needs_authorization` challenge.
|
|
40
|
+
*/
|
|
41
|
+
export const ToolProtectionSchema = z.object({
|
|
42
|
+
toolName: z.string().min(1),
|
|
43
|
+
requirement: AuthorizationRequirementSchema,
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=requirement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirement.js","sourceRoot":"","sources":["../../src/authz/requirement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IAChC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,4EAA4E;IAC5E,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CAC/C,CAAC,CAAC;AAEH,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC5D,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC5D,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AAC1E,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AAE9D,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE;IACzE,gBAAgB;IAChB,cAAc;IACd,cAAc;IACd,qBAAqB;IACrB,eAAe;CAChB,CAAC,CAAC;AAIH;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3B,WAAW,EAAE,8BAA8B;CAC5C,CAAC,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Delegation chain enforcement — framework-agnostic core (E3 · #2888).
|
|
3
|
+
*
|
|
4
|
+
* The leaf→root chain walk, scope-attenuation, audience binding, confused-deputy
|
|
5
|
+
* guard (KYA-OS §11.6), and ancestor-revocation rules, lifted out of the
|
|
6
|
+
* `with-kya-os` middleware closure so the SAME logic runs in every host (MCP
|
|
7
|
+
* middleware, an HTTP PEP, the conformance harness) against one implementation
|
|
8
|
+
* rather than a per-transport fork.
|
|
9
|
+
*
|
|
10
|
+
* Dependencies are injected as ports (interface-first): a per-credential
|
|
11
|
+
* verifier, an optional ancestor resolver, and an optional graph-backed
|
|
12
|
+
* `RevocationChecker`. Nothing here imports a transport or framework.
|
|
13
|
+
*/
|
|
14
|
+
import { type DelegationCredential } from "../types/protocol.js";
|
|
15
|
+
/** Union of a credential's delegation scopes and its constraint scopes. */
|
|
16
|
+
export declare function getDelegationScopes(credential: DelegationCredential): string[];
|
|
17
|
+
/**
|
|
18
|
+
* A child re-delegation may only narrow (attenuate) its parent's authority.
|
|
19
|
+
* Enforces flat-scope subset AND crisp-matcher subset (by matcher+resource),
|
|
20
|
+
* failing closed on any widening. Pure; never throws.
|
|
21
|
+
*/
|
|
22
|
+
export declare function validateScopeAttenuation(parentCredential: DelegationCredential, childCredential: DelegationCredential): {
|
|
23
|
+
valid: boolean;
|
|
24
|
+
reason?: string;
|
|
25
|
+
};
|
|
26
|
+
/** Per-credential verifier port (signature / schema / expiry / own status). */
|
|
27
|
+
export interface DelegationCredentialVerifierPort {
|
|
28
|
+
verifyDelegationCredential(credential: DelegationCredential, options?: {
|
|
29
|
+
skipSignature?: boolean;
|
|
30
|
+
}): Promise<{
|
|
31
|
+
valid: boolean;
|
|
32
|
+
reason?: string;
|
|
33
|
+
}>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Graph-backed ancestor-revocation port. The reference adapter is
|
|
37
|
+
* `CascadingRevocationManager` (./cascading-revocation), whose `isRevoked()`
|
|
38
|
+
* walks root→target over the delegation graph + StatusList, detecting a
|
|
39
|
+
* cascade-revoked ANCESTOR independently of how the chain was resolved.
|
|
40
|
+
*
|
|
41
|
+
* Wiring this is the E3.1 correctness fix: the prior closure checked only each
|
|
42
|
+
* credential's OWN `credentialStatus` bit via the resolver, so an ancestor
|
|
43
|
+
* cascade-revocation that hadn't flipped the leaf's own bit could be missed.
|
|
44
|
+
*/
|
|
45
|
+
export interface RevocationChecker {
|
|
46
|
+
isRevoked(delegationId: string): Promise<{
|
|
47
|
+
revoked: boolean;
|
|
48
|
+
reason?: string;
|
|
49
|
+
revokedAncestor?: string;
|
|
50
|
+
}>;
|
|
51
|
+
}
|
|
52
|
+
export interface ChainEnforcementDeps {
|
|
53
|
+
/** The verifying server's DID — every chain credential's audience must include it. */
|
|
54
|
+
serverDid: string;
|
|
55
|
+
/** Per-credential verifier (signature / schema / expiry / own status). */
|
|
56
|
+
verifier: DelegationCredentialVerifierPort;
|
|
57
|
+
/**
|
|
58
|
+
* Resolve ancestor credentials for a re-delegated leaf. May return ancestors
|
|
59
|
+
* only (root→parent) or the full chain (root→leaf). Required when the leaf has
|
|
60
|
+
* a `parentId`.
|
|
61
|
+
*/
|
|
62
|
+
resolveDelegationChain?: (leafCredential: DelegationCredential) => Promise<DelegationCredential[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Whether a StatusList resolver is configured downstream. A credential bearing
|
|
65
|
+
* `credentialStatus` is rejected when false (fail-closed).
|
|
66
|
+
*/
|
|
67
|
+
statusListConfigured: boolean;
|
|
68
|
+
/** Optional graph-backed ancestor-revocation check (see {@link RevocationChecker}). */
|
|
69
|
+
revocationChecker?: RevocationChecker;
|
|
70
|
+
}
|
|
71
|
+
export interface ChainValidationResult {
|
|
72
|
+
valid: boolean;
|
|
73
|
+
reason?: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Validate a delegation credential and (if re-delegated) its full chain:
|
|
77
|
+
* structural shape, per-credential verification, audience binding to the server,
|
|
78
|
+
* the §11.6 re-delegation audience-constraint requirement, parent↔child linkage
|
|
79
|
+
* (parentId + issuerDid==parent.subjectDid), cycle detection, scope attenuation,
|
|
80
|
+
* and — when a {@link RevocationChecker} is supplied — graph-backed ancestor
|
|
81
|
+
* revocation. Never throws on a malformed input; returns `{ valid, reason }`.
|
|
82
|
+
*/
|
|
83
|
+
export declare function validateDelegationChain(leafCredential: DelegationCredential, deps: ChainEnforcementDeps, options?: {
|
|
84
|
+
skipSignature?: boolean;
|
|
85
|
+
}): Promise<ChainValidationResult>;
|
|
86
|
+
//# sourceMappingURL=chain-enforcement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-enforcement.d.ts","sourceRoot":"","sources":["../../src/delegation/chain-enforcement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAEL,KAAK,oBAAoB,EAE1B,MAAM,sBAAsB,CAAC;AAG9B,2EAA2E;AAC3E,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAS9E;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CACtC,gBAAgB,EAAE,oBAAoB,EACtC,eAAe,EAAE,oBAAoB,GACpC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CA8CrC;AAED,+EAA+E;AAC/E,MAAM,WAAW,gCAAgC;IAC/C,0BAA0B,CACxB,UAAU,EAAE,oBAAoB,EAChC,OAAO,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAA;KAAE,GACpC,OAAO,CAAC;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACjD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QACvC,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,oBAAoB;IACnC,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,QAAQ,EAAE,gCAAgC,CAAC;IAC3C;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CACvB,cAAc,EAAE,oBAAoB,KACjC,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;IACrC;;;OAGG;IACH,oBAAoB,EAAE,OAAO,CAAC;IAC9B,uFAAuF;IACvF,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;CACvC;AAED,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,cAAc,EAAE,oBAAoB,EACpC,IAAI,EAAE,oBAAoB,EAC1B,OAAO,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GACpC,OAAO,CAAC,qBAAqB,CAAC,CAkLhC"}
|