@contentgrowth/content-auth 0.0.2 → 0.0.4
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/backend/index.d.ts
CHANGED
|
@@ -1057,21 +1057,18 @@ interface AuthConfig {
|
|
|
1057
1057
|
* Use 'postgres' or 'mysql' if passing a Drizzle instance for those DBs.
|
|
1058
1058
|
*/
|
|
1059
1059
|
provider?: "sqlite" | "postgres" | "mysql";
|
|
1060
|
+
/**
|
|
1061
|
+
* Use Cloudflare native crypto.subtle for password hashing to avoid CPU limits.
|
|
1062
|
+
* Defaults to true. Set to false to use Better Auth's default (Scrypt/Argon2).
|
|
1063
|
+
*/
|
|
1064
|
+
useCloudflareNativeHashing?: boolean;
|
|
1060
1065
|
[key: string]: any;
|
|
1061
1066
|
}
|
|
1062
|
-
declare const createAuth: (config: AuthConfig) => better_auth.Auth<
|
|
1063
|
-
database: (options: better_auth.BetterAuthOptions) => better_auth.DBAdapter<better_auth.BetterAuthOptions>;
|
|
1064
|
-
secret: string;
|
|
1065
|
-
baseURL: string | undefined;
|
|
1066
|
-
}>;
|
|
1067
|
+
declare const createAuth: (config: AuthConfig) => better_auth.Auth<any>;
|
|
1067
1068
|
declare const authMiddleware: (auth: any) => (c: Context) => Promise<any>;
|
|
1068
1069
|
declare const createAuthApp: (config: AuthConfig) => {
|
|
1069
1070
|
app: Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
1070
|
-
auth: better_auth.Auth<
|
|
1071
|
-
database: (options: better_auth.BetterAuthOptions) => better_auth.DBAdapter<better_auth.BetterAuthOptions>;
|
|
1072
|
-
secret: string;
|
|
1073
|
-
baseURL: string | undefined;
|
|
1074
|
-
}>;
|
|
1071
|
+
auth: better_auth.Auth<any>;
|
|
1075
1072
|
};
|
|
1076
1073
|
|
|
1077
1074
|
export { type AuthConfig, authMiddleware, createAuth, createAuthApp, schema };
|
package/dist/backend/index.js
CHANGED
|
@@ -89,6 +89,67 @@ var invitations = sqliteTable("invitations", {
|
|
|
89
89
|
inviterId: text("inviterId").notNull().references(() => users.id, { onDelete: "cascade" })
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
+
// src/backend/native-hashing.ts
|
|
93
|
+
async function hashPassword(password) {
|
|
94
|
+
const salt = crypto.getRandomValues(new Uint8Array(16));
|
|
95
|
+
const enc = new TextEncoder();
|
|
96
|
+
const keyMaterial = await crypto.subtle.importKey(
|
|
97
|
+
"raw",
|
|
98
|
+
enc.encode(password),
|
|
99
|
+
{ name: "PBKDF2" },
|
|
100
|
+
false,
|
|
101
|
+
["deriveBits", "deriveKey"]
|
|
102
|
+
);
|
|
103
|
+
const hashBuffer = await crypto.subtle.deriveBits(
|
|
104
|
+
{
|
|
105
|
+
name: "PBKDF2",
|
|
106
|
+
salt,
|
|
107
|
+
iterations: 1e5,
|
|
108
|
+
hash: "SHA-256"
|
|
109
|
+
},
|
|
110
|
+
keyMaterial,
|
|
111
|
+
256
|
|
112
|
+
// 32 bytes
|
|
113
|
+
);
|
|
114
|
+
const saltB64 = btoa(String.fromCharCode(...new Uint8Array(salt)));
|
|
115
|
+
const hashB64 = btoa(String.fromCharCode(...new Uint8Array(hashBuffer)));
|
|
116
|
+
return `pbkdf2:100000:${saltB64}:${hashB64}`;
|
|
117
|
+
}
|
|
118
|
+
async function verifyPassword(password, storedHash) {
|
|
119
|
+
const parts = storedHash.split(":");
|
|
120
|
+
if (parts.length !== 4) return false;
|
|
121
|
+
const [alg, iterationsStr, saltB64, hashB64] = parts;
|
|
122
|
+
if (alg !== "pbkdf2") return false;
|
|
123
|
+
const iterations = parseInt(iterationsStr, 10);
|
|
124
|
+
const salt = Uint8Array.from(atob(saltB64), (c) => c.charCodeAt(0));
|
|
125
|
+
const originalHash = Uint8Array.from(atob(hashB64), (c) => c.charCodeAt(0));
|
|
126
|
+
const enc = new TextEncoder();
|
|
127
|
+
const keyMaterial = await crypto.subtle.importKey(
|
|
128
|
+
"raw",
|
|
129
|
+
enc.encode(password),
|
|
130
|
+
{ name: "PBKDF2" },
|
|
131
|
+
false,
|
|
132
|
+
["deriveBits", "deriveKey"]
|
|
133
|
+
);
|
|
134
|
+
const hashBuffer = await crypto.subtle.deriveBits(
|
|
135
|
+
{
|
|
136
|
+
name: "PBKDF2",
|
|
137
|
+
salt,
|
|
138
|
+
iterations,
|
|
139
|
+
hash: "SHA-256"
|
|
140
|
+
},
|
|
141
|
+
keyMaterial,
|
|
142
|
+
256
|
|
143
|
+
);
|
|
144
|
+
const newHash = new Uint8Array(hashBuffer);
|
|
145
|
+
if (newHash.length !== originalHash.length) return false;
|
|
146
|
+
let result = 0;
|
|
147
|
+
for (let i = 0; i < newHash.length; i++) {
|
|
148
|
+
result |= newHash[i] ^ originalHash[i];
|
|
149
|
+
}
|
|
150
|
+
return result === 0;
|
|
151
|
+
}
|
|
152
|
+
|
|
92
153
|
// src/backend/index.ts
|
|
93
154
|
var createAuth = (config) => {
|
|
94
155
|
let db;
|
|
@@ -98,7 +159,7 @@ var createAuth = (config) => {
|
|
|
98
159
|
} else {
|
|
99
160
|
db = config.database;
|
|
100
161
|
}
|
|
101
|
-
const { database, secret, baseUrl, provider: _, ...rest } = config;
|
|
162
|
+
const { database, secret, baseUrl, provider: _, useCloudflareNativeHashing = true, ...rest } = config;
|
|
102
163
|
let adapterOptions = {
|
|
103
164
|
provider,
|
|
104
165
|
schema: {
|
|
@@ -111,11 +172,23 @@ var createAuth = (config) => {
|
|
|
111
172
|
invitation: invitations
|
|
112
173
|
}
|
|
113
174
|
};
|
|
175
|
+
const emailConfig = rest.emailAndPassword || { enabled: true };
|
|
176
|
+
const { emailAndPassword, ...otherOptions } = rest;
|
|
177
|
+
const emailPasswordOptions = {
|
|
178
|
+
...emailConfig
|
|
179
|
+
};
|
|
180
|
+
if (useCloudflareNativeHashing) {
|
|
181
|
+
emailPasswordOptions.password = {
|
|
182
|
+
hash: hashPassword,
|
|
183
|
+
verify: verifyPassword
|
|
184
|
+
};
|
|
185
|
+
}
|
|
114
186
|
const auth = betterAuth({
|
|
115
187
|
database: drizzleAdapter(db, adapterOptions),
|
|
116
188
|
secret,
|
|
117
189
|
baseURL: baseUrl,
|
|
118
|
-
|
|
190
|
+
emailAndPassword: emailPasswordOptions,
|
|
191
|
+
...otherOptions
|
|
119
192
|
});
|
|
120
193
|
return auth;
|
|
121
194
|
};
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentgrowth/content-auth",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Better Auth wrapper with UI components for Cloudflare Workers & Pages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"author": "Content Growth",
|
|
51
51
|
"license": "MIT",
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"react": "
|
|
54
|
-
"react-dom": "
|
|
53
|
+
"react": ">=18.2.0",
|
|
54
|
+
"react-dom": ">=18.2.0"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
57
|
"better-auth": "^1.4.9",
|