@objectstack/plugin-auth 6.1.1 → 6.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/index.d.mts +20 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -4
package/dist/index.d.mts
CHANGED
|
@@ -212,6 +212,26 @@ declare class AuthManager {
|
|
|
212
212
|
* Create a better-auth instance from configuration
|
|
213
213
|
*/
|
|
214
214
|
private createAuthInstance;
|
|
215
|
+
/**
|
|
216
|
+
* Detect WebContainer (StackBlitz) and swap in a pure-JS scrypt hasher.
|
|
217
|
+
*
|
|
218
|
+
* better-auth defaults to `@better-auth/utils/password.node`, which calls
|
|
219
|
+
* `node:crypto.scrypt`. WebContainer polyfills that API incompletely and
|
|
220
|
+
* signup throws `TypeError: y.run is not a function`.
|
|
221
|
+
*
|
|
222
|
+
* We can't dynamic-import `@better-auth/utils/password` because that
|
|
223
|
+
* package's `exports` map gates the pure-JS build behind a non-`"node"`
|
|
224
|
+
* condition — Node-the-runtime (which WebContainer reports itself as)
|
|
225
|
+
* always resolves to `password.node.mjs`. So we reimplement the same hash
|
|
226
|
+
* here using `@noble/hashes/scrypt` directly, with byte-identical params
|
|
227
|
+
* (N=16384, r=16, p=1, dkLen=64) and the same `{saltHex}:{keyHex}` storage
|
|
228
|
+
* format. Hashes produced by either implementation verify against the
|
|
229
|
+
* other — no migration needed.
|
|
230
|
+
*
|
|
231
|
+
* Returns `undefined` outside WebContainer so production deployments keep
|
|
232
|
+
* the native (fast) hasher and never load `@noble/hashes`.
|
|
233
|
+
*/
|
|
234
|
+
private resolvePasswordHasher;
|
|
215
235
|
/**
|
|
216
236
|
* Build the list of better-auth plugins based on AuthPluginConfig flags.
|
|
217
237
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -212,6 +212,26 @@ declare class AuthManager {
|
|
|
212
212
|
* Create a better-auth instance from configuration
|
|
213
213
|
*/
|
|
214
214
|
private createAuthInstance;
|
|
215
|
+
/**
|
|
216
|
+
* Detect WebContainer (StackBlitz) and swap in a pure-JS scrypt hasher.
|
|
217
|
+
*
|
|
218
|
+
* better-auth defaults to `@better-auth/utils/password.node`, which calls
|
|
219
|
+
* `node:crypto.scrypt`. WebContainer polyfills that API incompletely and
|
|
220
|
+
* signup throws `TypeError: y.run is not a function`.
|
|
221
|
+
*
|
|
222
|
+
* We can't dynamic-import `@better-auth/utils/password` because that
|
|
223
|
+
* package's `exports` map gates the pure-JS build behind a non-`"node"`
|
|
224
|
+
* condition — Node-the-runtime (which WebContainer reports itself as)
|
|
225
|
+
* always resolves to `password.node.mjs`. So we reimplement the same hash
|
|
226
|
+
* here using `@noble/hashes/scrypt` directly, with byte-identical params
|
|
227
|
+
* (N=16384, r=16, p=1, dkLen=64) and the same `{saltHex}:{keyHex}` storage
|
|
228
|
+
* format. Hashes produced by either implementation verify against the
|
|
229
|
+
* other — no migration needed.
|
|
230
|
+
*
|
|
231
|
+
* Returns `undefined` outside WebContainer so production deployments keep
|
|
232
|
+
* the native (fast) hasher and never load `@noble/hashes`.
|
|
233
|
+
*/
|
|
234
|
+
private resolvePasswordHasher;
|
|
215
235
|
/**
|
|
216
236
|
* Build the list of better-auth plugins based on AuthPluginConfig flags.
|
|
217
237
|
*
|
package/dist/index.js
CHANGED
|
@@ -547,6 +547,7 @@ var AuthManager = class {
|
|
|
547
547
|
async createAuthInstance() {
|
|
548
548
|
const { betterAuth } = await import("better-auth");
|
|
549
549
|
const plugins = await this.buildPluginList();
|
|
550
|
+
const passwordHasher = await this.resolvePasswordHasher();
|
|
550
551
|
const betterAuthConfig = {
|
|
551
552
|
// Base configuration
|
|
552
553
|
secret: this.config.secret || this.generateSecret(),
|
|
@@ -606,6 +607,7 @@ var AuthManager = class {
|
|
|
606
607
|
// Email and password configuration
|
|
607
608
|
emailAndPassword: {
|
|
608
609
|
enabled: this.config.emailAndPassword?.enabled ?? true,
|
|
610
|
+
...passwordHasher ? { password: passwordHasher } : {},
|
|
609
611
|
...this.config.emailAndPassword?.disableSignUp != null ? { disableSignUp: this.config.emailAndPassword.disableSignUp } : {},
|
|
610
612
|
...this.config.emailAndPassword?.requireEmailVerification != null ? { requireEmailVerification: this.config.emailAndPassword.requireEmailVerification } : {},
|
|
611
613
|
...this.config.emailAndPassword?.minPasswordLength != null ? { minPasswordLength: this.config.emailAndPassword.minPasswordLength } : {},
|
|
@@ -722,6 +724,58 @@ var AuthManager = class {
|
|
|
722
724
|
};
|
|
723
725
|
return betterAuth(betterAuthConfig);
|
|
724
726
|
}
|
|
727
|
+
/**
|
|
728
|
+
* Detect WebContainer (StackBlitz) and swap in a pure-JS scrypt hasher.
|
|
729
|
+
*
|
|
730
|
+
* better-auth defaults to `@better-auth/utils/password.node`, which calls
|
|
731
|
+
* `node:crypto.scrypt`. WebContainer polyfills that API incompletely and
|
|
732
|
+
* signup throws `TypeError: y.run is not a function`.
|
|
733
|
+
*
|
|
734
|
+
* We can't dynamic-import `@better-auth/utils/password` because that
|
|
735
|
+
* package's `exports` map gates the pure-JS build behind a non-`"node"`
|
|
736
|
+
* condition — Node-the-runtime (which WebContainer reports itself as)
|
|
737
|
+
* always resolves to `password.node.mjs`. So we reimplement the same hash
|
|
738
|
+
* here using `@noble/hashes/scrypt` directly, with byte-identical params
|
|
739
|
+
* (N=16384, r=16, p=1, dkLen=64) and the same `{saltHex}:{keyHex}` storage
|
|
740
|
+
* format. Hashes produced by either implementation verify against the
|
|
741
|
+
* other — no migration needed.
|
|
742
|
+
*
|
|
743
|
+
* Returns `undefined` outside WebContainer so production deployments keep
|
|
744
|
+
* the native (fast) hasher and never load `@noble/hashes`.
|
|
745
|
+
*/
|
|
746
|
+
async resolvePasswordHasher() {
|
|
747
|
+
const isWebContainer = typeof globalThis !== "undefined" && (Boolean(globalThis.process?.versions?.webcontainer) || Boolean(globalThis.process?.env?.SHELL?.includes?.("jsh")) || Boolean(globalThis.process?.env?.STACKBLITZ));
|
|
748
|
+
if (!isWebContainer) return void 0;
|
|
749
|
+
try {
|
|
750
|
+
const { scryptAsync } = await import("@noble/hashes/scrypt.js");
|
|
751
|
+
const PARAMS = { N: 16384, r: 16, p: 1, dkLen: 64, maxmem: 128 * 16384 * 16 * 2 };
|
|
752
|
+
const toHex = (b) => {
|
|
753
|
+
let s = "";
|
|
754
|
+
for (let i = 0; i < b.length; i++) s += b[i].toString(16).padStart(2, "0");
|
|
755
|
+
return s;
|
|
756
|
+
};
|
|
757
|
+
const generateKey = (password, saltHex) => scryptAsync(password.normalize("NFKC"), saltHex, PARAMS);
|
|
758
|
+
return {
|
|
759
|
+
hash: async (password) => {
|
|
760
|
+
const saltBytes = globalThis.crypto.getRandomValues(new Uint8Array(16));
|
|
761
|
+
const saltHex = toHex(saltBytes);
|
|
762
|
+
const key = await generateKey(password, saltHex);
|
|
763
|
+
return `${saltHex}:${toHex(key)}`;
|
|
764
|
+
},
|
|
765
|
+
verify: async ({ hash, password }) => {
|
|
766
|
+
const [saltHex, keyHex] = hash.split(":");
|
|
767
|
+
if (!saltHex || !keyHex) throw new Error("Invalid password hash");
|
|
768
|
+
const target = await generateKey(password, saltHex);
|
|
769
|
+
return toHex(target) === keyHex;
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
} catch (err) {
|
|
773
|
+
console.warn(
|
|
774
|
+
`[AuthManager] WebContainer detected but pure-JS scrypt unavailable: ${err?.message ?? err}. Falling back to default.`
|
|
775
|
+
);
|
|
776
|
+
return void 0;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
725
779
|
/**
|
|
726
780
|
* Build the list of better-auth plugins based on AuthPluginConfig flags.
|
|
727
781
|
*
|