@datalayer/personal-agent-protocol 0.0.0-stage → 0.2.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/README.md CHANGED
@@ -1,3 +1,22 @@
1
- # Temporary Holding Version
1
+ # @datalayer/personal-agent-protocol
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ TypeScript SDK for Personal Agent Protocol draft 0.1.
4
+
5
+ ```typescript
6
+ import { discoverCompany } from "@datalayer/personal-agent-protocol";
7
+
8
+ const company = await discoverCompany("example.com");
9
+ ```
10
+
11
+ The current release provides forward-compatible discovery, OAuth, client
12
+ metadata, conversation-event, and Operations v1 models; strict
13
+ duplicate-member rejection; local Direct Sign-In primitives; signed-out
14
+ session start and renewal; and safe company discovery built on Datalayer
15
+ Reactor. It also provides ES256/RS256 JOSE signing and DPoP proof creation and
16
+ verification through the maintained `jose` package. Use
17
+ `buildPapReactor(options, plugins)` to install typed transport, URL-policy,
18
+ protocol-profile, clock, randomness, signer, DPoP proof, protected-key,
19
+ token-store, cache, browser-handoff, and extension-handler contributions, or
20
+ pass an existing Reactor host to `discoverCompany`. Security-dependent
21
+ services have no fallback and fail closed when missing or ambiguous. See the
22
+ repository README for current limits and security guidance.
package/lib/auth.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ import { SecretValue, type RandomBytes } from "./sessions.js";
2
+ export interface DirectSignInOptions {
3
+ readonly authorizationEndpoint: string;
4
+ readonly issuer: string;
5
+ readonly clientId: string;
6
+ readonly redirectUri: string;
7
+ readonly scopes: readonly string[];
8
+ readonly randomBytes?: RandomBytes;
9
+ }
10
+ export interface DirectSignInRequest {
11
+ readonly authorizationUrl: SecretValue;
12
+ readonly issuer: string;
13
+ readonly clientId: string;
14
+ readonly redirectUri: string;
15
+ readonly scopes: readonly string[];
16
+ readonly state: SecretValue;
17
+ readonly codeVerifier: SecretValue;
18
+ }
19
+ export declare function buildDirectSignInRequest(options: DirectSignInOptions): Promise<DirectSignInRequest>;
20
+ export interface DirectSignInCallback {
21
+ readonly code: SecretValue;
22
+ readonly issuer: string;
23
+ }
24
+ export declare function validateDirectSignInCallback(request: DirectSignInRequest, callbackUrl: string): DirectSignInCallback;
25
+ export interface AuthorizationCodeGrantOptions {
26
+ readonly code: string;
27
+ readonly redirectUri: string;
28
+ readonly codeVerifier: string;
29
+ readonly sessionId: string;
30
+ readonly clientId: string;
31
+ readonly clientAssertion: string;
32
+ }
33
+ export declare class AuthorizationCodeGrant {
34
+ readonly code: SecretValue;
35
+ readonly redirectUri: string;
36
+ readonly codeVerifier: SecretValue;
37
+ readonly sessionId: string;
38
+ readonly clientId: string;
39
+ readonly clientAssertion: SecretValue;
40
+ constructor(options: AuthorizationCodeGrantOptions);
41
+ toForm(): URLSearchParams;
42
+ toJSON(): Record<string, unknown>;
43
+ }
44
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,WAAW,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AA6DpF,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,gBAAgB,EAAE,WAAW,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;CACpC;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,mBAAmB,CAAC,CA6B9B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAWD,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,mBAAmB,EAC5B,WAAW,EAAE,MAAM,GAClB,oBAAoB,CAuCtB;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,qBAAa,sBAAsB;IACjC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,WAAW,CAAC;gBAE1B,OAAO,EAAE,6BAA6B;IAYlD,MAAM,IAAI,eAAe;IAazB,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAYlC"}
package/lib/auth.js ADDED
@@ -0,0 +1,168 @@
1
+ import { AuthorizationError } from "./errors.js";
2
+ import { JWT_CLIENT_ASSERTION, SecretValue } from "./sessions.js";
3
+ function defaultRandomBytes(length) {
4
+ if (!globalThis.crypto) {
5
+ throw new AuthorizationError("crypto_unavailable", "Web Crypto is required");
6
+ }
7
+ return globalThis.crypto.getRandomValues(new Uint8Array(length));
8
+ }
9
+ function entropy(length, randomBytes) {
10
+ const value = randomBytes(length);
11
+ if (value.byteLength < length) {
12
+ throw new AuthorizationError("weak_entropy", `Authorization requires ${length * 8} random bits`);
13
+ }
14
+ return value;
15
+ }
16
+ function base64Url(bytes) {
17
+ const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
18
+ let output = "";
19
+ for (let index = 0; index < bytes.length; index += 3) {
20
+ const first = bytes[index] ?? 0;
21
+ const second = bytes[index + 1];
22
+ const third = bytes[index + 2];
23
+ output += alphabet[first >>> 2];
24
+ output += alphabet[((first & 3) << 4) | ((second ?? 0) >>> 4)];
25
+ if (second !== undefined) {
26
+ output += alphabet[((second & 15) << 2) | ((third ?? 0) >>> 6)];
27
+ }
28
+ if (third !== undefined) {
29
+ output += alphabet[third & 63];
30
+ }
31
+ }
32
+ return output;
33
+ }
34
+ function httpsUrl(value, label) {
35
+ let parsed;
36
+ try {
37
+ parsed = new URL(value);
38
+ }
39
+ catch (cause) {
40
+ throw new AuthorizationError("invalid_url", `${label} must be an HTTPS URL`, { cause });
41
+ }
42
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password) {
43
+ throw new AuthorizationError("invalid_url", `${label} must be an HTTPS URL`);
44
+ }
45
+ return parsed;
46
+ }
47
+ function validScopes(values) {
48
+ const scopes = [...new Set(values)];
49
+ const token = /^[\x21\x23-\x5b\x5d-\x7e]+$/;
50
+ if (scopes.length === 0 || scopes.some((scope) => !token.test(scope))) {
51
+ throw new AuthorizationError("invalid_scope", "At least one valid OAuth scope is required");
52
+ }
53
+ return scopes;
54
+ }
55
+ export async function buildDirectSignInRequest(options) {
56
+ const randomBytes = options.randomBytes ?? defaultRandomBytes;
57
+ const state = base64Url(entropy(16, randomBytes));
58
+ const verifier = base64Url(entropy(32, randomBytes));
59
+ const challenge = base64Url(new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier))));
60
+ const endpoint = httpsUrl(options.authorizationEndpoint, "authorizationEndpoint");
61
+ const scopes = validScopes(options.scopes);
62
+ const clientId = httpsUrl(options.clientId, "clientId").toString();
63
+ const redirectUri = httpsUrl(options.redirectUri, "redirectUri").toString();
64
+ const issuer = httpsUrl(options.issuer, "issuer").toString().replace(/\/$/, "");
65
+ endpoint.searchParams.set("response_type", "code");
66
+ endpoint.searchParams.set("client_id", clientId);
67
+ endpoint.searchParams.set("redirect_uri", redirectUri);
68
+ endpoint.searchParams.set("scope", scopes.join(" "));
69
+ endpoint.searchParams.set("state", state);
70
+ endpoint.searchParams.set("code_challenge", challenge);
71
+ endpoint.searchParams.set("code_challenge_method", "S256");
72
+ endpoint.hash = "";
73
+ return {
74
+ authorizationUrl: new SecretValue(endpoint.toString()),
75
+ issuer,
76
+ clientId,
77
+ redirectUri,
78
+ scopes,
79
+ state: new SecretValue(state),
80
+ codeVerifier: new SecretValue(verifier),
81
+ };
82
+ }
83
+ function equalConstantTime(left, right) {
84
+ let difference = left.length ^ right.length;
85
+ const length = Math.max(left.length, right.length);
86
+ for (let index = 0; index < length; index += 1) {
87
+ difference |= (left.charCodeAt(index) || 0) ^ (right.charCodeAt(index) || 0);
88
+ }
89
+ return difference === 0;
90
+ }
91
+ export function validateDirectSignInCallback(request, callbackUrl) {
92
+ const expected = httpsUrl(request.redirectUri, "redirectUri");
93
+ const callback = httpsUrl(callbackUrl, "callbackUrl");
94
+ if (callback.hash) {
95
+ throw new AuthorizationError("invalid_callback", "Authorization callback has a fragment");
96
+ }
97
+ if (callback.origin !== expected.origin || callback.pathname !== expected.pathname) {
98
+ throw new AuthorizationError("redirect_mismatch", "Callback does not match redirect URI");
99
+ }
100
+ for (const [key, value] of expected.searchParams) {
101
+ if (callback.searchParams.get(key) !== value) {
102
+ throw new AuthorizationError("redirect_mismatch", "Callback changed redirect URI parameters");
103
+ }
104
+ }
105
+ for (const key of ["code", "state", "iss", "error"]) {
106
+ if (callback.searchParams.getAll(key).length > 1) {
107
+ throw new AuthorizationError("invalid_callback", "Authorization callback repeats a security parameter");
108
+ }
109
+ }
110
+ if (callback.searchParams.has("error")) {
111
+ throw new AuthorizationError("authorization_denied", "Company did not authorize the request");
112
+ }
113
+ if (!equalConstantTime(callback.searchParams.get("state") ?? "", request.state.reveal())) {
114
+ throw new AuthorizationError("state_mismatch", "Authorization state does not match");
115
+ }
116
+ if (callback.searchParams.get("iss") !== request.issuer) {
117
+ throw new AuthorizationError("issuer_mismatch", "Authorization issuer does not match");
118
+ }
119
+ const code = callback.searchParams.get("code");
120
+ if (!code) {
121
+ throw new AuthorizationError("invalid_callback", "Authorization callback has no code");
122
+ }
123
+ return { code: new SecretValue(code), issuer: request.issuer };
124
+ }
125
+ export class AuthorizationCodeGrant {
126
+ code;
127
+ redirectUri;
128
+ codeVerifier;
129
+ sessionId;
130
+ clientId;
131
+ clientAssertion;
132
+ constructor(options) {
133
+ this.code = new SecretValue(options.code);
134
+ this.redirectUri = httpsUrl(options.redirectUri, "redirectUri").toString();
135
+ this.codeVerifier = new SecretValue(options.codeVerifier);
136
+ if (!/^[A-Za-z0-9_-]{1,256}$/.test(options.sessionId)) {
137
+ throw new AuthorizationError("invalid_session_id", "Invalid PAP session ID");
138
+ }
139
+ this.sessionId = options.sessionId;
140
+ this.clientId = httpsUrl(options.clientId, "clientId").toString();
141
+ this.clientAssertion = new SecretValue(options.clientAssertion);
142
+ }
143
+ toForm() {
144
+ return new URLSearchParams({
145
+ grant_type: "authorization_code",
146
+ code: this.code.reveal(),
147
+ redirect_uri: this.redirectUri,
148
+ code_verifier: this.codeVerifier.reveal(),
149
+ session_id: this.sessionId,
150
+ client_id: this.clientId,
151
+ client_assertion_type: JWT_CLIENT_ASSERTION,
152
+ client_assertion: this.clientAssertion.reveal(),
153
+ });
154
+ }
155
+ toJSON() {
156
+ return {
157
+ grant_type: "authorization_code",
158
+ code: this.code,
159
+ redirect_uri: this.redirectUri,
160
+ code_verifier: this.codeVerifier,
161
+ session_id: this.sessionId,
162
+ client_id: this.clientId,
163
+ client_assertion_type: JWT_CLIENT_ASSERTION,
164
+ client_assertion: this.clientAssertion,
165
+ };
166
+ }
167
+ }
168
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import { type JWK, type KeyInput } from "jose";
2
+ import type { DpopProofProvider, DpopProofRequest, Signer } from "./reactor.js";
3
+ import { SecretValue } from "./sessions.js";
4
+ export type JoseAlgorithm = "ES256" | "RS256";
5
+ export interface JoseSignerOptions {
6
+ readonly privateKey: KeyInput;
7
+ readonly algorithm?: JoseAlgorithm;
8
+ readonly keyId?: string;
9
+ }
10
+ /** Sign PAP assertions with an injected asymmetric private key or handle. */
11
+ export declare class JoseSigner implements Signer {
12
+ #private;
13
+ constructor(options: JoseSignerOptions);
14
+ sign(claims: Readonly<Record<string, unknown>>, _options: {
15
+ readonly purpose: string;
16
+ }): Promise<SecretValue>;
17
+ }
18
+ export interface DpopKeyMaterial {
19
+ readonly privateKey: KeyInput;
20
+ readonly publicJwk: JWK;
21
+ readonly algorithm?: JoseAlgorithm;
22
+ }
23
+ export type DpopKeyResolver = (request: DpopProofRequest) => DpopKeyMaterial | Promise<DpopKeyMaterial>;
24
+ export interface JoseDpopProofProviderOptions {
25
+ readonly resolveKey: DpopKeyResolver;
26
+ readonly now?: () => Date;
27
+ readonly randomBytes?: (length: number) => Uint8Array;
28
+ }
29
+ /** Create fresh RFC 9449 proofs using per-user/company key material. */
30
+ export declare class JoseDpopProofProvider implements DpopProofProvider {
31
+ #private;
32
+ constructor(options: JoseDpopProofProviderOptions);
33
+ create(request: DpopProofRequest): Promise<SecretValue>;
34
+ }
35
+ export interface DpopReplayCache {
36
+ markOnce(key: string, options: {
37
+ readonly expiresAt: Date;
38
+ }): Promise<boolean>;
39
+ }
40
+ export interface VerifyDpopProofOptions {
41
+ readonly method: string;
42
+ readonly url: string;
43
+ readonly replayCache: DpopReplayCache;
44
+ readonly accessToken?: SecretValue;
45
+ readonly nonce?: string;
46
+ readonly now?: Date;
47
+ readonly acceptanceWindowSeconds?: number;
48
+ }
49
+ export interface VerifiedDpopProof {
50
+ readonly jti: string;
51
+ readonly issuedAt: Date;
52
+ readonly publicJwk: JWK;
53
+ readonly keyThumbprint: string;
54
+ }
55
+ /** Verify signature, binding, freshness, nonce, token hash, and replay state. */
56
+ export declare function verifyDpopProof(proof: SecretValue | string, options: VerifyDpopProofOptions): Promise<VerifiedDpopProof>;
57
+ //# sourceMappingURL=crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,GAAG,EAER,KAAK,QAAQ,EACd,MAAM,MAAM,CAAC;AAGd,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,OAAO,CAAC;AAgE9C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,6EAA6E;AAC7E,qBAAa,UAAW,YAAW,MAAM;;gBAK3B,OAAO,EAAE,iBAAiB;IAMhC,IAAI,CACR,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACzC,QAAQ,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GACrC,OAAO,CAAC,WAAW,CAAC;CAcxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;CACpC;AAED,MAAM,MAAM,eAAe,GAAG,CAC5B,OAAO,EAAE,gBAAgB,KACtB,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAEhD,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,UAAU,CAAC;CACvD;AAED,wEAAwE;AACxE,qBAAa,qBAAsB,YAAW,iBAAiB;;gBAKjD,OAAO,EAAE,4BAA4B;IAM3C,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,WAAW,CAAC;CA2B9D;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChF;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAC3C;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC;IACxB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,iFAAiF;AACjF,wBAAsB,eAAe,CACnC,KAAK,EAAE,WAAW,GAAG,MAAM,EAC3B,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,iBAAiB,CAAC,CA6D5B"}
package/lib/crypto.js ADDED
@@ -0,0 +1,188 @@
1
+ import { SignJWT, calculateJwkThumbprint, decodeProtectedHeader, importJWK, jwtVerify, } from "jose";
2
+ import { ProofError } from "./errors.js";
3
+ import { SecretValue } from "./sessions.js";
4
+ const privateJwkMembers = new Set(["d", "p", "q", "dp", "dq", "qi", "oth", "k"]);
5
+ function algorithm(value) {
6
+ if (value !== "ES256" && value !== "RS256") {
7
+ throw new TypeError("PAP JOSE algorithms must be ES256 or RS256");
8
+ }
9
+ return value;
10
+ }
11
+ function publicJwk(value, alg) {
12
+ for (const member of privateJwkMembers) {
13
+ if (member in value) {
14
+ throw new TypeError("DPoP public JWK must not contain private key material");
15
+ }
16
+ }
17
+ const expected = alg === "ES256" ? "EC" : "RSA";
18
+ if (value.kty !== expected)
19
+ throw new TypeError(`${alg} requires a ${expected} public JWK`);
20
+ if (alg === "ES256") {
21
+ if (value.crv !== "P-256" || !value.x || !value.y) {
22
+ throw new TypeError("ES256 requires a complete P-256 public JWK");
23
+ }
24
+ }
25
+ else if (!value.n || !value.e) {
26
+ throw new TypeError("RS256 requires a complete RSA public JWK");
27
+ }
28
+ return { ...value };
29
+ }
30
+ function normalizedHtu(value) {
31
+ let url;
32
+ try {
33
+ url = new URL(value);
34
+ }
35
+ catch (cause) {
36
+ throw new ProofError("invalid_htu", "DPoP target must be an HTTPS URL", { cause });
37
+ }
38
+ if (url.protocol !== "https:" || url.username || url.password) {
39
+ throw new ProofError("invalid_htu", "DPoP target must be an HTTPS URL");
40
+ }
41
+ url.search = "";
42
+ url.hash = "";
43
+ return url.href;
44
+ }
45
+ function base64Url(bytes) {
46
+ let binary = "";
47
+ for (const value of bytes)
48
+ binary += String.fromCharCode(value);
49
+ return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "");
50
+ }
51
+ function randomBytes(length) {
52
+ if (!globalThis.crypto)
53
+ throw new ProofError("crypto_unavailable", "Web Crypto is required");
54
+ return globalThis.crypto.getRandomValues(new Uint8Array(length));
55
+ }
56
+ async function accessTokenHash(token) {
57
+ if (!globalThis.crypto)
58
+ throw new ProofError("crypto_unavailable", "Web Crypto is required");
59
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(token.reveal()));
60
+ return base64Url(new Uint8Array(digest));
61
+ }
62
+ /** Sign PAP assertions with an injected asymmetric private key or handle. */
63
+ export class JoseSigner {
64
+ #privateKey;
65
+ #algorithm;
66
+ #keyId;
67
+ constructor(options) {
68
+ this.#privateKey = options.privateKey;
69
+ this.#algorithm = algorithm(options.algorithm ?? "ES256");
70
+ this.#keyId = options.keyId;
71
+ }
72
+ async sign(claims, _options) {
73
+ try {
74
+ const token = await new SignJWT(claims)
75
+ .setProtectedHeader({
76
+ alg: this.#algorithm,
77
+ typ: "JWT",
78
+ ...(this.#keyId === undefined ? {} : { kid: this.#keyId }),
79
+ })
80
+ .sign(this.#privateKey);
81
+ return new SecretValue(token);
82
+ }
83
+ catch (cause) {
84
+ throw new ProofError("signing_failed", "Could not sign PAP assertion", { cause });
85
+ }
86
+ }
87
+ }
88
+ /** Create fresh RFC 9449 proofs using per-user/company key material. */
89
+ export class JoseDpopProofProvider {
90
+ #resolveKey;
91
+ #now;
92
+ #randomBytes;
93
+ constructor(options) {
94
+ this.#resolveKey = options.resolveKey;
95
+ this.#now = options.now ?? (() => new Date());
96
+ this.#randomBytes = options.randomBytes ?? randomBytes;
97
+ }
98
+ async create(request) {
99
+ const material = await this.#resolveKey(request);
100
+ const alg = algorithm(material.algorithm ?? "ES256");
101
+ const jwk = publicJwk(material.publicJwk, alg);
102
+ const entropy = this.#randomBytes(16);
103
+ if (entropy.byteLength < 16) {
104
+ throw new ProofError("weak_randomness", "DPoP proof IDs require 128 random bits");
105
+ }
106
+ const claims = {
107
+ jti: base64Url(entropy),
108
+ htm: request.method.toUpperCase(),
109
+ htu: normalizedHtu(request.url),
110
+ iat: Math.floor(this.#now().getTime() / 1000),
111
+ ...(request.nonce === undefined ? {} : { nonce: request.nonce }),
112
+ ...(request.accessToken === undefined
113
+ ? {}
114
+ : { ath: await accessTokenHash(request.accessToken) }),
115
+ };
116
+ try {
117
+ const token = await new SignJWT(claims)
118
+ .setProtectedHeader({ typ: "dpop+jwt", alg, jwk })
119
+ .sign(material.privateKey);
120
+ return new SecretValue(token);
121
+ }
122
+ catch (cause) {
123
+ throw new ProofError("signing_failed", "Could not sign DPoP proof", { cause });
124
+ }
125
+ }
126
+ }
127
+ /** Verify signature, binding, freshness, nonce, token hash, and replay state. */
128
+ export async function verifyDpopProof(proof, options) {
129
+ const compact = proof instanceof SecretValue ? proof.reveal() : proof;
130
+ const now = options.now ?? new Date();
131
+ const windowSeconds = options.acceptanceWindowSeconds ?? 60;
132
+ if (!Number.isInteger(windowSeconds) || windowSeconds <= 0) {
133
+ throw new RangeError("acceptanceWindowSeconds must be a positive integer");
134
+ }
135
+ let jwk;
136
+ let payload;
137
+ try {
138
+ const header = decodeProtectedHeader(compact);
139
+ const alg = algorithm(header.alg ?? "");
140
+ if (header.typ !== "dpop+jwt" || typeof header.jwk !== "object") {
141
+ throw new ProofError("invalid_dpop_proof", "DPoP protected header is invalid");
142
+ }
143
+ jwk = publicJwk(header.jwk, alg);
144
+ const key = await importJWK(jwk, alg);
145
+ ({ payload } = await jwtVerify(compact, key, {
146
+ algorithms: [alg],
147
+ typ: "dpop+jwt",
148
+ requiredClaims: ["jti", "htm", "htu", "iat"],
149
+ }));
150
+ }
151
+ catch (cause) {
152
+ if (cause instanceof ProofError)
153
+ throw cause;
154
+ throw new ProofError("invalid_dpop_proof", "DPoP signature or claims are invalid", {
155
+ cause,
156
+ });
157
+ }
158
+ if (typeof payload.jti !== "string" || !payload.jti || typeof payload.iat !== "number") {
159
+ throw new ProofError("invalid_dpop_proof", "DPoP proof identity is invalid");
160
+ }
161
+ const issuedAt = new Date(payload.iat * 1000);
162
+ const difference = Math.abs(now.getTime() - issuedAt.getTime());
163
+ if (difference > windowSeconds * 1000) {
164
+ throw new ProofError("invalid_dpop_proof", "DPoP proof is outside the acceptance window");
165
+ }
166
+ if (payload.htm !== options.method.toUpperCase() || payload.htu !== normalizedHtu(options.url)) {
167
+ throw new ProofError("invalid_dpop_proof", "DPoP proof does not match the request");
168
+ }
169
+ if (options.nonce !== undefined && payload.nonce !== options.nonce) {
170
+ throw new ProofError("use_dpop_nonce", "DPoP proof nonce is missing or invalid");
171
+ }
172
+ if (options.accessToken !== undefined) {
173
+ if (payload.ath !== (await accessTokenHash(options.accessToken))) {
174
+ throw new ProofError("invalid_dpop_proof", "DPoP access-token hash is invalid");
175
+ }
176
+ }
177
+ else if (payload.ath !== undefined) {
178
+ throw new ProofError("invalid_dpop_proof", "Token-endpoint DPoP proof must not contain ath");
179
+ }
180
+ const keyThumbprint = await calculateJwkThumbprint(jwk);
181
+ if (!(await options.replayCache.markOnce(`${keyThumbprint}:${payload.jti}`, {
182
+ expiresAt: new Date(now.getTime() + windowSeconds * 1000),
183
+ }))) {
184
+ throw new ProofError("invalid_dpop_proof", "DPoP proof has already been used");
185
+ }
186
+ return { jti: payload.jti, issuedAt, publicJwk: jwk, keyThumbprint };
187
+ }
188
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,sBAAsB,EACtB,qBAAqB,EACrB,SAAS,EACT,SAAS,GAIV,MAAM,MAAM,CAAC;AAEd,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAI5C,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;AAEjF,SAAS,SAAS,CAAC,KAAa;IAC9B,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QAC3C,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,SAAS,CAAC,KAAU,EAAE,GAAkB;IAC/C,KAAK,MAAM,MAAM,IAAI,iBAAiB,EAAE,CAAC;QACvC,IAAI,MAAM,IAAI,KAAK,EAAE,CAAC;YACpB,MAAM,IAAI,SAAS,CAAC,uDAAuD,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;IAChD,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ;QAAE,MAAM,IAAI,SAAS,CAAC,GAAG,GAAG,eAAe,QAAQ,aAAa,CAAC,CAAC;IAC5F,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;YAClD,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;SAAM,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,SAAS,CAAC,0CAA0C,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,EAAE,GAAG,KAAK,EAAE,CAAC;AACtB,CAAC;AAED,SAAS,aAAa,CAAC,KAAa;IAClC,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,UAAU,CAAC,aAAa,EAAE,kCAAkC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACrF,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9D,MAAM,IAAI,UAAU,CAAC,aAAa,EAAE,kCAAkC,CAAC,CAAC;IAC1E,CAAC;IACD,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC;IAChB,GAAG,CAAC,IAAI,GAAG,EAAE,CAAC;IACd,OAAO,GAAG,CAAC,IAAI,CAAC;AAClB,CAAC;AAED,SAAS,SAAS,CAAC,KAAiB;IAClC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,KAAK,IAAI,KAAK;QAAE,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAChE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACpF,CAAC;AAED,SAAS,WAAW,CAAC,MAAc;IACjC,IAAI,CAAC,UAAU,CAAC,MAAM;QAAE,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,wBAAwB,CAAC,CAAC;IAC7F,OAAO,UAAU,CAAC,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,KAAkB;IAC/C,IAAI,CAAC,UAAU,CAAC,MAAM;QAAE,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,wBAAwB,CAAC,CAAC;IAC7F,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAClD,SAAS,EACT,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CACzC,CAAC;IACF,OAAO,SAAS,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC;AAC3C,CAAC;AAQD,6EAA6E;AAC7E,MAAM,OAAO,UAAU;IACZ,WAAW,CAAW;IACtB,UAAU,CAAgB;IAC1B,MAAM,CAAqB;IAEpC,YAAY,OAA0B;QACpC,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,IAAI,CACR,MAAyC,EACzC,QAAsC;QAEtC,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,OAAO,CAAC,MAAoB,CAAC;iBAClD,kBAAkB,CAAC;gBAClB,GAAG,EAAE,IAAI,CAAC,UAAU;gBACpB,GAAG,EAAE,KAAK;gBACV,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;aAC3D,CAAC;iBACD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC1B,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,UAAU,CAAC,gBAAgB,EAAE,8BAA8B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACpF,CAAC;IACH,CAAC;CACF;AAkBD,wEAAwE;AACxE,MAAM,OAAO,qBAAqB;IACvB,WAAW,CAAkB;IAC7B,IAAI,CAAa;IACjB,YAAY,CAAiC;IAEtD,YAAY,OAAqC;QAC/C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,IAAI,WAAW,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAyB;QACpC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,SAAS,IAAI,OAAO,CAAC,CAAC;QACrD,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,OAAO,CAAC,UAAU,GAAG,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,UAAU,CAAC,iBAAiB,EAAE,wCAAwC,CAAC,CAAC;QACpF,CAAC;QACD,MAAM,MAAM,GAAe;YACzB,GAAG,EAAE,SAAS,CAAC,OAAO,CAAC;YACvB,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE;YACjC,GAAG,EAAE,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC;YAC/B,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC;YAC7C,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;YAChE,GAAG,CAAC,OAAO,CAAC,WAAW,KAAK,SAAS;gBACnC,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;SACzD,CAAC;QACF,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;iBACpC,kBAAkB,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;iBACjD,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;YAC7B,OAAO,IAAI,WAAW,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,UAAU,CAAC,gBAAgB,EAAE,2BAA2B,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;CACF;AAuBD,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAA2B,EAC3B,OAA+B;IAE/B,MAAM,OAAO,GAAG,KAAK,YAAY,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACtE,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACtC,MAAM,aAAa,GAAG,OAAO,CAAC,uBAAuB,IAAI,EAAE,CAAC;IAC5D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,aAAa,IAAI,CAAC,EAAE,CAAC;QAC3D,MAAM,IAAI,UAAU,CAAC,oDAAoD,CAAC,CAAC;IAC7E,CAAC;IACD,IAAI,GAAQ,CAAC;IACb,IAAI,OAAmB,CAAC;IACxB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QACxC,IAAI,MAAM,CAAC,GAAG,KAAK,UAAU,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YAChE,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,kCAAkC,CAAC,CAAC;QACjF,CAAC;QACD,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACtC,CAAC,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE;YAC3C,UAAU,EAAE,CAAC,GAAG,CAAC;YACjB,GAAG,EAAE,UAAU;YACf,cAAc,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;SAC7C,CAAC,CAAC,CAAC;IACN,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,UAAU;YAAE,MAAM,KAAK,CAAC;QAC7C,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,sCAAsC,EAAE;YACjF,KAAK;SACN,CAAC,CAAC;IACL,CAAC;IACD,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;QACvF,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,gCAAgC,CAAC,CAAC;IAC/E,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;IAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IAChE,IAAI,UAAU,GAAG,aAAa,GAAG,IAAI,EAAE,CAAC;QACtC,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,6CAA6C,CAAC,CAAC;IAC5F,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,KAAK,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,OAAO,CAAC,GAAG,KAAK,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/F,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,uCAAuC,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK,EAAE,CAAC;QACnE,MAAM,IAAI,UAAU,CAAC,gBAAgB,EAAE,wCAAwC,CAAC,CAAC;IACnF,CAAC;IACD,IAAI,OAAO,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACtC,IAAI,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,eAAe,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,mCAAmC,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;SAAM,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,IAAI,UAAU,CAClB,oBAAoB,EACpB,gDAAgD,CACjD,CAAC;IACJ,CAAC;IACD,MAAM,aAAa,GAAG,MAAM,sBAAsB,CAAC,GAAG,CAAC,CAAC;IACxD,IACE,CAAC,CAAC,MAAM,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,aAAa,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE;QACtE,SAAS,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,aAAa,GAAG,IAAI,CAAC;KAC1D,CAAC,CAAC,EACH,CAAC;QACD,MAAM,IAAI,UAAU,CAAC,oBAAoB,EAAE,kCAAkC,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,CAAC;AACvE,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { type DiscoveredCompany } from "./models.js";
2
+ import type { ReactorPlatformView } from "@datalayer/reactor";
3
+ export interface DiscoveryOptions {
4
+ readonly reactor?: ReactorPlatformView;
5
+ readonly fetch?: typeof globalThis.fetch;
6
+ readonly assertSafeUrl?: (url: URL) => void | Promise<void>;
7
+ readonly maxRedirects?: number;
8
+ readonly maxResponseBytes?: number;
9
+ }
10
+ export declare function discoverCompany(domain: string, options?: DiscoveryOptions): Promise<DiscoveredCompany>;
11
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,aAAa,CAAC;AASrB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AA8ED,wBAAsB,eAAe,CACnC,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,iBAAiB,CAAC,CA0D5B"}
@@ -0,0 +1,100 @@
1
+ import { DiscoveryError, ProtocolValidationError } from "./errors.js";
2
+ import { parseJsonStrict } from "./json.js";
3
+ import { parseDiscoveryDocument, parseOAuthServerMetadata, } from "./models.js";
4
+ import { DiscoveryTransports, UrlSafetyPolicies, buildPapReactor, firstContribution, } from "./reactor.js";
5
+ function normalizeDomain(domain) {
6
+ const value = domain.replace(/\.$/, "").toLowerCase();
7
+ if (!value || value.includes("://") || value.includes("/")) {
8
+ throw new DiscoveryError("invalid_domain", "Discovery requires a DNS domain name");
9
+ }
10
+ return value;
11
+ }
12
+ function metadataUrl(issuer) {
13
+ const parsed = new URL(issuer);
14
+ const path = parsed.pathname.replace(/\/$/, "");
15
+ parsed.pathname = `/.well-known/oauth-authorization-server${path}`;
16
+ parsed.search = "";
17
+ parsed.hash = "";
18
+ return parsed;
19
+ }
20
+ async function readJson(initialUrl, transport, urlPolicy, maxRedirects, maxResponseBytes) {
21
+ let current = initialUrl;
22
+ for (let redirects = 0; redirects <= maxRedirects; redirects += 1) {
23
+ await urlPolicy.assertSafe(current);
24
+ let response;
25
+ try {
26
+ response = await transport.fetch(current, {
27
+ headers: { Accept: "application/json" },
28
+ redirect: "manual",
29
+ credentials: "omit",
30
+ });
31
+ }
32
+ catch (cause) {
33
+ throw new DiscoveryError("request_failed", "Discovery request failed", { cause });
34
+ }
35
+ if (response.status >= 300 && response.status < 400) {
36
+ if (redirects === maxRedirects) {
37
+ throw new DiscoveryError("too_many_redirects", "Discovery exceeded redirect limit");
38
+ }
39
+ const location = response.headers.get("location");
40
+ if (!location) {
41
+ throw new DiscoveryError("invalid_redirect", "Discovery redirect has no location");
42
+ }
43
+ current = new URL(location, current);
44
+ continue;
45
+ }
46
+ if (!response.ok) {
47
+ throw new DiscoveryError("http_error", "Discovery endpoint returned an unsuccessful status", { statusCode: response.status });
48
+ }
49
+ const contentType = response.headers.get("content-type")?.split(";", 1)[0]?.trim();
50
+ if (contentType !== "application/json" && contentType !== "application/poppy+json") {
51
+ throw new DiscoveryError("invalid_content_type", "Discovery response must be JSON");
52
+ }
53
+ const body = await response.text();
54
+ if (new TextEncoder().encode(body).byteLength > maxResponseBytes) {
55
+ throw new DiscoveryError("response_too_large", "Discovery response exceeds size limit");
56
+ }
57
+ try {
58
+ return { value: parseJsonStrict(body), finalUrl: current };
59
+ }
60
+ catch (cause) {
61
+ if (cause instanceof ProtocolValidationError)
62
+ throw cause;
63
+ throw new ProtocolValidationError("invalid_json", "Response is not valid JSON", {
64
+ cause,
65
+ });
66
+ }
67
+ }
68
+ throw new DiscoveryError("too_many_redirects", "Discovery exceeded redirect limit");
69
+ }
70
+ export async function discoverCompany(domain, options = {}) {
71
+ const requestedDomain = normalizeDomain(domain);
72
+ const reactor = options.reactor ?? buildPapReactor(options);
73
+ const transport = firstContribution(reactor, DiscoveryTransports, "discovery transport");
74
+ const urlPolicy = firstContribution(reactor, UrlSafetyPolicies, "URL safety policy");
75
+ const maxRedirects = options.maxRedirects ?? 3;
76
+ const maxBytes = options.maxResponseBytes ?? 100 * 1024;
77
+ const discovery = await readJson(new URL(`https://${requestedDomain}/.well-known/poppy.json`), transport, urlPolicy, maxRedirects, maxBytes);
78
+ const document = parseDiscoveryDocument(discovery.value);
79
+ if (document.organization.domain.replace(/^www\./, "") !==
80
+ requestedDomain.replace(/^www\./, "")) {
81
+ throw new DiscoveryError("organization_domain_mismatch", "Discovery organization domain does not match the requested domain");
82
+ }
83
+ if (!document.auth) {
84
+ return { discoveryUrl: discovery.finalUrl.toString(), document };
85
+ }
86
+ const metadataResponse = await readJson(metadataUrl(document.auth.issuer), transport, urlPolicy, maxRedirects, maxBytes);
87
+ const oauthMetadata = parseOAuthServerMetadata(metadataResponse.value);
88
+ if (oauthMetadata.issuer !== document.auth.issuer) {
89
+ throw new DiscoveryError("issuer_mismatch", "OAuth metadata issuer does not match auth.issuer");
90
+ }
91
+ if (!oauthMetadata.poppy_domains.includes(document.organization.domain)) {
92
+ throw new DiscoveryError("domain_not_authorized", "OAuth metadata does not authorize the discovered company domain");
93
+ }
94
+ return {
95
+ discoveryUrl: discovery.finalUrl.toString(),
96
+ document,
97
+ oauthMetadata,
98
+ };
99
+ }
100
+ //# sourceMappingURL=discovery.js.map