@parlor/auth 0.1.0 → 0.3.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/dist/account.d.ts +8 -1
- package/dist/account.d.ts.map +1 -1
- package/dist/account.js +13 -0
- package/dist/account.js.map +1 -1
- package/dist/audit.js.map +1 -1
- package/dist/better-auth.d.ts +5 -0
- package/dist/better-auth.d.ts.map +1 -1
- package/dist/better-auth.js +5 -3
- package/dist/better-auth.js.map +1 -1
- package/dist/client/index.d.ts +40 -4
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +105 -5
- package/dist/client/index.js.map +1 -1
- package/dist/database.js.map +1 -1
- package/dist/devices.d.ts.map +1 -1
- package/dist/devices.js +6 -1
- package/dist/devices.js.map +1 -1
- package/dist/es256.js.map +1 -1
- package/dist/grants.js.map +1 -1
- package/dist/hosts.d.ts +6 -1
- package/dist/hosts.d.ts.map +1 -1
- package/dist/hosts.js +53 -5
- package/dist/hosts.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/migrations.js.map +1 -1
- package/dist/native-sign-in.d.ts +45 -0
- package/dist/native-sign-in.d.ts.map +1 -0
- package/dist/native-sign-in.js +183 -0
- package/dist/native-sign-in.js.map +1 -0
- package/dist/pages.d.ts +1 -1
- package/dist/pages.d.ts.map +1 -1
- package/dist/pages.js +8 -4
- package/dist/pages.js.map +1 -1
- package/dist/provider.d.ts +11 -4
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +36 -2
- package/dist/provider.js.map +1 -1
- package/dist/revocation.js.map +1 -1
- package/dist/routes.js.map +1 -1
- package/dist/schema.js.map +1 -1
- package/dist/statements.d.ts +2 -0
- package/dist/statements.d.ts.map +1 -1
- package/dist/statements.js +2 -0
- package/dist/statements.js.map +1 -1
- package/dist/tokens.d.ts +27 -1
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +82 -3
- package/dist/tokens.js.map +1 -1
- package/dist/turn-keys.js.map +1 -1
- package/package.json +7 -7
package/dist/tokens.js
CHANGED
|
@@ -8,6 +8,8 @@ export const HOST_AUDIENCE = "parlor:host";
|
|
|
8
8
|
export const TURN_AUDIENCE = "parlor:mcp";
|
|
9
9
|
export const HOST_ASSERTION_TYP = "parlor-host+jwt";
|
|
10
10
|
export const TURN_TOKEN_TYP = "parlor-turn+jwt";
|
|
11
|
+
/** An agent on the host's computer outside any turn: Claude Code or Codex in a terminal. */
|
|
12
|
+
export const AGENT_TOKEN_TYP = "parlor-agent+jwt";
|
|
11
13
|
const CLOCK_SKEW_MS = 60_000;
|
|
12
14
|
/**
|
|
13
15
|
* A turn token never outlives the revocation horizon, or a revoked grant's token could
|
|
@@ -44,9 +46,14 @@ export function credentialOf(authorization) {
|
|
|
44
46
|
}
|
|
45
47
|
if (!JWS_SHAPE.test(value))
|
|
46
48
|
return { kind: "session", token: value };
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
switch (typOf(value)) {
|
|
50
|
+
case TURN_TOKEN_TYP:
|
|
51
|
+
return { kind: "turn", token: brand(value) };
|
|
52
|
+
case AGENT_TOKEN_TYP:
|
|
53
|
+
return { kind: "agent", token: brand(value) };
|
|
54
|
+
default:
|
|
55
|
+
return { kind: "access", token: value };
|
|
56
|
+
}
|
|
50
57
|
}
|
|
51
58
|
/** Mints a turn token for `host`'s grant; the provider's `delegate`. */
|
|
52
59
|
export async function delegate(keys, host, turn, now) {
|
|
@@ -131,4 +138,76 @@ export function agentPrincipalOf(claims) {
|
|
|
131
138
|
},
|
|
132
139
|
};
|
|
133
140
|
}
|
|
141
|
+
/** Mints a token for an agent on `host`'s computer outside any turn; the provider's `delegateAgent`. */
|
|
142
|
+
export async function delegateAgent(keys, host, agent, now) {
|
|
143
|
+
if (!(agent.ttlMs > 0))
|
|
144
|
+
throw new RangeError("An agent token needs a positive lifetime.");
|
|
145
|
+
const iat = Math.floor(now / 1000);
|
|
146
|
+
const exp = iat + Math.ceil(Math.min(agent.ttlMs, MAX_TURN_TOKEN_TTL_MS) / 1000);
|
|
147
|
+
const claims = {
|
|
148
|
+
aud: TURN_AUDIENCE,
|
|
149
|
+
iss: keys.issuer,
|
|
150
|
+
sub: host.userId,
|
|
151
|
+
gid: host.grantId,
|
|
152
|
+
hid: host.hostId,
|
|
153
|
+
agt: agent.agent,
|
|
154
|
+
iat,
|
|
155
|
+
exp,
|
|
156
|
+
};
|
|
157
|
+
const token = await new SignJWT({ ...claims })
|
|
158
|
+
.setProtectedHeader({ alg: "ES256", typ: AGENT_TOKEN_TYP, kid: keys.kid })
|
|
159
|
+
.sign(keys.privateKey);
|
|
160
|
+
return { token, expiresAt: exp * 1000 };
|
|
161
|
+
}
|
|
162
|
+
const agentClaimsSchema = z.object({
|
|
163
|
+
aud: z.literal(TURN_AUDIENCE),
|
|
164
|
+
iss: z.string().min(1),
|
|
165
|
+
sub: z.string().min(1),
|
|
166
|
+
gid: z.string().min(1),
|
|
167
|
+
hid: z.string().min(1),
|
|
168
|
+
agt: z.string().min(1),
|
|
169
|
+
iat: z.number().int(),
|
|
170
|
+
exp: z.number().int(),
|
|
171
|
+
});
|
|
172
|
+
/** Signature, `aud`, `iss` and `exp` only; the caller then asks `RevocationSet` about `gid`. */
|
|
173
|
+
export async function verifyAgentToken(keys, token, now) {
|
|
174
|
+
let payload;
|
|
175
|
+
try {
|
|
176
|
+
({ payload } = await jwtVerify(token, (header) => {
|
|
177
|
+
const key = header.kid === undefined ? undefined : keys.publicKeys.get(header.kid);
|
|
178
|
+
if (!key)
|
|
179
|
+
throw new errors.JWKSNoMatchingKey();
|
|
180
|
+
return key;
|
|
181
|
+
}, {
|
|
182
|
+
algorithms: ["ES256"],
|
|
183
|
+
typ: AGENT_TOKEN_TYP,
|
|
184
|
+
issuer: keys.issuer,
|
|
185
|
+
audience: TURN_AUDIENCE,
|
|
186
|
+
currentDate: new Date(now),
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
if (error instanceof errors.JWTExpired) {
|
|
191
|
+
throw new AuthFailure("expired", "The agent token expired.");
|
|
192
|
+
}
|
|
193
|
+
throw new AuthFailure("invalid", "The agent token is invalid.");
|
|
194
|
+
}
|
|
195
|
+
const claims = agentClaimsSchema.safeParse(payload);
|
|
196
|
+
if (!claims.success)
|
|
197
|
+
throw new AuthFailure("invalid", "The agent token is malformed.");
|
|
198
|
+
const { iat, exp } = claims.data;
|
|
199
|
+
if (exp - iat > MAX_TURN_TOKEN_TTL_MS / 1000 || iat * 1000 > now + CLOCK_SKEW_MS) {
|
|
200
|
+
throw new AuthFailure("invalid", "The agent token has an impossible lifetime.");
|
|
201
|
+
}
|
|
202
|
+
return claims.data;
|
|
203
|
+
}
|
|
204
|
+
/** An external agent of the user: no turn, so `ui_*` reaches no screen and confirms go to the app. */
|
|
205
|
+
export function outsideAgentPrincipalOf(claims) {
|
|
206
|
+
return {
|
|
207
|
+
kind: "agent",
|
|
208
|
+
userId: asId("user", claims.sub),
|
|
209
|
+
grantId: asId("grant", claims.gid),
|
|
210
|
+
agent: { name: claims.agt, verified: true },
|
|
211
|
+
};
|
|
212
|
+
}
|
|
134
213
|
//# sourceMappingURL=tokens.js.map
|
package/dist/tokens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AgentPrincipal,\n asId,\n type HostPrincipal,\n type TurnBinding,\n} from \"@parlor/core\";\nimport {\n type AgentDelegation,\n AuthFailure,\n type Delegation,\n REVOCATION_HORIZON_MS,\n type TurnDelegation,\n} from \"@parlor/server\";\nimport { decodeProtectedHeader, errors, jwtVerify, SignJWT } from \"jose\";\nimport { z } from \"zod\";\n\n/** A host assertion's audience: signed by the computer's own key, per request. */\nexport const HOST_AUDIENCE = \"parlor:host\";\n/** A turn token's audience: signed by the server, carried by the host's MCP proxy. */\nexport const TURN_AUDIENCE = \"parlor:mcp\";\n\nexport const HOST_ASSERTION_TYP = \"parlor-host+jwt\";\nexport const TURN_TOKEN_TYP = \"parlor-turn+jwt\";\n/** An agent on the host's computer outside any turn: Claude Code or Codex in a terminal. */\nexport const AGENT_TOKEN_TYP = \"parlor-agent+jwt\";\n\nconst CLOCK_SKEW_MS = 60_000;\n\n/**\n * A turn token never outlives the revocation horizon, or a revoked grant's token could\n * verify after `RevocationSet` forgot the revocation.\n */\nexport const MAX_TURN_TOKEN_TTL_MS = REVOCATION_HORIZON_MS - CLOCK_SKEW_MS;\n\nexport type TokenAudience = typeof HOST_AUDIENCE | typeof TURN_AUDIENCE;\n\ndeclare const audience: unique symbol;\n\n/** A compact JWS whose audience is known from the scheme it arrived under; never swapped. */\nexport type Jws<A extends TokenAudience> = string & { readonly [audience]: A };\nexport type HostAssertion = Jws<typeof HOST_AUDIENCE>;\nexport type TurnToken = Jws<typeof TURN_AUDIENCE>;\ndeclare const outsideTurns: unique symbol;\n/** Same audience as a turn token, never mistaken for one: no turn, so no screen to drive. */\nexport type AgentToken = Jws<typeof TURN_AUDIENCE> & { readonly [outsideTurns]: true };\n\n/** What an `authorization` header carries, sorted by scheme and shape before any verification. */\nexport type Credential =\n | { readonly kind: \"host\"; readonly assertion: HostAssertion }\n | { readonly kind: \"turn\"; readonly token: TurnToken }\n | { readonly kind: \"agent\"; readonly token: AgentToken }\n | { readonly kind: \"access\"; readonly token: string }\n | { readonly kind: \"session\"; readonly token: string };\n\nexport interface TurnTokenClaims {\n readonly aud: typeof TURN_AUDIENCE;\n readonly iss: string;\n /** user id */\n readonly sub: string;\n /** grant id: revoking the grant kills the token */\n readonly gid: string;\n readonly hid: string;\n readonly thr: string;\n readonly trn: string;\n /** the client the prompt came from; `ui_*` binds to it */\n readonly cid: string;\n readonly agt: string;\n readonly iat: number;\n /** as long as the turn's lease */\n readonly exp: number;\n}\n\nexport interface TurnTokenKeys {\n readonly issuer: string;\n readonly kid: string;\n readonly privateKey: CryptoKey;\n readonly publicKeys: ReadonlyMap<string, CryptoKey>;\n}\n\nconst JWS_SHAPE = /^[\\w-]+\\.[\\w-]+\\.[\\w-]+$/;\n\nfunction brand<A extends TokenAudience>(compact: string): Jws<A> {\n return compact as Jws<A>;\n}\n\nfunction typOf(jws: string): string | undefined {\n try {\n return decodeProtectedHeader(jws).typ;\n } catch {\n throw new AuthFailure(\"invalid\", \"The token is malformed.\");\n }\n}\n\n/** `ParlorHost <jws>` is a host; a `Bearer` JWS whose header says `typ: parlor-turn+jwt` is a turn. */\nexport function credentialOf(authorization: string | null): Credential | undefined {\n if (authorization === null) return undefined;\n const match = /^([A-Za-z]+)\\s+(\\S+)$/.exec(authorization);\n const scheme = match?.[1]?.toLowerCase();\n const value = match?.[2];\n if (value === undefined || (scheme !== \"bearer\" && scheme !== \"parlorhost\")) {\n throw new AuthFailure(\"invalid\", \"Use a Bearer token.\");\n }\n if (scheme === \"parlorhost\") {\n if (!JWS_SHAPE.test(value)) {\n throw new AuthFailure(\"invalid\", \"The host assertion is malformed.\");\n }\n return { kind: \"host\", assertion: brand<typeof HOST_AUDIENCE>(value) };\n }\n if (!JWS_SHAPE.test(value)) return { kind: \"session\", token: value };\n switch (typOf(value)) {\n case TURN_TOKEN_TYP:\n return { kind: \"turn\", token: brand<typeof TURN_AUDIENCE>(value) };\n case AGENT_TOKEN_TYP:\n return { kind: \"agent\", token: brand<typeof TURN_AUDIENCE>(value) as AgentToken };\n default:\n return { kind: \"access\", token: value };\n }\n}\n\n/** Mints a turn token for `host`'s grant; the provider's `delegate`. */\nexport async function delegate(\n keys: TurnTokenKeys,\n host: HostPrincipal,\n turn: TurnDelegation,\n now: number,\n): Promise<Delegation> {\n if (!(turn.ttlMs > 0)) throw new RangeError(\"A turn token needs a positive lifetime.\");\n const iat = Math.floor(now / 1000);\n const exp = iat + Math.ceil(Math.min(turn.ttlMs, MAX_TURN_TOKEN_TTL_MS) / 1000);\n const claims: TurnTokenClaims = {\n aud: TURN_AUDIENCE,\n iss: keys.issuer,\n sub: host.userId,\n gid: host.grantId,\n hid: host.hostId,\n thr: turn.threadId,\n trn: turn.turnId,\n cid: turn.clientId,\n agt: turn.agent,\n iat,\n exp,\n };\n const token = await new SignJWT({ ...claims })\n .setProtectedHeader({ alg: \"ES256\", typ: TURN_TOKEN_TYP, kid: keys.kid })\n .sign(keys.privateKey);\n return { token, expiresAt: exp * 1000 };\n}\n\nconst claimsSchema = z.object({\n aud: z.literal(TURN_AUDIENCE),\n iss: z.string().min(1),\n sub: z.string().min(1),\n gid: z.string().min(1),\n hid: z.string().min(1),\n thr: z.string().min(1),\n trn: z.string().min(1),\n cid: z.string(),\n agt: z.string().min(1),\n iat: z.number().int(),\n exp: z.number().int(),\n});\n\n/** Signature, `aud`, `iss` and `exp` only; the caller then asks `RevocationSet` about `gid`. */\nexport async function verifyTurnToken(\n keys: TurnTokenKeys,\n token: TurnToken,\n now: number,\n): Promise<TurnTokenClaims> {\n let payload: unknown;\n try {\n ({ payload } = await jwtVerify(\n token,\n (header) => {\n const key =\n header.kid === undefined ? undefined : keys.publicKeys.get(header.kid);\n if (!key) throw new errors.JWKSNoMatchingKey();\n return key;\n },\n {\n algorithms: [\"ES256\"],\n typ: TURN_TOKEN_TYP,\n issuer: keys.issuer,\n audience: TURN_AUDIENCE,\n currentDate: new Date(now),\n },\n ));\n } catch (error) {\n if (error instanceof errors.JWTExpired) {\n throw new AuthFailure(\"expired\", \"The turn token expired.\");\n }\n throw new AuthFailure(\"invalid\", \"The turn token is invalid.\");\n }\n const claims = claimsSchema.safeParse(payload);\n if (!claims.success) throw new AuthFailure(\"invalid\", \"The turn token is malformed.\");\n const { iat, exp } = claims.data;\n if (exp - iat > MAX_TURN_TOKEN_TTL_MS / 1000 || iat * 1000 > now + CLOCK_SKEW_MS) {\n throw new AuthFailure(\"invalid\", \"The turn token has an impossible lifetime.\");\n }\n return claims.data;\n}\n\nexport function agentPrincipalOf(\n claims: TurnTokenClaims,\n): AgentPrincipal & { readonly turn: TurnBinding } {\n return {\n kind: \"agent\",\n userId: asId(\"user\", claims.sub),\n grantId: asId(\"grant\", claims.gid),\n agent: { name: claims.agt, verified: true },\n turn: {\n threadId: asId(\"thread\", claims.thr),\n turnId: asId(\"turn\", claims.trn),\n hostId: asId(\"host\", claims.hid),\n clientId: claims.cid,\n },\n };\n}\n\nexport interface AgentTokenClaims {\n readonly aud: typeof TURN_AUDIENCE;\n readonly iss: string;\n readonly sub: string;\n readonly gid: string;\n readonly hid: string;\n readonly agt: string;\n readonly iat: number;\n readonly exp: number;\n}\n\n/** Mints a token for an agent on `host`'s computer outside any turn; the provider's `delegateAgent`. */\nexport async function delegateAgent(\n keys: TurnTokenKeys,\n host: HostPrincipal,\n agent: AgentDelegation,\n now: number,\n): Promise<Delegation> {\n if (!(agent.ttlMs > 0))\n throw new RangeError(\"An agent token needs a positive lifetime.\");\n const iat = Math.floor(now / 1000);\n const exp = iat + Math.ceil(Math.min(agent.ttlMs, MAX_TURN_TOKEN_TTL_MS) / 1000);\n const claims: AgentTokenClaims = {\n aud: TURN_AUDIENCE,\n iss: keys.issuer,\n sub: host.userId,\n gid: host.grantId,\n hid: host.hostId,\n agt: agent.agent,\n iat,\n exp,\n };\n const token = await new SignJWT({ ...claims })\n .setProtectedHeader({ alg: \"ES256\", typ: AGENT_TOKEN_TYP, kid: keys.kid })\n .sign(keys.privateKey);\n return { token, expiresAt: exp * 1000 };\n}\n\nconst agentClaimsSchema = z.object({\n aud: z.literal(TURN_AUDIENCE),\n iss: z.string().min(1),\n sub: z.string().min(1),\n gid: z.string().min(1),\n hid: z.string().min(1),\n agt: z.string().min(1),\n iat: z.number().int(),\n exp: z.number().int(),\n});\n\n/** Signature, `aud`, `iss` and `exp` only; the caller then asks `RevocationSet` about `gid`. */\nexport async function verifyAgentToken(\n keys: TurnTokenKeys,\n token: AgentToken,\n now: number,\n): Promise<AgentTokenClaims> {\n let payload: unknown;\n try {\n ({ payload } = await jwtVerify(\n token,\n (header) => {\n const key =\n header.kid === undefined ? undefined : keys.publicKeys.get(header.kid);\n if (!key) throw new errors.JWKSNoMatchingKey();\n return key;\n },\n {\n algorithms: [\"ES256\"],\n typ: AGENT_TOKEN_TYP,\n issuer: keys.issuer,\n audience: TURN_AUDIENCE,\n currentDate: new Date(now),\n },\n ));\n } catch (error) {\n if (error instanceof errors.JWTExpired) {\n throw new AuthFailure(\"expired\", \"The agent token expired.\");\n }\n throw new AuthFailure(\"invalid\", \"The agent token is invalid.\");\n }\n const claims = agentClaimsSchema.safeParse(payload);\n if (!claims.success) throw new AuthFailure(\"invalid\", \"The agent token is malformed.\");\n const { iat, exp } = claims.data;\n if (exp - iat > MAX_TURN_TOKEN_TTL_MS / 1000 || iat * 1000 > now + CLOCK_SKEW_MS) {\n throw new AuthFailure(\"invalid\", \"The agent token has an impossible lifetime.\");\n }\n return claims.data;\n}\n\n/** An external agent of the user: no turn, so `ui_*` reaches no screen and confirms go to the app. */\nexport function outsideAgentPrincipalOf(claims: AgentTokenClaims): AgentPrincipal {\n return {\n kind: \"agent\",\n userId: asId(\"user\", claims.sub),\n grantId: asId(\"grant\", claims.gid),\n agent: { name: claims.agt, verified: true },\n };\n}\n"]}
|
package/dist/turn-keys.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn-keys.js","sourceRoot":"","sources":["../src/turn-keys.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"turn-keys.js","sourceRoot":"","sources":["../src/turn-keys.ts"],"names":[],"mappings":"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","sourcesContent":["import { createCipheriv, createDecipheriv, hkdfSync, randomBytes } from \"node:crypto\";\n\nimport type { DataProvider } from \"@parlor/core\";\nimport type { Migration } from \"@parlor/server\";\nimport { sql } from \"drizzle-orm\";\nimport { exportJWK, generateKeyPair } from \"jose\";\n\nimport { type Database, jwkOf, rowsOf } from \"./database.js\";\nimport type { TurnTokenKeys } from \"./tokens.js\";\n\nexport const TURN_KEYS_MIGRATION: Migration = {\n id: \"auth/0005_turn_keys\",\n sql: `\n create table parlor_auth_turn_keys (\n kid text primary key,\n public_key jsonb not null,\n private_key text not null,\n active boolean not null default true,\n created_at timestamptz not null default now()\n );\n create unique index parlor_auth_turn_keys_active on parlor_auth_turn_keys (active) where active`,\n};\n\nconst KEY_ALGORITHM = { name: \"ECDSA\", namedCurve: \"P-256\" } as const;\nconst REFRESH_MIN_INTERVAL_MS = 1000;\n\ninterface KeyRow {\n readonly kid: string;\n readonly public_key: JsonWebKey | string;\n readonly private_key: string;\n readonly active: boolean;\n}\n\nfunction sealingKey(secret: string): Buffer {\n return Buffer.from(hkdfSync(\"sha256\", secret, \"\", \"parlor-auth/turn-keys\", 32));\n}\n\nfunction seal(secret: string, plaintext: string): string {\n const iv = randomBytes(12);\n const cipher = createCipheriv(\"aes-256-gcm\", sealingKey(secret), iv);\n const body = Buffer.concat([cipher.update(plaintext, \"utf8\"), cipher.final()]);\n return [iv, cipher.getAuthTag(), body]\n .map((part) => part.toString(\"base64url\"))\n .join(\".\");\n}\n\nfunction unseal(secret: string, sealed: string): string {\n const [iv, tag, body] = sealed.split(\".\").map((part) => Buffer.from(part, \"base64url\"));\n if (!iv || !tag || !body) throw new Error(\"The sealed turn key is malformed.\");\n const decipher = createDecipheriv(\"aes-256-gcm\", sealingKey(secret), iv);\n decipher.setAuthTag(tag);\n return Buffer.concat([decipher.update(body), decipher.final()]).toString(\"utf8\");\n}\n\nexport interface TurnKeyStore {\n keys(): Promise<TurnTokenKeys>;\n refresh(): Promise<TurnTokenKeys>;\n}\n\nexport interface TurnKeyStoreOptions {\n readonly database: DataProvider;\n readonly issuer: string;\n readonly secret: () => Promise<string>;\n readonly now?: (() => number) | undefined;\n}\n\nexport function createTurnKeyStore(options: TurnKeyStoreOptions): TurnKeyStore {\n const { database, issuer } = options;\n const now = options.now ?? Date.now;\n let loaded: Promise<TurnTokenKeys> | undefined;\n let refreshedAt = 0;\n\n const read = async (): Promise<KeyRow[]> =>\n rowsOf<KeyRow>(\n await (database.read() as Database).execute(\n sql`select kid, public_key, private_key, active from parlor_auth_turn_keys`,\n ),\n );\n\n const replace = async (secret: string, retiring: string | undefined): Promise<void> => {\n const pair = await generateKeyPair(\"ES256\", { extractable: true });\n const publicKey = await exportJWK(pair.publicKey);\n const privateKey = await exportJWK(pair.privateKey);\n const kid = crypto.randomUUID();\n await database.transaction(async (tx) => {\n const db = tx as Database;\n if (retiring !== undefined) {\n await db.execute(\n sql`update parlor_auth_turn_keys set active = false where kid = ${retiring} and active`,\n );\n }\n await db.execute(sql`\n insert into parlor_auth_turn_keys (kid, public_key, private_key)\n values (${kid}, ${JSON.stringify(publicKey)}::jsonb, ${seal(secret, JSON.stringify(privateKey))})\n on conflict do nothing`);\n });\n };\n\n const signingKeyOf = async (\n secret: string,\n row: KeyRow,\n ): Promise<CryptoKey | undefined> => {\n try {\n return await crypto.subtle.importKey(\n \"jwk\",\n JSON.parse(unseal(secret, row.private_key)) as JsonWebKey,\n KEY_ALGORITHM,\n false,\n [\"sign\"],\n );\n } catch {\n return undefined;\n }\n };\n\n const build = async (mayReplace: boolean): Promise<TurnTokenKeys> => {\n const secret = await options.secret();\n let rows = await read();\n let active = rows.find((row) => row.active);\n let privateKey = active && (await signingKeyOf(secret, active));\n if (!privateKey && !mayReplace)\n throw new Error(\"The turn signing key cannot be opened.\");\n if (!privateKey) {\n await replace(secret, active?.kid);\n rows = await read();\n active = rows.find((row) => row.active);\n privateKey = active && (await signingKeyOf(secret, active));\n }\n if (!active || !privateKey)\n throw new Error(\"The turn signing key could not be created.\");\n const verifyKeys = await Promise.all(\n rows.map(async (row) => {\n const key = await crypto.subtle.importKey(\n \"jwk\",\n jwkOf(row.public_key),\n KEY_ALGORITHM,\n false,\n [\"verify\"],\n );\n return [row.kid, key] as const;\n }),\n );\n return { issuer, kid: active.kid, privateKey, publicKeys: new Map(verifyKeys) };\n };\n\n const load = (): Promise<TurnTokenKeys> => {\n loaded ??= build(true).catch((error: unknown) => {\n loaded = undefined;\n throw error;\n });\n return loaded;\n };\n\n return {\n keys: load,\n async refresh() {\n const current = await load();\n if (now() - refreshedAt < REFRESH_MIN_INTERVAL_MS) return current;\n refreshedAt = now();\n loaded = build(false).catch(() => current);\n return loaded;\n },\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parlor/auth",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"homepage": "https://cychien.github.io/parlor",
|
|
5
5
|
"bugs": "https://github.com/cychien/parlor/issues",
|
|
6
6
|
"license": "MIT",
|
|
@@ -36,11 +36,11 @@
|
|
|
36
36
|
"drizzle-orm": "^0.45.4",
|
|
37
37
|
"jose": "^6.2.12",
|
|
38
38
|
"zod": "^4.6.5",
|
|
39
|
-
"@parlor/
|
|
40
|
-
"@parlor/chat": "0.
|
|
41
|
-
"@parlor/
|
|
42
|
-
"@parlor/
|
|
43
|
-
"@parlor/
|
|
39
|
+
"@parlor/core": "0.3.0",
|
|
40
|
+
"@parlor/chat": "0.3.0",
|
|
41
|
+
"@parlor/capabilities": "0.3.0",
|
|
42
|
+
"@parlor/server": "0.3.0",
|
|
43
|
+
"@parlor/client": "0.3.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@modelcontextprotocol/client": "^2.3.1",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"pg": "^8.23.1",
|
|
51
51
|
"typescript": "^7.0.2",
|
|
52
52
|
"vitest": "^5.0.3",
|
|
53
|
-
"@parlor/data": "0.
|
|
53
|
+
"@parlor/data": "0.3.0"
|
|
54
54
|
},
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "tsc -p tsconfig.json",
|