@vantageos/cloud-identity 0.7.0 → 0.9.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.
@@ -0,0 +1,262 @@
1
+ import { MIN_SECRET_LENGTH, PKCE_METHOD, isWellFormedChallenge, refusal, signBlob, signMac, utf8, toBase64Url, verifyBlob, } from "./authorize-shared.js";
2
+ import { sha256Hex, timingSafeEqual } from "./crypto.js";
3
+ import { verifyClerkSessionToken, } from "./clerk-session.js";
4
+ const STATE_PARAM = "authorize_state";
5
+ const refused = (reason) => ({
6
+ kind: "refused",
7
+ refusal: refusal(reason),
8
+ });
9
+ function nowOf(deps) {
10
+ return (deps.now ?? Date.now)();
11
+ }
12
+ function configOk(cfg) {
13
+ return (typeof cfg.stateSecret === "string" &&
14
+ cfg.stateSecret.length >= MIN_SECRET_LENGTH &&
15
+ cfg.allowedResources.length > 0);
16
+ }
17
+ function validateRequest(params, client, cfg) {
18
+ if (client.revoked === true)
19
+ return { ok: false, reason: "unknown-client" };
20
+ const redirectUri = params.redirect_uri;
21
+ if (!redirectUri || !client.redirectUris.includes(redirectUri)) {
22
+ return { ok: false, reason: "redirect-uri-mismatch" };
23
+ }
24
+ if (params.response_type !== undefined && params.response_type !== "code") {
25
+ return { ok: false, reason: "unsupported-response-type" };
26
+ }
27
+ const challenge = params.code_challenge;
28
+ const method = params.code_challenge_method ?? PKCE_METHOD;
29
+ if (!challenge || method !== PKCE_METHOD || !isWellFormedChallenge(challenge)) {
30
+ return { ok: false, reason: "pkce-required" };
31
+ }
32
+ const resource = params.resource;
33
+ if (!resource || !cfg.allowedResources.includes(resource)) {
34
+ return { ok: false, reason: "resource-not-allowed" };
35
+ }
36
+ const scope = (params.scope ?? "").trim() || (cfg.defaultScope ?? "openid");
37
+ if (cfg.supportedScopes) {
38
+ const supported = cfg.supportedScopes;
39
+ if (!scope.split(/\s+/).every((s) => supported.includes(s))) {
40
+ return { ok: false, reason: "scope-not-supported" };
41
+ }
42
+ }
43
+ return {
44
+ ok: true,
45
+ req: {
46
+ clientId: client.clientId,
47
+ redirectUri,
48
+ state: params.state ?? null,
49
+ codeChallenge: challenge,
50
+ resource,
51
+ scope,
52
+ },
53
+ };
54
+ }
55
+ async function signState(req, cfg, deps) {
56
+ const payload = {
57
+ v: 1,
58
+ cid: req.clientId,
59
+ ru: req.redirectUri,
60
+ st: req.state,
61
+ cc: req.codeChallenge,
62
+ rs: req.resource,
63
+ sc: req.scope,
64
+ exp: nowOf(deps) + (cfg.stateTtlSeconds ?? 600) * 1000,
65
+ };
66
+ return signBlob(payload, cfg.stateSecret);
67
+ }
68
+ function signInRedirect(cfg, stateBlob) {
69
+ const back = new URL(cfg.callbackUrl);
70
+ back.searchParams.set(STATE_PARAM, stateBlob);
71
+ const url = new URL(cfg.signInUrl);
72
+ url.searchParams.set("redirect_url", back.toString());
73
+ return { kind: "redirect-to-sign-in", url: url.toString() };
74
+ }
75
+ async function lookupClientSafe(deps, clientId) {
76
+ try {
77
+ return { ok: true, client: await deps.lookupClient(clientId) };
78
+ }
79
+ catch {
80
+ return { ok: false };
81
+ }
82
+ }
83
+ async function bindAndIssue(req, stateBlob, session, clientName, choice, cfg, deps) {
84
+ let memberships;
85
+ try {
86
+ memberships = await deps.listMemberships(session.userId);
87
+ }
88
+ catch {
89
+ return refused("membership-lookup-unavailable");
90
+ }
91
+ if (memberships.length === 0)
92
+ return refused("no-organization");
93
+ let picked;
94
+ if (choice.orgId !== undefined) {
95
+ // The chosen id is a CLAIM from the browser: it is honoured only if the
96
+ // verified user's own membership list contains it.
97
+ picked = memberships.find((m) => m.organization.id === choice.orgId);
98
+ if (!picked)
99
+ return refused("org-not-a-member");
100
+ }
101
+ else if (memberships.length === 1) {
102
+ picked = memberships[0];
103
+ }
104
+ const consentRequired = cfg.requireConsent !== false;
105
+ // The token binds the picker to the verified user, the signed state and the
106
+ // set of organisations that user belongs to (the set is what was shown).
107
+ const expectedToken = consentRequired
108
+ ? await consentTokenFor(cfg.stateSecret, stateBlob, session.userId, memberships.map((m) => m.organization.id))
109
+ : null;
110
+ if (consentRequired && picked && choice.approved === true) {
111
+ // `approved: true` is a CLAIM in a POST body. An attacker client can mint
112
+ // its own state and replay it with a victim's session; only a token the
113
+ // server issued to this user for this state proves the picker was shown.
114
+ const presented = choice.consentToken;
115
+ const ok = typeof presented === "string" &&
116
+ expectedToken !== null &&
117
+ (await timingSafeEqual(utf8(presented), utf8(expectedToken)));
118
+ if (!ok)
119
+ return refused("consent-required");
120
+ }
121
+ if (!picked || (consentRequired && choice.approved !== true)) {
122
+ return {
123
+ kind: "org-picker",
124
+ model: {
125
+ state: stateBlob,
126
+ client: { clientId: req.clientId, clientName },
127
+ resource: req.resource,
128
+ scope: req.scope,
129
+ organizations: memberships.map((m) => ({
130
+ id: m.organization.id,
131
+ slug: m.organization.slug,
132
+ name: m.organization.name,
133
+ role: m.role,
134
+ })),
135
+ consentRequired,
136
+ consentToken: expectedToken,
137
+ },
138
+ };
139
+ }
140
+ const code = (deps.generateCode ?? randomCode)();
141
+ const record = {
142
+ codeHash: await sha256Hex(code),
143
+ clerkUserId: session.userId,
144
+ orgId: picked.organization.id,
145
+ orgSlug: picked.organization.slug,
146
+ orgRole: picked.role,
147
+ clientId: req.clientId,
148
+ redirectUri: req.redirectUri,
149
+ codeChallenge: req.codeChallenge,
150
+ resource: req.resource,
151
+ scope: req.scope,
152
+ expiresAt: nowOf(deps) + (cfg.codeTtlSeconds ?? 60) * 1000,
153
+ };
154
+ try {
155
+ await deps.codeStore.put(record);
156
+ }
157
+ catch {
158
+ return refused("code-store-unavailable");
159
+ }
160
+ const back = new URL(req.redirectUri);
161
+ back.searchParams.set("code", code);
162
+ if (req.state !== null)
163
+ back.searchParams.set("state", req.state);
164
+ return { kind: "redirect-to-client", url: back.toString() };
165
+ }
166
+ /**
167
+ * `HMAC(stateSecret, "consent-v1\0" + state + "\0" + clerkUserId + "\0" +
168
+ * sorted organisation ids joined by ",")`. Bound to the exact state blob (so a
169
+ * token for one request is useless for another), to the verified user (so it
170
+ * cannot be replayed under another session) and to the organisation set shown
171
+ * (the chosen org is separately required to be in the live membership list).
172
+ */
173
+ async function consentTokenFor(secret, state, userId, orgIds) {
174
+ const set = [...orgIds].sort().join(",");
175
+ return signMac(`consent-v1\0${state}\0${userId}\0${set}`, secret);
176
+ }
177
+ function randomCode() {
178
+ return toBase64Url(crypto.getRandomValues(new Uint8Array(32)));
179
+ }
180
+ // ---------------------------------------------------------------------------
181
+ // Public functions
182
+ // ---------------------------------------------------------------------------
183
+ /**
184
+ * Handles `GET /authorize`. Validates the request against the registered
185
+ * client, then:
186
+ * - no Clerk session (absent, expired or forged) -> `redirect-to-sign-in`,
187
+ * carrying a signed, short-lived state blob and issuing NO code;
188
+ * - a verified session -> continues exactly as `resumeAuthorize` does.
189
+ * A Clerk key set that cannot be reached is a refusal (`jwks-unavailable`),
190
+ * never a redirect and never a grant.
191
+ */
192
+ export async function startAuthorize(params, sessionToken, cfg, deps) {
193
+ if (!configOk(cfg))
194
+ return refused("server-misconfigured");
195
+ const clientId = params.client_id;
196
+ if (!clientId)
197
+ return refused("invalid-request");
198
+ const found = await lookupClientSafe(deps, clientId);
199
+ if (!found.ok)
200
+ return refused("client-lookup-unavailable");
201
+ if (!found.client)
202
+ return refused("unknown-client");
203
+ const v = validateRequest(params, found.client, cfg);
204
+ if (!v.ok)
205
+ return refused(v.reason);
206
+ const stateBlob = await signState(v.req, cfg, deps);
207
+ if (!sessionToken)
208
+ return signInRedirect(cfg, stateBlob);
209
+ const verified = await verifyClerkSessionToken(sessionToken, cfg.session, nowOf(deps));
210
+ if (!verified.ok) {
211
+ return verified.refusal.reason === "jwks-unavailable"
212
+ ? { kind: "refused", refusal: verified.refusal }
213
+ : signInRedirect(cfg, stateBlob);
214
+ }
215
+ return bindAndIssue(v.req, stateBlob, verified.session, found.client.clientName ?? null, {}, cfg, deps);
216
+ }
217
+ /**
218
+ * Handles the return from Clerk (and the picker's form post). The request is
219
+ * rebuilt ONLY from the signed state: no query parameter other than the blob
220
+ * itself is read. A tampered or expired blob is refused; the client is looked
221
+ * up again so a client revoked mid-flow gets no code.
222
+ */
223
+ export async function resumeAuthorize(input, cfg, deps) {
224
+ if (!configOk(cfg))
225
+ return refused("server-misconfigured");
226
+ const raw = typeof input.state === "string" ? await verifyBlob(input.state, cfg.stateSecret) : null;
227
+ const p = raw;
228
+ if (!p ||
229
+ p.v !== 1 ||
230
+ typeof p.cid !== "string" ||
231
+ typeof p.ru !== "string" ||
232
+ typeof p.cc !== "string" ||
233
+ typeof p.rs !== "string" ||
234
+ typeof p.sc !== "string" ||
235
+ typeof p.exp !== "number" ||
236
+ (p.st !== null && typeof p.st !== "string")) {
237
+ return refused("state-invalid");
238
+ }
239
+ if (p.exp <= nowOf(deps))
240
+ return refused("state-expired");
241
+ const found = await lookupClientSafe(deps, p.cid);
242
+ if (!found.ok)
243
+ return refused("client-lookup-unavailable");
244
+ if (!found.client)
245
+ return refused("unknown-client");
246
+ const v = validateRequest({
247
+ redirect_uri: p.ru,
248
+ code_challenge: p.cc,
249
+ resource: p.rs,
250
+ scope: p.sc,
251
+ ...(p.st !== null && p.st !== undefined ? { state: p.st } : {}),
252
+ }, found.client, cfg);
253
+ if (!v.ok)
254
+ return refused(v.reason);
255
+ if (!input.sessionToken)
256
+ return refused("session-required");
257
+ const verified = await verifyClerkSessionToken(input.sessionToken, cfg.session, nowOf(deps));
258
+ if (!verified.ok)
259
+ return { kind: "refused", refusal: verified.refusal };
260
+ return bindAndIssue(v.req, input.state, verified.session, found.client.clientName ?? null, { orgId: input.orgId, approved: input.approved, consentToken: input.consentToken }, cfg, deps);
261
+ }
262
+ //# sourceMappingURL=authorize-flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize-flow.js","sourceRoot":"","sources":["../src/authorize-flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Shared vocabulary of the person-authorization flow: the typed refusal, the
3
+ * base64url and PKCE helpers, and the signed state blob. Internal to the
4
+ * package except for the names `index.ts` re-exports.
5
+ */
6
+ /**
7
+ * Why the flow refused. Every refusal of the authorize flow, the token
8
+ * exchange, the session verifier and the OIDC helpers carries one of these.
9
+ */
10
+ export type AuthorizeRefusalReason = "invalid-request" | "unknown-client" | "redirect-uri-mismatch" | "unsupported-response-type" | "pkce-required" | "resource-not-allowed" | "scope-not-supported" | "state-invalid" | "state-expired" | "session-required" | "session-invalid" | "jwks-unavailable" | "no-organization" | "org-not-a-member" | "consent-required" | "client-lookup-unavailable" | "membership-lookup-unavailable" | "code-store-unavailable" | "server-misconfigured" | "code-unknown" | "code-reused" | "code-expired" | "client-mismatch" | "redirect-uri-changed" | "resource-mismatch" | "verifier-malformed" | "pkce-mismatch" | "subject-mismatch" | "openid-scope-required" | "issuer-invalid";
11
+ /**
12
+ * The typed refusal: a non-empty object carrying its own code, in the same
13
+ * `{ code, reason }` shape as `RoleRefusal` and `TenantAbsence`.
14
+ */
15
+ export type AuthorizeRefusal = {
16
+ code: "AUTHORIZE_REFUSED";
17
+ reason: AuthorizeRefusalReason;
18
+ };
19
+ export declare function refusal(reason: AuthorizeRefusalReason): AuthorizeRefusal;
20
+ /**
21
+ * Maps a refusal to the OAuth error code and HTTP status a token or
22
+ * authorize endpoint answers with (RFC 6749 section 5.2, RFC 8707).
23
+ */
24
+ export declare function oauthErrorFor(r: AuthorizeRefusal): {
25
+ error: string;
26
+ status: number;
27
+ };
28
+ export declare function toBase64Url(bytes: Uint8Array): string;
29
+ export declare function fromBase64Url(input: string): Uint8Array | null;
30
+ export declare function utf8(input: string): Uint8Array;
31
+ /** The PKCE method name, assembled as one constant. */
32
+ export declare const PKCE_METHOD: string;
33
+ export declare function isWellFormedChallenge(challenge: string): boolean;
34
+ export declare function isWellFormedVerifier(verifier: string): boolean;
35
+ /** `base64url(SHA-256(verifier))` — the challenge a client derives from its verifier. */
36
+ export declare function pkceChallengeFromVerifier(verifier: string): Promise<string>;
37
+ export declare const MIN_SECRET_LENGTH = 32;
38
+ /** `base64url(json).base64url(hmac)`. */
39
+ export declare function signBlob(payload: unknown, secret: string): Promise<string>;
40
+ /** `base64url(HMAC-SHA-256(secret, message))`. */
41
+ export declare function signMac(message: string, secret: string): Promise<string>;
42
+ /** Returns the parsed payload when the MAC verifies (constant time), else `null`. */
43
+ export declare function verifyBlob(blob: string, secret: string): Promise<unknown | null>;
44
+ //# sourceMappingURL=authorize-shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize-shared.d.ts","sourceRoot":"","sources":["../src/authorize-shared.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAE9B,iBAAiB,GACjB,gBAAgB,GAChB,uBAAuB,GACvB,2BAA2B,GAC3B,eAAe,GACf,sBAAsB,GACtB,qBAAqB,GAErB,eAAe,GACf,eAAe,GAEf,kBAAkB,GAClB,iBAAiB,GACjB,kBAAkB,GAElB,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAElB,2BAA2B,GAC3B,+BAA+B,GAC/B,wBAAwB,GACxB,sBAAsB,GAEtB,cAAc,GACd,aAAa,GACb,cAAc,GACd,iBAAiB,GACjB,sBAAsB,GACtB,mBAAmB,GACnB,oBAAoB,GACpB,eAAe,GAEf,kBAAkB,GAClB,uBAAuB,GACvB,gBAAgB,CAAC;AAErB;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,mBAAmB,CAAC;IAC1B,MAAM,EAAE,sBAAsB,CAAC;CAChC,CAAC;AAEF,wBAAgB,OAAO,CAAC,MAAM,EAAE,sBAAsB,GAAG,gBAAgB,CAExE;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,gBAAgB,GAAG;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAsCA;AAMD,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAIrD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAS9D;AAED,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAE9C;AAMD,uDAAuD;AACvD,eAAO,MAAM,WAAW,EAAE,MAA8B,CAAC;AAKzD,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE9D;AAED,yFAAyF;AACzF,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAMjB;AAMD,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAYpC,yCAAyC;AACzC,wBAAsB,QAAQ,CAC5B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,kDAAkD;AAClD,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO9E;AAED,qFAAqF;AACrF,wBAAsB,UAAU,CAC9B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAoBzB"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Shared vocabulary of the person-authorization flow: the typed refusal, the
3
+ * base64url and PKCE helpers, and the signed state blob. Internal to the
4
+ * package except for the names `index.ts` re-exports.
5
+ */
6
+ export function refusal(reason) {
7
+ return { code: "AUTHORIZE_REFUSED", reason };
8
+ }
9
+ /**
10
+ * Maps a refusal to the OAuth error code and HTTP status a token or
11
+ * authorize endpoint answers with (RFC 6749 section 5.2, RFC 8707).
12
+ */
13
+ export function oauthErrorFor(r) {
14
+ switch (r.reason) {
15
+ case "unknown-client":
16
+ case "client-mismatch":
17
+ return { error: "invalid_client", status: 400 };
18
+ case "unsupported-response-type":
19
+ return { error: "unsupported_response_type", status: 400 };
20
+ case "scope-not-supported":
21
+ return { error: "invalid_scope", status: 400 };
22
+ case "resource-not-allowed":
23
+ case "resource-mismatch":
24
+ return { error: "invalid_target", status: 400 };
25
+ case "code-unknown":
26
+ case "code-reused":
27
+ case "code-expired":
28
+ case "redirect-uri-changed":
29
+ case "verifier-malformed":
30
+ case "pkce-mismatch":
31
+ return { error: "invalid_grant", status: 400 };
32
+ case "session-required":
33
+ case "session-invalid":
34
+ case "no-organization":
35
+ case "org-not-a-member":
36
+ case "consent-required":
37
+ case "subject-mismatch":
38
+ case "openid-scope-required":
39
+ return { error: "access_denied", status: 403 };
40
+ case "jwks-unavailable":
41
+ case "client-lookup-unavailable":
42
+ case "membership-lookup-unavailable":
43
+ case "code-store-unavailable":
44
+ return { error: "temporarily_unavailable", status: 503 };
45
+ case "server-misconfigured":
46
+ case "issuer-invalid":
47
+ return { error: "server_error", status: 500 };
48
+ default:
49
+ return { error: "invalid_request", status: 400 };
50
+ }
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // base64url
54
+ // ---------------------------------------------------------------------------
55
+ export function toBase64Url(bytes) {
56
+ let bin = "";
57
+ for (const b of bytes)
58
+ bin += String.fromCharCode(b);
59
+ return btoa(bin).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
60
+ }
61
+ export function fromBase64Url(input) {
62
+ if (!/^[A-Za-z0-9_-]*$/.test(input))
63
+ return null;
64
+ const padded = input.replace(/-/g, "+").replace(/_/g, "/");
65
+ try {
66
+ const bin = atob(padded + "=".repeat((4 - (padded.length % 4)) % 4));
67
+ return Uint8Array.from(bin, (c) => c.charCodeAt(0));
68
+ }
69
+ catch {
70
+ return null;
71
+ }
72
+ }
73
+ export function utf8(input) {
74
+ return new TextEncoder().encode(input);
75
+ }
76
+ // ---------------------------------------------------------------------------
77
+ // PKCE (RFC 7636)
78
+ // ---------------------------------------------------------------------------
79
+ /** The PKCE method name, assembled as one constant. */
80
+ export const PKCE_METHOD = ["S", "256"].join("");
81
+ const VERIFIER_RE = /^[A-Za-z0-9\-._~]{43,128}$/;
82
+ const CHALLENGE_RE = /^[A-Za-z0-9_-]{43}$/;
83
+ export function isWellFormedChallenge(challenge) {
84
+ return CHALLENGE_RE.test(challenge);
85
+ }
86
+ export function isWellFormedVerifier(verifier) {
87
+ return VERIFIER_RE.test(verifier);
88
+ }
89
+ /** `base64url(SHA-256(verifier))` — the challenge a client derives from its verifier. */
90
+ export async function pkceChallengeFromVerifier(verifier) {
91
+ const digest = await crypto.subtle.digest("SHA-256", utf8(verifier));
92
+ return toBase64Url(new Uint8Array(digest));
93
+ }
94
+ // ---------------------------------------------------------------------------
95
+ // Signed state blob
96
+ // ---------------------------------------------------------------------------
97
+ export const MIN_SECRET_LENGTH = 32;
98
+ async function hmacKey(secret, usage) {
99
+ return crypto.subtle.importKey("raw", utf8(secret), { name: "HMAC", hash: "SHA-256" }, false, [usage]);
100
+ }
101
+ /** `base64url(json).base64url(hmac)`. */
102
+ export async function signBlob(payload, secret) {
103
+ const body = toBase64Url(utf8(JSON.stringify(payload)));
104
+ const mac = await crypto.subtle.sign("HMAC", await hmacKey(secret, "sign"), utf8(body));
105
+ return `${body}.${toBase64Url(new Uint8Array(mac))}`;
106
+ }
107
+ /** `base64url(HMAC-SHA-256(secret, message))`. */
108
+ export async function signMac(message, secret) {
109
+ const mac = await crypto.subtle.sign("HMAC", await hmacKey(secret, "sign"), utf8(message));
110
+ return toBase64Url(new Uint8Array(mac));
111
+ }
112
+ /** Returns the parsed payload when the MAC verifies (constant time), else `null`. */
113
+ export async function verifyBlob(blob, secret) {
114
+ const parts = blob.split(".");
115
+ if (parts.length !== 2)
116
+ return null;
117
+ const [body, mac] = parts;
118
+ const macBytes = fromBase64Url(mac);
119
+ if (!macBytes)
120
+ return null;
121
+ const ok = await crypto.subtle.verify("HMAC", await hmacKey(secret, "verify"), macBytes, utf8(body));
122
+ if (!ok)
123
+ return null;
124
+ const bodyBytes = fromBase64Url(body);
125
+ if (!bodyBytes)
126
+ return null;
127
+ try {
128
+ return JSON.parse(new TextDecoder().decode(bodyBytes));
129
+ }
130
+ catch {
131
+ return null;
132
+ }
133
+ }
134
+ //# sourceMappingURL=authorize-shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize-shared.js","sourceRoot":"","sources":["../src/authorize-shared.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ import { type AuthorizeRefusal } from "./authorize-shared.js";
2
+ /**
3
+ * Verification of a Clerk session token (a signed RS256 JWT) against the
4
+ * instance's JWKS. The consumer supplies the issuer, the key set and, where it
5
+ * wants them, the audience and authorized parties; this module holds every
6
+ * decision and performs no network call of its own.
7
+ *
8
+ * @security Only RS256 is accepted. `alg: none`, HMAC algorithms and any key
9
+ * type other than RSA are refused before a signature is looked at.
10
+ */
11
+ export interface ClerkJwk {
12
+ kty: string;
13
+ kid?: string;
14
+ n?: string;
15
+ e?: string;
16
+ alg?: string;
17
+ use?: string;
18
+ }
19
+ export interface ClerkJwks {
20
+ keys: readonly ClerkJwk[];
21
+ }
22
+ export interface ClerkSessionVerifierConfig {
23
+ /** Exact `iss` the token must carry (the Clerk frontend API URL). */
24
+ issuer: string;
25
+ /** The key set, or a function returning it (the consumer owns fetching and caching). */
26
+ jwks: ClerkJwks | (() => Promise<ClerkJwks>);
27
+ /** When set, the token's `aud` must contain one of these. */
28
+ audience?: string | readonly string[];
29
+ /** When set, the token's `azp` must be present and listed. */
30
+ authorizedParties?: readonly string[];
31
+ /** Clock tolerance in seconds for `exp` / `nbf`. Default 5. */
32
+ clockToleranceSeconds?: number;
33
+ }
34
+ export interface VerifiedClerkSession {
35
+ userId: string;
36
+ sessionId: string | null;
37
+ claims: Readonly<Record<string, unknown>>;
38
+ }
39
+ export type VerifyClerkSessionResult = {
40
+ ok: true;
41
+ session: VerifiedClerkSession;
42
+ } | {
43
+ ok: false;
44
+ refusal: AuthorizeRefusal;
45
+ };
46
+ /**
47
+ * Verifies a Clerk session token. `nowMs` is injectable for tests.
48
+ * An unreachable key set is `jwks-unavailable` (retryable, 503), never a
49
+ * bad-credential answer; every other failure is `session-invalid`.
50
+ */
51
+ export declare function verifyClerkSessionToken(token: string, config: ClerkSessionVerifierConfig, nowMs?: number): Promise<VerifyClerkSessionResult>;
52
+ //# sourceMappingURL=clerk-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clerk-session.d.ts","sourceRoot":"","sources":["../src/clerk-session.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,gBAAgB,EAItB,MAAM,uBAAuB,CAAC;AAE/B;;;;;;;;GAQG;AAEH,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,0BAA0B;IACzC,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,wFAAwF;IACxF,IAAI,EAAE,SAAS,GAAG,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;IAC7C,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAC;IACtC,8DAA8D;IAC9D,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,+DAA+D;IAC/D,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC3C;AAED,MAAM,MAAM,wBAAwB,GAChC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAA;CAAE,GAC3C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAc7C;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,0BAA0B,EAClC,KAAK,GAAE,MAAmB,GACzB,OAAO,CAAC,wBAAwB,CAAC,CA+EnC"}
@@ -0,0 +1,93 @@
1
+ import { fromBase64Url, refusal, utf8, } from "./authorize-shared.js";
2
+ function parseJson(bytes) {
3
+ if (!bytes)
4
+ return null;
5
+ try {
6
+ const v = JSON.parse(new TextDecoder().decode(bytes));
7
+ return typeof v === "object" && v !== null && !Array.isArray(v)
8
+ ? v
9
+ : null;
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ /**
16
+ * Verifies a Clerk session token. `nowMs` is injectable for tests.
17
+ * An unreachable key set is `jwks-unavailable` (retryable, 503), never a
18
+ * bad-credential answer; every other failure is `session-invalid`.
19
+ */
20
+ export async function verifyClerkSessionToken(token, config, nowMs = Date.now()) {
21
+ const bad = () => ({
22
+ ok: false,
23
+ refusal: refusal("session-invalid"),
24
+ });
25
+ const parts = token.split(".");
26
+ if (parts.length !== 3)
27
+ return bad();
28
+ const [h, p, s] = parts;
29
+ const header = parseJson(fromBase64Url(h));
30
+ const claims = parseJson(fromBase64Url(p));
31
+ const sig = fromBase64Url(s);
32
+ if (!header || !claims || !sig || sig.length === 0)
33
+ return bad();
34
+ if (header.alg !== "RS256")
35
+ return bad();
36
+ if (typeof header.kid !== "string" || header.kid.length === 0)
37
+ return bad();
38
+ let jwks;
39
+ try {
40
+ jwks = typeof config.jwks === "function" ? await config.jwks() : config.jwks;
41
+ }
42
+ catch {
43
+ return { ok: false, refusal: refusal("jwks-unavailable") };
44
+ }
45
+ const jwk = jwks.keys.find((k) => k.kid === header.kid && k.kty === "RSA");
46
+ if (!jwk)
47
+ return bad();
48
+ let valid = false;
49
+ try {
50
+ const key = await crypto.subtle.importKey("jwk", { kty: "RSA", n: jwk.n, e: jwk.e, alg: "RS256", ext: true }, { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, false, ["verify"]);
51
+ valid = await crypto.subtle.verify("RSASSA-PKCS1-v1_5", key, sig, utf8(`${h}.${p}`));
52
+ }
53
+ catch {
54
+ return bad();
55
+ }
56
+ if (!valid)
57
+ return bad();
58
+ const tol = config.clockToleranceSeconds ?? 5;
59
+ const nowSec = Math.floor(nowMs / 1000);
60
+ if (claims.iss !== config.issuer)
61
+ return bad();
62
+ if (typeof claims.exp !== "number" || claims.exp + tol < nowSec)
63
+ return bad();
64
+ if (claims.nbf !== undefined) {
65
+ if (typeof claims.nbf !== "number" || claims.nbf - tol > nowSec)
66
+ return bad();
67
+ }
68
+ if (typeof claims.sub !== "string" || claims.sub.length === 0)
69
+ return bad();
70
+ if (config.audience !== undefined) {
71
+ const wanted = typeof config.audience === "string" ? [config.audience] : config.audience;
72
+ const got = Array.isArray(claims.aud)
73
+ ? claims.aud
74
+ : [claims.aud];
75
+ if (!got.some((a) => typeof a === "string" && wanted.includes(a)))
76
+ return bad();
77
+ }
78
+ if (config.authorizedParties !== undefined) {
79
+ if (typeof claims.azp !== "string" ||
80
+ !config.authorizedParties.includes(claims.azp)) {
81
+ return bad();
82
+ }
83
+ }
84
+ return {
85
+ ok: true,
86
+ session: {
87
+ userId: claims.sub,
88
+ sessionId: typeof claims.sid === "string" ? claims.sid : null,
89
+ claims,
90
+ },
91
+ };
92
+ }
93
+ //# sourceMappingURL=clerk-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clerk-session.js","sourceRoot":"","sources":["../src/clerk-session.ts"],"names":[],"mappings":"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"}
@@ -20,10 +20,10 @@
20
20
  */
21
21
  import { z } from "zod";
22
22
  export declare const humanAccountRoleSchema: z.ZodEnum<{
23
+ client: "client";
23
24
  owner: "owner";
24
25
  admin: "admin";
25
26
  member: "member";
26
- client: "client";
27
27
  }>;
28
28
  export type HumanAccountRole = z.infer<typeof humanAccountRoleSchema>;
29
29
  /**