kavachos 0.0.6 → 0.1.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,69 +1,202 @@
1
- # kavachos
1
+ <p align="center">
2
+ <img src="https://kavachos.com/logo.svg" height="64" alt="KavachOS" />
3
+ </p>
2
4
 
3
- Auth OS for AI agents. Identity, permissions, delegation, and audit.
5
+ <h1 align="center">kavachos</h1>
4
6
 
5
- [![npm](https://img.shields.io/npm/v/kavachos)](https://www.npmjs.com/package/kavachos)
6
- [![license](https://img.shields.io/badge/license-MIT-blue)](https://github.com/kavachos/kavachos/blob/main/LICENSE)
7
+ <p align="center">
8
+ <strong>The auth OS for AI agents and humans</strong><br />
9
+ Identity, permissions, delegation, and audit for the agentic era.
10
+ </p>
7
11
 
8
- ## Install
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/kavachos"><img src="https://img.shields.io/npm/v/kavachos?style=flat-square&color=c9a84c" alt="npm" /></a>
14
+ <a href="https://www.npmjs.com/package/kavachos"><img src="https://img.shields.io/npm/dm/kavachos?style=flat-square&color=c9a84c" alt="downloads" /></a>
15
+ <a href="https://github.com/kavachos/kavachos/actions"><img src="https://img.shields.io/github/actions/workflow/status/kavachos/kavachos/ci.yml?style=flat-square&label=tests" alt="tests" /></a>
16
+ <a href="https://github.com/kavachos/kavachos/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue?style=flat-square" alt="MIT" /></a>
17
+ <a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-strict-blue?style=flat-square" alt="TypeScript" /></a>
18
+ <a href="https://docs.kavachos.com"><img src="https://img.shields.io/badge/docs-kavachos.com-c9a84c?style=flat-square" alt="docs" /></a>
19
+ </p>
9
20
 
10
- ```bash
21
+ <p align="center">
22
+ <a href="https://docs.kavachos.com/docs/quickstart">Quickstart</a> &middot;
23
+ <a href="https://docs.kavachos.com/docs">Documentation</a> &middot;
24
+ <a href="https://github.com/kavachos/kavachos/tree/main/examples">Examples</a> &middot;
25
+ <a href="https://app.kavachos.com">KavachOS Cloud</a>
26
+ </p>
27
+
28
+ ---
29
+
30
+ ## Why kavachos?
31
+
32
+ Every auth library handles human login. None of them handle **AI agent identity**. KavachOS gives every agent its own bearer token, scoped permissions, delegation chains, and an immutable audit trail. Plus full human auth (14 methods, 27+ OAuth providers, passkeys, SSO) so you don't need two auth systems.
33
+
34
+ ```
11
35
  npm install kavachos
12
- # or
13
- pnpm add kavachos
14
36
  ```
15
37
 
16
38
  ## Quick start
17
39
 
18
40
  ```typescript
19
- import { createKavach } from 'kavachos';
41
+ import { createKavach } from "kavachos";
42
+ import { emailPassword } from "kavachos/auth";
20
43
 
21
44
  const kavach = createKavach({
22
- database: { provider: 'sqlite', url: 'kavach.db' },
45
+ database: { provider: "sqlite", url: "kavach.db" },
46
+ plugins: [emailPassword()],
23
47
  });
24
48
 
25
- // Create an agent with scoped permissions
49
+ // Create an AI agent with scoped permissions
26
50
  const agent = await kavach.agent.create({
27
- ownerId: 'user-123',
28
- name: 'github-reader',
29
- type: 'autonomous',
51
+ ownerId: "user-123",
52
+ name: "github-reader",
53
+ type: "autonomous",
30
54
  permissions: [
31
- { resource: 'mcp:github:*', actions: ['read'] },
32
- {
33
- resource: 'mcp:deploy:production',
34
- actions: ['execute'],
35
- constraints: { requireApproval: true },
36
- },
55
+ { resource: "mcp:github:*", actions: ["read"] },
56
+ { resource: "mcp:deploy:production", actions: ["execute"],
57
+ constraints: { requireApproval: true } },
37
58
  ],
38
59
  });
39
60
 
40
- // Authorize an action
61
+ // Authorize and audit (< 1ms)
41
62
  const result = await kavach.authorize(agent.id, {
42
- action: 'read',
43
- resource: 'mcp:github:repos',
63
+ action: "read",
64
+ resource: "mcp:github:repos",
44
65
  });
45
- // { allowed: true, auditId: 'aud_...' }
66
+ // { allowed: true, auditId: "aud_..." }
67
+ ```
68
+
69
+ ## Features
70
+
71
+ <table>
72
+ <tr>
73
+ <td width="50%">
74
+
75
+ ### Agent identity
76
+ - Cryptographic bearer tokens (`kv_...`)
77
+ - Wildcard permission matching (`mcp:github:*`)
78
+ - Delegation chains with depth limits
79
+ - Immutable audit trail
80
+ - Trust scoring and anomaly detection
81
+ - Budget policies and cost attribution
82
+ - CIBA-style human approval flows
83
+
84
+ </td>
85
+ <td width="50%">
86
+
87
+ ### Human auth (14 methods)
88
+ - Email + password
89
+ - Magic link, email OTP
90
+ - Passkey / WebAuthn
91
+ - TOTP 2FA
92
+ - Phone SMS
93
+ - Google One-tap
94
+ - Sign In With Ethereum
95
+ - Anonymous auth
96
+ - Session freshness enforcement
97
+
98
+ </td>
99
+ </tr>
100
+ <tr>
101
+ <td>
102
+
103
+ ### OAuth (27+ providers)
104
+ Google, GitHub, Apple, Microsoft, Discord, Slack, GitLab, LinkedIn, Twitter/X, Facebook, Spotify, Twitch, Reddit, Notion, plus a generic OIDC factory for any provider.
105
+
106
+ </td>
107
+ <td>
108
+
109
+ ### MCP OAuth 2.1
110
+ Spec-compliant authorization server for Model Context Protocol. PKCE S256, RFC 9728 / 8707 / 8414 / 7591.
111
+
112
+ </td>
113
+ </tr>
114
+ <tr>
115
+ <td>
116
+
117
+ ### Enterprise
118
+ Organizations + RBAC, SAML SSO, SCIM directory sync, admin controls, API key management, multi-tenant isolation, GDPR compliance.
119
+
120
+ </td>
121
+ <td>
122
+
123
+ ### Edge compatible
124
+ Runs on Cloudflare Workers (D1), Deno, Bun, and Node.js. Only 3 runtime deps: `drizzle-orm`, `jose`, `zod`.
46
125
 
47
- // Query the audit trail
48
- const logs = await kavach.audit.query({ agentId: agent.id });
126
+ </td>
127
+ </tr>
128
+ </table>
129
+
130
+ ### Security
131
+
132
+ Rate limiting (per-agent and per-IP) &middot; HIBP breach checking &middot; CSRF protection &middot; httpOnly secure cookies &middot; Email enumeration prevention &middot; Trusted device windows &middot; Password reset with signed tokens
133
+
134
+ ## Framework adapters
135
+
136
+ Works with every major framework:
137
+
138
+ | Framework | Package | Framework | Package |
139
+ |-----------|---------|-----------|---------|
140
+ | **Hono** | `@kavachos/hono` | **Nuxt** | `@kavachos/nuxt` |
141
+ | **Express** | `@kavachos/express` | **SvelteKit** | `@kavachos/sveltekit` |
142
+ | **Next.js** | `@kavachos/nextjs` | **Astro** | `@kavachos/astro` |
143
+ | **Fastify** | `@kavachos/fastify` | **NestJS** | `@kavachos/nestjs` |
144
+
145
+ ## Client libraries
146
+
147
+ | Package | What |
148
+ |---------|------|
149
+ | `@kavachos/react` | KavachProvider + hooks |
150
+ | `@kavachos/vue` | Vue 3 plugin + composables |
151
+ | `@kavachos/svelte` | Svelte stores |
152
+ | `@kavachos/ui` | 7 pre-built auth components (SignIn, SignUp, UserButton...) |
153
+ | `@kavachos/expo` | React Native / Expo |
154
+ | `@kavachos/electron` | Electron desktop |
155
+ | `@kavachos/client` | Zero-dep TypeScript REST client |
156
+
157
+ ## Databases
158
+
159
+ SQLite, PostgreSQL, MySQL, Cloudflare D1, libSQL (Turso). Tables are auto-created on first run.
160
+
161
+ ```typescript
162
+ // Cloudflare Workers + D1
163
+ createKavach({ database: { provider: "d1", binding: env.KAVACH_DB } });
164
+
165
+ // PostgreSQL
166
+ createKavach({ database: { provider: "postgres", url: process.env.DATABASE_URL } });
167
+ ```
168
+
169
+ ## Plugins
170
+
171
+ Auth methods are plugins. Enable what you need:
172
+
173
+ ```typescript
174
+ import {
175
+ emailPassword, magicLink, passkey, totp,
176
+ organizations, sso, admin, apiKeys, webhooks,
177
+ } from "kavachos/auth";
178
+
179
+ createKavach({
180
+ database: { provider: "sqlite", url: "kavach.db" },
181
+ plugins: [emailPassword(), magicLink({ sendMagicLink }), passkey(), totp()],
182
+ });
49
183
  ```
50
184
 
51
- ## What's included
185
+ ## KavachOS Cloud
52
186
 
53
- - **Agent identity** - create, scope, revoke, and rotate agent credentials. Each agent gets an opaque bearer token (`kv_...`) and a permanent audit identity.
54
- - **Permission engine** - resource-based access control with colon-separated hierarchies (`mcp:github:*`) and wildcard matching. Constraints support rate limits, time windows, and human-in-the-loop approval gates.
55
- - **Delegation chains** - an orchestrator can delegate a subset of its permissions to a sub-agent, with depth limits and expiry. Chains are auditable and revocable at any point.
56
- - **Audit trail** - every authorization decision is written to an immutable log. Export as JSON or CSV for EU AI Act Article 12, SOC 2 CC6.1-CC7.2, and ISO 42001 compliance.
57
- - **MCP OAuth 2.1** - spec-compliant authorization server for the Model Context Protocol, with PKCE (S256), Protected Resource Metadata (RFC 9728), and Resource Indicators (RFC 8707).
187
+ Don't want to self-host? [KavachOS Cloud](https://app.kavachos.com) is the managed version with dashboard, billing, and zero infrastructure.
58
188
 
59
- ## Full docs
189
+ | | Free | Starter | Growth | Scale |
190
+ |---|---|---|---|---|
191
+ | MAU | 1,000 | 10,000 | 50,000 | 200,000 |
192
+ | Price | $0 | $29/mo | $79/mo | $199/mo |
60
193
 
61
- [kavachos.com/docs](https://kavachos.com/docs)
194
+ [Start free](https://app.kavachos.com/sign-up) &middot; [Compare plans](https://kavachos.com/pricing) &middot; [Self-host instead](https://docs.kavachos.com/docs/quickstart)
62
195
 
63
- ## Source
196
+ ## Documentation
64
197
 
65
- [github.com/kavachos/kavachos](https://github.com/kavachos/kavachos)
198
+ Full docs at **[docs.kavachos.com](https://docs.kavachos.com/docs)**
66
199
 
67
200
  ## License
68
201
 
69
- MIT
202
+ [MIT](https://github.com/kavachos/kavachos/blob/main/LICENSE)
@@ -1,8 +1,9 @@
1
1
  import * as jose from 'jose';
2
- import { A as AgentIdentity } from '../types-W8X0PXE7.js';
2
+ import { A as AgentIdentity } from '../types-6D7iJvGD.js';
3
3
  import { z } from 'zod';
4
4
  import { R as Result } from '../types-BuHrZcjE.js';
5
5
  import 'drizzle-orm/sqlite-core';
6
+ import '../redirect/index.js';
6
7
 
7
8
  /**
8
9
  * A2A (Agent-to-Agent) protocol types for KavachOS.
@@ -1,8 +1,9 @@
1
- import { D as Database, C as CreateAgentInput, A as AgentIdentity, h as AgentFilter, U as UpdateAgentInput } from '../types-W8X0PXE7.js';
2
- export { Z as AgentConfig } from '../types-W8X0PXE7.js';
1
+ import { D as Database, C as CreateAgentInput, A as AgentIdentity, h as AgentFilter, U as UpdateAgentInput } from '../types-6D7iJvGD.js';
2
+ export { Y as AgentConfig } from '../types-6D7iJvGD.js';
3
3
  import 'drizzle-orm/sqlite-core';
4
4
  import '../types-BuHrZcjE.js';
5
5
  import 'zod';
6
+ import '../redirect/index.js';
6
7
 
7
8
  interface AgentModuleConfig {
8
9
  db: Database;
@@ -1,7 +1,8 @@
1
- import { D as Database, k as AuditFilter, l as AuditEntry, m as AuditExportOptions } from '../types-W8X0PXE7.js';
1
+ import { D as Database, k as AuditFilter, l as AuditEntry, m as AuditExportOptions } from '../types-6D7iJvGD.js';
2
2
  import 'drizzle-orm/sqlite-core';
3
3
  import '../types-BuHrZcjE.js';
4
4
  import 'zod';
5
+ import '../redirect/index.js';
5
6
 
6
7
  interface AuditModuleConfig {
7
8
  db: Database;
@@ -1,9 +1,10 @@
1
1
  import { z } from 'zod';
2
- import { a2 as AuthAdapter, o as ResolvedUser, L as KavachPlugin, D as Database, X as AdminConfig, p as SessionManager, $ as ApiKeyManagerConfig, a7 as EmailOtpConfig, P as Permission, ab as MagicLinkConfig, ag as OrgConfig, al as PasskeyConfig, I as PluginEndpoint, aF as TotpConfig } from '../types-W8X0PXE7.js';
3
- export { u as AdminModule, Y as AdminUser, _ as ApiKey, v as ApiKeyManagerModule, a3 as CaptchaConfig, G as CaptchaModule, a4 as CaptchaVerifyResult, a5 as CreateTokenInput, E as EmailOtpModule, a8 as EmailVerificationConfig, y as EmailVerificationModule, r as MagicLinkModule, ad as OidcProvider, ae as OneTimeTokenConfig, z as OneTimeTokenModule, af as OneTimeTokenPurpose, ah as OrgInvitation, ai as OrgMember, O as OrgModule, aj as OrgRole, ak as Organization, am as PasskeyCredential, s as PasskeyModule, an as PasswordResetConfig, x as PasswordResetModule, ap as PhoneAuthConfig, F as PhoneAuthModule, av as RevokeTokensResult, aw as SSO_ERROR, ax as SamlProvider, aA as SsoAuditEvent, aB as SsoConfig, aC as SsoConnection, aD as SsoError, t as SsoModule, T as TotpModule, aG as TotpSetup, aH as UsernameAuthConfig, w as UsernameAuthModule, aI as ValidateTokenResult, bv as WebhookConfig, bw as WebhookEvent, W as WebhookModule, aS as createAdminModule, aT as createApiKeyManagerModule, aV as createCaptchaModule, aY as createEmailOtpModule, aZ as createEmailVerificationModule, a_ as createMagicLinkModule, a$ as createOneTimeTokenModule, b0 as createOrgModule, b1 as createPasskeyModule, b2 as createPasswordResetModule, b3 as createPhoneAuthModule, b7 as createSsoModule, b8 as createTotpModule, b9 as createUsernameAuthModule, bx as createWebhookModule } from '../types-W8X0PXE7.js';
2
+ import { a1 as AuthAdapter, o as ResolvedUser, J as KavachPlugin, D as Database, Q as AdminConfig, p as SessionManager, _ as ApiKeyManagerConfig, a6 as EmailOtpConfig, P as Permission, aa as MagicLinkConfig, af as OrgConfig, ak as PasskeyConfig, H as PluginEndpoint, aB as TotpConfig } from '../types-6D7iJvGD.js';
3
+ export { u as AdminModule, X as AdminUser, Z as ApiKey, v as ApiKeyManagerModule, a2 as CaptchaConfig, G as CaptchaModule, a3 as CaptchaVerifyResult, a4 as CreateTokenInput, E as EmailOtpModule, a7 as EmailVerificationConfig, y as EmailVerificationModule, r as MagicLinkModule, ac as OidcProvider, ad as OneTimeTokenConfig, z as OneTimeTokenModule, ae as OneTimeTokenPurpose, ag as OrgInvitation, ah as OrgMember, O as OrgModule, ai as OrgRole, aj as Organization, al as PasskeyCredential, s as PasskeyModule, am as PasswordResetConfig, x as PasswordResetModule, ao as PhoneAuthConfig, F as PhoneAuthModule, ar as RevokeTokensResult, as as SSO_ERROR, at as SamlProvider, aw as SsoAuditEvent, ax as SsoConfig, ay as SsoConnection, az as SsoError, t as SsoModule, T as TotpModule, aC as TotpSetup, aD as UsernameAuthConfig, w as UsernameAuthModule, aE as ValidateTokenResult, bq as WebhookConfig, br as WebhookEvent, W as WebhookModule, aO as createAdminModule, aP as createApiKeyManagerModule, aR as createCaptchaModule, aU as createEmailOtpModule, aV as createEmailVerificationModule, aW as createMagicLinkModule, aX as createOneTimeTokenModule, aY as createOrgModule, aZ as createPasskeyModule, a_ as createPasswordResetModule, a$ as createPhoneAuthModule, b2 as createSsoModule, b3 as createTotpModule, b4 as createUsernameAuthModule, bs as createWebhookModule } from '../types-6D7iJvGD.js';
4
4
  import { R as Result } from '../types-BuHrZcjE.js';
5
5
  import * as jose from 'jose';
6
6
  import 'drizzle-orm/sqlite-core';
7
+ import '../redirect/index.js';
7
8
 
8
9
  /**
9
10
  * JWT bearer-token auth adapter.
@@ -1,4 +1,4 @@
1
- export { EVENT_TYPES, HibpApiError, HibpBreachedError, OAuthProxyError, OneTapVerifyError, SSO_ERROR, SsoError, additionalFields, admin, anonymousAuth, apiKeys, bearerAuth, createAdditionalFieldsModule, createAdminModule, createAnonymousAuthModule, createApiKeyManagerModule, createCaptchaModule, createCostAttributionModule, createCustomSessionModule, createDeviceAuthModule, createEmailOtpModule, createEmailVerificationModule, createEphemeralSessionModule, createEventStreamModule, createFederationModule, createGdprModule, createHibpModule, createJwtSessionModule, createLastLoginModule, createMagicLinkModule, createOAuthProxyModule, createOidcProviderModule, createOneTapModule, createOneTimeTokenModule, createOpenApiModule, createOrgModule, createPasskeyModule, createPasswordResetModule, createPhoneAuthModule, createPolarModule, createRateLimiter, createReBACModule, createScimModule, createSiweModule, createSsoModule, createStripeModule, createTotpModule, createTrustedDeviceModule, createUsernameAuthModule, createWebhookModule, customAuth, customSession, deviceAuth, deviceLabelFromRequest, emailOtp, gdpr, headerAuth, magicLink, oauthProxy, oneTap, organization, passkey, polar, scim, siwe, stripe, twoFactor, withRateLimit } from '../chunk-FKVAXCNJ.js';
1
+ export { EVENT_TYPES, HibpApiError, HibpBreachedError, OAuthProxyError, OneTapVerifyError, SSO_ERROR, SsoError, additionalFields, admin, anonymousAuth, apiKeys, bearerAuth, createAdditionalFieldsModule, createAdminModule, createAnonymousAuthModule, createApiKeyManagerModule, createCaptchaModule, createCostAttributionModule, createCustomSessionModule, createDeviceAuthModule, createEmailOtpModule, createEmailVerificationModule, createEphemeralSessionModule, createEventStreamModule, createFederationModule, createGdprModule, createHibpModule, createJwtSessionModule, createLastLoginModule, createMagicLinkModule, createOAuthProxyModule, createOidcProviderModule, createOneTapModule, createOneTimeTokenModule, createOpenApiModule, createOrgModule, createPasskeyModule, createPasswordResetModule, createPhoneAuthModule, createPolarModule, createRateLimiter, createReBACModule, createScimModule, createSiweModule, createSsoModule, createStripeModule, createTotpModule, createTrustedDeviceModule, createUsernameAuthModule, createWebhookModule, customAuth, customSession, deviceAuth, deviceLabelFromRequest, emailOtp, gdpr, headerAuth, magicLink, oauthProxy, oneTap, organization, passkey, polar, scim, siwe, stripe, twoFactor, withRateLimit } from '../chunk-IEOOSOJ4.js';
2
2
  import '../chunk-KDL6A76K.js';
3
3
  import '../chunk-QCRHJMDX.js';
4
4
  import '../chunk-NSBPE2FW.js';
@@ -4,8 +4,6 @@ import * as jose2 from 'jose';
4
4
  import { jwtVerify, SignJWT, createRemoteJWKSet, importJWK } from 'jose';
5
5
  import { z } from 'zod';
6
6
  import { eq, like, sql, lt, and, gte, lte, asc, desc, gt, inArray, or, notInArray } from 'drizzle-orm';
7
- import { randomUUID, createHash, randomBytes as randomBytes$1, createVerify } from 'crypto';
8
- import { TextEncoder as TextEncoder$1 } from 'util';
9
7
  import { deflateRaw } from 'zlib';
10
8
 
11
9
  var BearerAuthOptionsSchema = z.object({
@@ -10548,7 +10546,7 @@ function getSamlAttributeValue(assertion, attributeName) {
10548
10546
  return null;
10549
10547
  }
10550
10548
  function deflateRawAsync(input) {
10551
- const encoder = new TextEncoder$1();
10549
+ const encoder = new TextEncoder();
10552
10550
  return new Promise((resolve, reject) => {
10553
10551
  deflateRaw(encoder.encode(input), (err2, result) => {
10554
10552
  if (err2) reject(err2);
@@ -10564,14 +10562,33 @@ function uint8ArrayToBase64(bytes) {
10564
10562
  return btoa(binary);
10565
10563
  }
10566
10564
  async function buildSamlAuthnRequest(provider) {
10567
- const requestId = `_${randomBytes$1(16).toString("hex")}`;
10565
+ const requestId = `_${randomBytesHex(16)}`;
10568
10566
  const now = (/* @__PURE__ */ new Date()).toISOString();
10569
10567
  const xml = `<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="${requestId}" Version="2.0" IssueInstant="${now}" Destination="${provider.entryPoint}" AssertionConsumerServiceURL="${provider.callbackUrl}"><saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">${provider.entityId ?? provider.issuer}</saml:Issuer></samlp:AuthnRequest>`;
10570
10568
  const deflated = await deflateRawAsync(xml);
10571
10569
  const b64 = uint8ArrayToBase64(deflated);
10572
10570
  return { requestId, encoded: encodeURIComponent(b64) };
10573
10571
  }
10574
- function verifySamlSignature(doc, certPem) {
10572
+ function pemToArrayBuffer(pem) {
10573
+ const base64 = pem.replace(/-----[^-]+-----/g, "").replace(/\s+/g, "");
10574
+ const binary = atob(base64);
10575
+ const bytes = new Uint8Array(binary.length);
10576
+ for (let i = 0; i < binary.length; i++) {
10577
+ bytes[i] = binary.charCodeAt(i);
10578
+ }
10579
+ return bytes.buffer;
10580
+ }
10581
+ function base64ToArrayBuffer(b64) {
10582
+ let base64 = b64.replace(/-/g, "+").replace(/_/g, "/");
10583
+ while (base64.length % 4 !== 0) base64 += "=";
10584
+ const binary = atob(base64);
10585
+ const bytes = new Uint8Array(binary.length);
10586
+ for (let i = 0; i < binary.length; i++) {
10587
+ bytes[i] = binary.charCodeAt(i);
10588
+ }
10589
+ return bytes.buffer;
10590
+ }
10591
+ async function verifySamlSignature(doc, certPem) {
10575
10592
  const signatureNode = findElement(doc, "Signature");
10576
10593
  if (!signatureNode) return false;
10577
10594
  const signedInfoNode = findElement(signatureNode, "SignedInfo");
@@ -10617,15 +10634,22 @@ function verifySamlSignature(doc, certPem) {
10617
10634
  referencedContent = removeSignatureFromXml(doc.rawOuterXml);
10618
10635
  }
10619
10636
  if (referencedContent && expectedDigest) {
10620
- let hashAlgo;
10637
+ let digestHashName;
10621
10638
  if (digestAlgo.includes("sha256") || digestAlgo.includes("SHA256")) {
10622
- hashAlgo = "sha256";
10639
+ digestHashName = "SHA-256";
10623
10640
  } else if (digestAlgo.includes("sha1") || digestAlgo.includes("SHA1")) {
10624
- hashAlgo = "sha1";
10641
+ digestHashName = "SHA-1";
10625
10642
  } else {
10626
- hashAlgo = "sha256";
10643
+ digestHashName = "SHA-256";
10644
+ }
10645
+ const contentBuf = new TextEncoder().encode(referencedContent);
10646
+ const digestBuf = await globalThis.crypto.subtle.digest(digestHashName, contentBuf);
10647
+ const digestBytes = new Uint8Array(digestBuf);
10648
+ let digestBinary = "";
10649
+ for (let i = 0; i < digestBytes.length; i++) {
10650
+ digestBinary += String.fromCharCode(digestBytes[i]);
10627
10651
  }
10628
- const actualDigest = createHash(hashAlgo).update(referencedContent).digest("base64");
10652
+ const actualDigest = btoa(digestBinary);
10629
10653
  if (actualDigest !== expectedDigest) {
10630
10654
  return false;
10631
10655
  }
@@ -10635,10 +10659,24 @@ function verifySamlSignature(doc, certPem) {
10635
10659
  const normalizedCert = certPem.includes("-----") ? certPem : `-----BEGIN CERTIFICATE-----
10636
10660
  ${certPem}
10637
10661
  -----END CERTIFICATE-----`;
10638
- const verifier = createVerify(nodeAlgo);
10639
- verifier.update(signedInfoNode.rawOuterXml);
10640
10662
  try {
10641
- return verifier.verify(normalizedCert, sigValue, "base64");
10663
+ const hashName = nodeAlgo === "RSA-SHA1" ? "SHA-1" : "SHA-256";
10664
+ const certDer = pemToArrayBuffer(normalizedCert);
10665
+ const cryptoKey = await globalThis.crypto.subtle.importKey(
10666
+ "spki",
10667
+ certDer,
10668
+ { name: "RSASSA-PKCS1-v1_5", hash: hashName },
10669
+ false,
10670
+ ["verify"]
10671
+ );
10672
+ const signatureBuffer = base64ToArrayBuffer(sigValue);
10673
+ const dataBuffer = new TextEncoder().encode(signedInfoNode.rawOuterXml);
10674
+ return await globalThis.crypto.subtle.verify(
10675
+ "RSASSA-PKCS1-v1_5",
10676
+ cryptoKey,
10677
+ signatureBuffer,
10678
+ dataBuffer
10679
+ );
10642
10680
  } catch {
10643
10681
  return false;
10644
10682
  }
@@ -10655,7 +10693,7 @@ function removeSignatureFromXml(xml) {
10655
10693
  }
10656
10694
  return result;
10657
10695
  }
10658
- function parseSamlResponse(samlResponse, provider, expectedRequestId) {
10696
+ async function parseSamlResponse(samlResponse, provider, expectedRequestId) {
10659
10697
  const decoded = atob(samlResponse);
10660
10698
  let doc;
10661
10699
  try {
@@ -10683,7 +10721,7 @@ function parseSamlResponse(samlResponse, provider, expectedRequestId) {
10683
10721
  "SAML response is not signed but signature is required"
10684
10722
  );
10685
10723
  }
10686
- if (!verifySamlSignature(doc, provider.cert)) {
10724
+ if (!await verifySamlSignature(doc, provider.cert)) {
10687
10725
  throw new SsoError(
10688
10726
  SSO_ERROR.SAML_SIGNATURE_INVALID,
10689
10727
  "SAML response signature verification failed"
@@ -10839,20 +10877,22 @@ var RateLimiter = class {
10839
10877
  }
10840
10878
  }
10841
10879
  };
10842
- function encodeState(stateTtlSeconds) {
10880
+ async function encodeState(stateTtlSeconds) {
10843
10881
  const now = Date.now();
10844
10882
  const expires = now + stateTtlSeconds * 1e3;
10845
- const random = randomBytes$1(16).toString("hex");
10883
+ const random = randomBytesHex(16);
10846
10884
  const payload = `${random}.${expires}`;
10847
- const hash = createHash("sha256").update(payload).digest("hex").slice(0, 8);
10885
+ const hashBytes = await sha256Raw(payload);
10886
+ const hash = toHex(hashBytes).slice(0, 8);
10848
10887
  return `${payload}.${hash}`;
10849
10888
  }
10850
- function validateStateToken(state) {
10889
+ async function validateStateToken(state) {
10851
10890
  const parts = state.split(".");
10852
10891
  if (parts.length !== 3) return false;
10853
10892
  const [random, expiresStr, hash] = parts;
10854
10893
  const payload = `${random}.${expiresStr}`;
10855
- const expectedHash = createHash("sha256").update(payload).digest("hex").slice(0, 8);
10894
+ const hashBytes = await sha256Raw(payload);
10895
+ const expectedHash = toHex(hashBytes).slice(0, 8);
10856
10896
  if (hash !== expectedHash) return false;
10857
10897
  const expires = Number.parseInt(expiresStr, 10);
10858
10898
  if (Number.isNaN(expires)) return false;
@@ -10887,7 +10927,7 @@ function createSsoModule(config, db) {
10887
10927
  auditLog({ ...event, timestamp: /* @__PURE__ */ new Date() });
10888
10928
  }
10889
10929
  async function createConnection(input) {
10890
- const id = `sso_${randomUUID().replace(/-/g, "")}`;
10930
+ const id = `sso_${generateId().replace(/-/g, "")}`;
10891
10931
  const now = /* @__PURE__ */ new Date();
10892
10932
  await db.insert(ssoConnections).values({
10893
10933
  id,
@@ -10980,8 +11020,9 @@ function createSsoModule(config, db) {
10980
11020
  `SAML provider "${conn.providerId}" not configured`
10981
11021
  );
10982
11022
  try {
10983
- const { email, name } = parseSamlResponse(samlResponse, provider, expectedRequestId);
10984
- const userId = `saml_${createHash("sha256").update(`${conn.providerId}:${email}`).digest("hex").slice(0, 32)}`;
11023
+ const { email, name } = await parseSamlResponse(samlResponse, provider, expectedRequestId);
11024
+ const userIdHash = await sha256Raw(`${conn.providerId}:${email}`);
11025
+ const userId = `saml_${toHex(userIdHash).slice(0, 32)}`;
10985
11026
  emitAudit({
10986
11027
  type: "sso_login_success",
10987
11028
  connectionId,
@@ -11114,8 +11155,8 @@ function createSsoModule(config, db) {
11114
11155
  }
11115
11156
  if (payload.at_hash && tokens.access_token) {
11116
11157
  const atHash = payload.at_hash;
11117
- const accessTokenHash = createHash("sha256").update(tokens.access_token).digest();
11118
- const leftHalf = accessTokenHash.subarray(0, accessTokenHash.length / 2);
11158
+ const accessTokenHashBytes = await sha256Raw(tokens.access_token);
11159
+ const leftHalf = accessTokenHashBytes.subarray(0, accessTokenHashBytes.length / 2);
11119
11160
  const expectedAtHash = uint8ArrayToBase64Url(leftHalf);
11120
11161
  if (atHash !== expectedAtHash) {
11121
11162
  emitAudit({
@@ -11134,7 +11175,8 @@ function createSsoModule(config, db) {
11134
11175
  );
11135
11176
  }
11136
11177
  const name = payload.name ?? void 0;
11137
- const userId = `oidc_${createHash("sha256").update(`${conn.providerId}:${payload.sub}`).digest("hex").slice(0, 32)}`;
11178
+ const oidcUserIdHash = await sha256Raw(`${conn.providerId}:${payload.sub}`);
11179
+ const userId = `oidc_${toHex(oidcUserIdHash).slice(0, 32)}`;
11138
11180
  emitAudit({
11139
11181
  type: "sso_login_success",
11140
11182
  connectionId,
@@ -11146,10 +11188,10 @@ function createSsoModule(config, db) {
11146
11188
  orgId: conn.orgId
11147
11189
  };
11148
11190
  }
11149
- function generateState() {
11191
+ async function generateState() {
11150
11192
  return encodeState(stateTtlSeconds);
11151
11193
  }
11152
- function validateState(state) {
11194
+ async function validateState(state) {
11153
11195
  return validateStateToken(state);
11154
11196
  }
11155
11197
  async function handleRequest(request) {
@@ -12512,5 +12554,5 @@ function createWebhookModule(configs) {
12512
12554
  }
12513
12555
 
12514
12556
  export { EVENT_TYPES, HibpApiError, HibpBreachedError, OAuthProxyError, OneTapVerifyError, SSO_ERROR, SsoError, additionalFields, admin, anonymousAuth, apiKeys2 as apiKeys, bearerAuth, createAdditionalFieldsModule, createAdminModule, createAnonymousAuthModule, createApiKeyManagerModule, createCaptchaModule, createCostAttributionModule, createCustomSessionModule, createDeviceAuthModule, createEmailOtpModule, createEmailVerificationModule, createEphemeralSessionModule, createEventStreamModule, createFederationModule, createGdprModule, createHibpModule, createJwtSessionModule, createLastLoginModule, createMagicLinkModule, createOAuthProxyModule, createOidcProviderModule, createOneTapModule, createOneTimeTokenModule, createOpenApiModule, createOrgModule, createPasskeyModule, createPasswordResetModule, createPhoneAuthModule, createPolarModule, createRateLimiter, createReBACModule, createScimModule, createSessionManager, createSiweModule, createSsoModule, createStripeModule, createTotpModule, createTrustedDeviceModule, createUsernameAuthModule, createWebhookModule, customAuth, customSession, deviceAuth, deviceLabelFromRequest, emailOtp, gdpr, headerAuth, magicLink, oauthProxy, oneTap, organization, passkey, polar, scim, siwe, stripe, twoFactor, withRateLimit };
12515
- //# sourceMappingURL=chunk-FKVAXCNJ.js.map
12516
- //# sourceMappingURL=chunk-FKVAXCNJ.js.map
12557
+ //# sourceMappingURL=chunk-IEOOSOJ4.js.map
12558
+ //# sourceMappingURL=chunk-IEOOSOJ4.js.map