@korajs/auth 0.3.0 → 0.3.2

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/server.cjs CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __esm = (fn, res) => function __init() {
7
9
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -18,12 +20,23 @@ var __copyProps = (to, from, except, desc) => {
18
20
  }
19
21
  return to;
20
22
  };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
21
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
22
32
 
23
33
  // ../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js
34
+ var getImportMetaUrl, importMetaUrl;
24
35
  var init_cjs_shims = __esm({
25
36
  "../../node_modules/.pnpm/tsup@8.5.1_postcss@8.5.8_tsx@4.21.0_typescript@5.9.3/node_modules/tsup/assets/cjs_shims.js"() {
26
37
  "use strict";
38
+ getImportMetaUrl = () => typeof document === "undefined" ? new URL(`file:${__filename}`).href : document.currentScript && document.currentScript.tagName.toUpperCase() === "SCRIPT" ? document.currentScript.src : new URL("main.js", document.baseURI).href;
39
+ importMetaUrl = /* @__PURE__ */ getImportMetaUrl();
27
40
  }
28
41
  });
29
42
 
@@ -143,6 +156,7 @@ __export(server_exports, {
143
156
  PasskeyVerificationError: () => PasskeyVerificationError,
144
157
  PasswordResetError: () => PasswordResetError,
145
158
  PasswordResetManager: () => PasswordResetManager,
159
+ PostgresUserStore: () => PostgresUserStore,
146
160
  ROLE_HIERARCHY: () => ROLE_HIERARCHY,
147
161
  RbacEngine: () => RbacEngine,
148
162
  RbacError: () => RbacError,
@@ -156,6 +170,7 @@ __export(server_exports, {
156
170
  SessionManager: () => SessionManager,
157
171
  SessionMfaRequiredError: () => SessionMfaRequiredError,
158
172
  SessionNotFoundError: () => SessionNotFoundError,
173
+ SqliteUserStore: () => SqliteUserStore,
159
174
  TokenManager: () => TokenManager,
160
175
  TotpAlreadyEnabledError: () => TotpAlreadyEnabledError,
161
176
  TotpError: () => TotpError,
@@ -173,6 +188,8 @@ __export(server_exports, {
173
188
  base32Encode: () => base32Encode,
174
189
  computePublicKeyThumbprint: () => computePublicKeyThumbprint,
175
190
  createClerkAdapter: () => createClerkAdapter,
191
+ createPostgresUserStore: () => createPostgresUserStore,
192
+ createSqliteUserStore: () => createSqliteUserStore,
176
193
  createSupabaseAdapter: () => createSupabaseAdapter,
177
194
  decodeJwt: () => decodeJwt,
178
195
  defineRoles: () => defineRoles,
@@ -1946,6 +1963,385 @@ function generateSecureToken2() {
1946
1963
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1947
1964
  }
1948
1965
 
1966
+ // src/provider/built-in/sqlite-user-store.ts
1967
+ init_cjs_shims();
1968
+ var import_node_crypto6 = require("crypto");
1969
+ var SqliteUserStore = class {
1970
+ db;
1971
+ constructor(db) {
1972
+ this.db = db;
1973
+ this.db.pragma("journal_mode = WAL");
1974
+ this.ensureTables();
1975
+ }
1976
+ ensureTables() {
1977
+ this.db.exec(`
1978
+ CREATE TABLE IF NOT EXISTS auth_users (
1979
+ id TEXT PRIMARY KEY,
1980
+ email TEXT NOT NULL UNIQUE COLLATE NOCASE,
1981
+ name TEXT NOT NULL,
1982
+ email_verified INTEGER NOT NULL DEFAULT 0,
1983
+ created_at INTEGER NOT NULL,
1984
+ password_hash TEXT NOT NULL,
1985
+ salt TEXT NOT NULL
1986
+ );
1987
+
1988
+ CREATE TABLE IF NOT EXISTS auth_devices (
1989
+ id TEXT PRIMARY KEY,
1990
+ user_id TEXT NOT NULL,
1991
+ public_key TEXT NOT NULL,
1992
+ name TEXT NOT NULL,
1993
+ revoked INTEGER NOT NULL DEFAULT 0,
1994
+ created_at INTEGER NOT NULL,
1995
+ last_seen_at INTEGER NOT NULL,
1996
+ FOREIGN KEY (user_id) REFERENCES auth_users(id) ON DELETE CASCADE
1997
+ );
1998
+
1999
+ CREATE INDEX IF NOT EXISTS idx_auth_devices_user_id ON auth_devices(user_id);
2000
+ `);
2001
+ }
2002
+ async createUser(params) {
2003
+ const normalizedEmail = params.email.toLowerCase();
2004
+ const now = Date.now();
2005
+ const id = (0, import_node_crypto6.randomUUID)();
2006
+ try {
2007
+ this.db.prepare(`
2008
+ INSERT INTO auth_users (id, email, name, email_verified, created_at, password_hash, salt)
2009
+ VALUES (?, ?, ?, 0, ?, ?, ?)
2010
+ `).run(id, normalizedEmail, params.name, now, params.passwordHash, params.salt);
2011
+ } catch (err) {
2012
+ if (err instanceof Error && err.message.includes("UNIQUE constraint failed")) {
2013
+ throw new DuplicateEmailError();
2014
+ }
2015
+ throw err;
2016
+ }
2017
+ return { id, email: normalizedEmail, name: params.name, emailVerified: false, createdAt: now };
2018
+ }
2019
+ async findByEmail(email) {
2020
+ const row = this.db.prepare(
2021
+ "SELECT * FROM auth_users WHERE email = ?"
2022
+ ).get(email.toLowerCase());
2023
+ return row ? rowToStoredUser(row) : null;
2024
+ }
2025
+ async findById(id) {
2026
+ const row = this.db.prepare(
2027
+ "SELECT * FROM auth_users WHERE id = ?"
2028
+ ).get(id);
2029
+ return row ? rowToStoredUser(row) : null;
2030
+ }
2031
+ async registerDevice(params) {
2032
+ const existing = this.db.prepare(
2033
+ "SELECT * FROM auth_devices WHERE id = ?"
2034
+ ).get(params.id);
2035
+ if (existing && !existing.revoked) {
2036
+ return rowToDevice(existing);
2037
+ }
2038
+ const now = Date.now();
2039
+ if (existing) {
2040
+ this.db.prepare(`
2041
+ UPDATE auth_devices SET revoked = 0, public_key = ?, name = ?, last_seen_at = ?
2042
+ WHERE id = ?
2043
+ `).run(params.publicKey, params.name, now, params.id);
2044
+ } else {
2045
+ this.db.prepare(`
2046
+ INSERT INTO auth_devices (id, user_id, public_key, name, revoked, created_at, last_seen_at)
2047
+ VALUES (?, ?, ?, ?, 0, ?, ?)
2048
+ `).run(params.id, params.userId, params.publicKey, params.name, now, now);
2049
+ }
2050
+ return {
2051
+ id: params.id,
2052
+ userId: params.userId,
2053
+ publicKey: params.publicKey,
2054
+ name: params.name,
2055
+ revoked: false,
2056
+ createdAt: existing ? existing.created_at : now,
2057
+ lastSeenAt: now
2058
+ };
2059
+ }
2060
+ async findDevice(deviceId) {
2061
+ const row = this.db.prepare(
2062
+ "SELECT * FROM auth_devices WHERE id = ?"
2063
+ ).get(deviceId);
2064
+ return row ? rowToDevice(row) : null;
2065
+ }
2066
+ async listDevices(userId) {
2067
+ const rows = this.db.prepare(
2068
+ "SELECT * FROM auth_devices WHERE user_id = ?"
2069
+ ).all(userId);
2070
+ return rows.map(rowToDevice);
2071
+ }
2072
+ async revokeDevice(deviceId) {
2073
+ this.db.prepare("UPDATE auth_devices SET revoked = 1 WHERE id = ?").run(deviceId);
2074
+ }
2075
+ async setEmailVerified(userId, verified) {
2076
+ this.db.prepare(
2077
+ "UPDATE auth_users SET email_verified = ? WHERE id = ?"
2078
+ ).run(verified ? 1 : 0, userId);
2079
+ }
2080
+ async updatePassword(userId, passwordHash, salt) {
2081
+ this.db.prepare(
2082
+ "UPDATE auth_users SET password_hash = ?, salt = ? WHERE id = ?"
2083
+ ).run(passwordHash, salt, userId);
2084
+ }
2085
+ async listAll() {
2086
+ const rows = this.db.prepare("SELECT * FROM auth_users").all();
2087
+ return rows.map(rowToStoredUser);
2088
+ }
2089
+ async update(user) {
2090
+ this.db.prepare(`
2091
+ UPDATE auth_users
2092
+ SET email = ?, name = ?, email_verified = ?, password_hash = ?, salt = ?
2093
+ WHERE id = ?
2094
+ `).run(user.email, user.name, user.emailVerified ? 1 : 0, user.passwordHash, user.salt, user.id);
2095
+ }
2096
+ async delete(userId) {
2097
+ const deleteInTransaction = this.db.transaction(() => {
2098
+ this.db.prepare("DELETE FROM auth_devices WHERE user_id = ?").run(userId);
2099
+ this.db.prepare("DELETE FROM auth_users WHERE id = ?").run(userId);
2100
+ });
2101
+ deleteInTransaction();
2102
+ }
2103
+ async touchDevice(deviceId) {
2104
+ this.db.prepare(
2105
+ "UPDATE auth_devices SET last_seen_at = ? WHERE id = ?"
2106
+ ).run(Date.now(), deviceId);
2107
+ }
2108
+ };
2109
+ async function createSqliteUserStore(options) {
2110
+ const Database = await loadBetterSqlite3();
2111
+ const db = new Database(options.filename);
2112
+ return new SqliteUserStore(db);
2113
+ }
2114
+ async function loadBetterSqlite3() {
2115
+ try {
2116
+ const { createRequire } = await import("module");
2117
+ const require2 = createRequire(importMetaUrl);
2118
+ return require2("better-sqlite3");
2119
+ } catch {
2120
+ throw new Error(
2121
+ 'SQLite backend requires the "better-sqlite3" package. Install it in your project dependencies.'
2122
+ );
2123
+ }
2124
+ }
2125
+ function rowToStoredUser(row) {
2126
+ return {
2127
+ id: row.id,
2128
+ email: row.email,
2129
+ name: row.name,
2130
+ emailVerified: Boolean(row.email_verified),
2131
+ createdAt: row.created_at,
2132
+ passwordHash: row.password_hash,
2133
+ salt: row.salt
2134
+ };
2135
+ }
2136
+ function rowToDevice(row) {
2137
+ return {
2138
+ id: row.id,
2139
+ userId: row.user_id,
2140
+ publicKey: row.public_key,
2141
+ name: row.name,
2142
+ revoked: Boolean(row.revoked),
2143
+ createdAt: row.created_at,
2144
+ lastSeenAt: row.last_seen_at
2145
+ };
2146
+ }
2147
+
2148
+ // src/provider/built-in/postgres-user-store.ts
2149
+ init_cjs_shims();
2150
+ var import_node_crypto7 = require("crypto");
2151
+ var PostgresUserStore = class {
2152
+ sql;
2153
+ ready;
2154
+ constructor(sql) {
2155
+ this.sql = sql;
2156
+ this.ready = this.ensureTables();
2157
+ }
2158
+ async ensureTables() {
2159
+ await this.sql`
2160
+ CREATE TABLE IF NOT EXISTS auth_users (
2161
+ id TEXT PRIMARY KEY,
2162
+ email TEXT NOT NULL UNIQUE,
2163
+ name TEXT NOT NULL,
2164
+ email_verified BOOLEAN NOT NULL DEFAULT FALSE,
2165
+ created_at BIGINT NOT NULL,
2166
+ password_hash TEXT NOT NULL,
2167
+ salt TEXT NOT NULL
2168
+ )
2169
+ `;
2170
+ await this.sql`
2171
+ CREATE TABLE IF NOT EXISTS auth_devices (
2172
+ id TEXT PRIMARY KEY,
2173
+ user_id TEXT NOT NULL REFERENCES auth_users(id) ON DELETE CASCADE,
2174
+ public_key TEXT NOT NULL,
2175
+ name TEXT NOT NULL,
2176
+ revoked BOOLEAN NOT NULL DEFAULT FALSE,
2177
+ created_at BIGINT NOT NULL,
2178
+ last_seen_at BIGINT NOT NULL
2179
+ )
2180
+ `;
2181
+ await this.sql`
2182
+ CREATE INDEX IF NOT EXISTS idx_auth_devices_user_id ON auth_devices(user_id)
2183
+ `;
2184
+ await this.sql`
2185
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_auth_users_email_lower ON auth_users(LOWER(email))
2186
+ `;
2187
+ }
2188
+ async createUser(params) {
2189
+ await this.ready;
2190
+ const normalizedEmail = params.email.toLowerCase();
2191
+ const now = Date.now();
2192
+ const id = (0, import_node_crypto7.randomUUID)();
2193
+ try {
2194
+ await this.sql`
2195
+ INSERT INTO auth_users (id, email, name, email_verified, created_at, password_hash, salt)
2196
+ VALUES (${id}, ${normalizedEmail}, ${params.name}, FALSE, ${now}, ${params.passwordHash}, ${params.salt})
2197
+ `;
2198
+ } catch (err) {
2199
+ if (err instanceof Error && (err.message.includes("unique constraint") || err.message.includes("duplicate key"))) {
2200
+ throw new DuplicateEmailError();
2201
+ }
2202
+ throw err;
2203
+ }
2204
+ return { id, email: normalizedEmail, name: params.name, emailVerified: false, createdAt: now };
2205
+ }
2206
+ async findByEmail(email) {
2207
+ await this.ready;
2208
+ const rows = await this.sql`
2209
+ SELECT * FROM auth_users WHERE LOWER(email) = ${email.toLowerCase()}
2210
+ `;
2211
+ return rows.length > 0 ? rowToStoredUser2(rows[0]) : null;
2212
+ }
2213
+ async findById(id) {
2214
+ await this.ready;
2215
+ const rows = await this.sql`
2216
+ SELECT * FROM auth_users WHERE id = ${id}
2217
+ `;
2218
+ return rows.length > 0 ? rowToStoredUser2(rows[0]) : null;
2219
+ }
2220
+ async registerDevice(params) {
2221
+ await this.ready;
2222
+ const existingRows = await this.sql`
2223
+ SELECT * FROM auth_devices WHERE id = ${params.id}
2224
+ `;
2225
+ if (existingRows.length > 0 && !existingRows[0].revoked) {
2226
+ return rowToDevice2(existingRows[0]);
2227
+ }
2228
+ const now = Date.now();
2229
+ if (existingRows.length > 0) {
2230
+ await this.sql`
2231
+ UPDATE auth_devices SET revoked = FALSE, public_key = ${params.publicKey}, name = ${params.name}, last_seen_at = ${now}
2232
+ WHERE id = ${params.id}
2233
+ `;
2234
+ } else {
2235
+ await this.sql`
2236
+ INSERT INTO auth_devices (id, user_id, public_key, name, revoked, created_at, last_seen_at)
2237
+ VALUES (${params.id}, ${params.userId}, ${params.publicKey}, ${params.name}, FALSE, ${now}, ${now})
2238
+ `;
2239
+ }
2240
+ return {
2241
+ id: params.id,
2242
+ userId: params.userId,
2243
+ publicKey: params.publicKey,
2244
+ name: params.name,
2245
+ revoked: false,
2246
+ createdAt: existingRows.length > 0 ? Number(existingRows[0].created_at) : now,
2247
+ lastSeenAt: now
2248
+ };
2249
+ }
2250
+ async findDevice(deviceId) {
2251
+ await this.ready;
2252
+ const rows = await this.sql`
2253
+ SELECT * FROM auth_devices WHERE id = ${deviceId}
2254
+ `;
2255
+ return rows.length > 0 ? rowToDevice2(rows[0]) : null;
2256
+ }
2257
+ async listDevices(userId) {
2258
+ await this.ready;
2259
+ const rows = await this.sql`
2260
+ SELECT * FROM auth_devices WHERE user_id = ${userId}
2261
+ `;
2262
+ return rows.map(rowToDevice2);
2263
+ }
2264
+ async revokeDevice(deviceId) {
2265
+ await this.ready;
2266
+ await this.sql`UPDATE auth_devices SET revoked = TRUE WHERE id = ${deviceId}`;
2267
+ }
2268
+ async setEmailVerified(userId, verified) {
2269
+ await this.ready;
2270
+ await this.sql`UPDATE auth_users SET email_verified = ${verified} WHERE id = ${userId}`;
2271
+ }
2272
+ async updatePassword(userId, passwordHash, salt) {
2273
+ await this.ready;
2274
+ await this.sql`
2275
+ UPDATE auth_users SET password_hash = ${passwordHash}, salt = ${salt}
2276
+ WHERE id = ${userId}
2277
+ `;
2278
+ }
2279
+ async listAll() {
2280
+ await this.ready;
2281
+ const rows = await this.sql`SELECT * FROM auth_users`;
2282
+ return rows.map(rowToStoredUser2);
2283
+ }
2284
+ async update(user) {
2285
+ await this.ready;
2286
+ await this.sql`
2287
+ UPDATE auth_users
2288
+ SET email = ${user.email}, name = ${user.name}, email_verified = ${user.emailVerified},
2289
+ password_hash = ${user.passwordHash}, salt = ${user.salt}
2290
+ WHERE id = ${user.id}
2291
+ `;
2292
+ }
2293
+ async delete(userId) {
2294
+ await this.ready;
2295
+ await this.sql.begin(async (tx) => {
2296
+ await tx`DELETE FROM auth_devices WHERE user_id = ${userId}`;
2297
+ await tx`DELETE FROM auth_users WHERE id = ${userId}`;
2298
+ });
2299
+ }
2300
+ async touchDevice(deviceId) {
2301
+ await this.ready;
2302
+ const now = Date.now();
2303
+ await this.sql`UPDATE auth_devices SET last_seen_at = ${now} WHERE id = ${deviceId}`;
2304
+ }
2305
+ };
2306
+ async function createPostgresUserStore(options) {
2307
+ const postgresClient = await loadPostgresDeps();
2308
+ const sql = postgresClient(options.connectionString);
2309
+ return new PostgresUserStore(sql);
2310
+ }
2311
+ async function loadPostgresDeps() {
2312
+ try {
2313
+ const dynamicImport = new Function("specifier", "return import(specifier)");
2314
+ const postgresMod = await dynamicImport("postgres");
2315
+ return postgresMod.default;
2316
+ } catch {
2317
+ throw new Error(
2318
+ 'PostgreSQL backend requires the "postgres" package. Install it in your project dependencies.'
2319
+ );
2320
+ }
2321
+ }
2322
+ function rowToStoredUser2(row) {
2323
+ return {
2324
+ id: row.id,
2325
+ email: row.email,
2326
+ name: row.name,
2327
+ emailVerified: Boolean(row.email_verified),
2328
+ createdAt: Number(row.created_at),
2329
+ passwordHash: row.password_hash,
2330
+ salt: row.salt
2331
+ };
2332
+ }
2333
+ function rowToDevice2(row) {
2334
+ return {
2335
+ id: row.id,
2336
+ userId: row.user_id,
2337
+ publicKey: row.public_key,
2338
+ name: row.name,
2339
+ revoked: Boolean(row.revoked),
2340
+ createdAt: Number(row.created_at),
2341
+ lastSeenAt: Number(row.last_seen_at)
2342
+ };
2343
+ }
2344
+
1949
2345
  // src/provider/adapter.ts
1950
2346
  init_cjs_shims();
1951
2347
  var AuthProviderError = class extends Error {
@@ -2341,7 +2737,7 @@ function createSupabaseAdapter(config) {
2341
2737
 
2342
2738
  // src/passkey/passkey-server.ts
2343
2739
  init_cjs_shims();
2344
- var import_node_crypto6 = require("crypto");
2740
+ var import_node_crypto8 = require("crypto");
2345
2741
  var import_core8 = require("@korajs/core");
2346
2742
 
2347
2743
  // src/passkey/passkey-client.ts
@@ -2435,7 +2831,7 @@ var PasskeyVerificationError = class extends import_core8.KoraError {
2435
2831
  }
2436
2832
  };
2437
2833
  function generateRegistrationOptions(params) {
2438
- const challengeBytes = (0, import_node_crypto6.randomBytes)(32);
2834
+ const challengeBytes = (0, import_node_crypto8.randomBytes)(32);
2439
2835
  const challenge = toBase64Url(challengeBytes.buffer.slice(
2440
2836
  challengeBytes.byteOffset,
2441
2837
  challengeBytes.byteOffset + challengeBytes.byteLength
@@ -2548,7 +2944,7 @@ async function verifyRegistrationResponse(params) {
2548
2944
  };
2549
2945
  }
2550
2946
  function generateAuthenticationOptions(params) {
2551
- const challengeBytes = (0, import_node_crypto6.randomBytes)(32);
2947
+ const challengeBytes = (0, import_node_crypto8.randomBytes)(32);
2552
2948
  const challenge = toBase64Url(challengeBytes.buffer.slice(
2553
2949
  challengeBytes.byteOffset,
2554
2950
  challengeBytes.byteOffset + challengeBytes.byteLength
@@ -5706,6 +6102,7 @@ function delay(ms) {
5706
6102
  PasskeyVerificationError,
5707
6103
  PasswordResetError,
5708
6104
  PasswordResetManager,
6105
+ PostgresUserStore,
5709
6106
  ROLE_HIERARCHY,
5710
6107
  RbacEngine,
5711
6108
  RbacError,
@@ -5719,6 +6116,7 @@ function delay(ms) {
5719
6116
  SessionManager,
5720
6117
  SessionMfaRequiredError,
5721
6118
  SessionNotFoundError,
6119
+ SqliteUserStore,
5722
6120
  TokenManager,
5723
6121
  TotpAlreadyEnabledError,
5724
6122
  TotpError,
@@ -5736,6 +6134,8 @@ function delay(ms) {
5736
6134
  base32Encode,
5737
6135
  computePublicKeyThumbprint,
5738
6136
  createClerkAdapter,
6137
+ createPostgresUserStore,
6138
+ createSqliteUserStore,
5739
6139
  createSupabaseAdapter,
5740
6140
  decodeJwt,
5741
6141
  defineRoles,