better-auth 0.0.8-beta.2 → 0.0.8-beta.21
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/access.d.ts +3 -4
- package/dist/access.js +3 -13
- package/dist/access.js.map +1 -1
- package/dist/cli.d.ts +1 -2
- package/dist/cli.js +36 -44
- package/dist/cli.js.map +1 -1
- package/dist/client/plugins.d.ts +97 -2407
- package/dist/client/plugins.js +143 -203
- package/dist/client/plugins.js.map +1 -1
- package/dist/client.d.ts +159 -1213
- package/dist/client.js +125 -527
- package/dist/client.js.map +1 -1
- package/dist/{helper-B5_2Vzba.d.ts → helper-D8dhRz72.d.ts} +1 -4
- package/dist/{index-Dg4eEXZW.d.ts → index-B9jOjqnF.d.ts} +1 -1
- package/dist/{schema-BOszzrbQ.d.ts → index-CcxejJTH.d.ts} +172 -142
- package/dist/{client-CaF9eUcv.d.ts → index-Dwhjsk4l.d.ts} +2014 -1971
- package/dist/index.d.ts +1124 -6
- package/dist/index.js +737 -707
- package/dist/index.js.map +1 -1
- package/dist/internal-adapter-CVKQ4XR9.d.ts +637 -0
- package/dist/next-js.d.ts +17 -7
- package/dist/next-js.js +20 -3
- package/dist/next-js.js.map +1 -1
- package/dist/plugins.d.ts +12 -883
- package/dist/plugins.js +743 -679
- package/dist/plugins.js.map +1 -1
- package/dist/react.d.ts +312 -12
- package/dist/react.js +138 -148
- package/dist/react.js.map +1 -1
- package/dist/social.d.ts +2 -2
- package/dist/social.js +179 -151
- package/dist/social.js.map +1 -1
- package/dist/solid-start.d.ts +7 -6
- package/dist/solid-start.js +3 -3
- package/dist/solid-start.js.map +1 -1
- package/dist/solid.d.ts +91 -2713
- package/dist/solid.js +130 -139
- package/dist/solid.js.map +1 -1
- package/dist/{statement-COylZd3J.d.ts → statement-D6SPoYOh.d.ts} +7 -7
- package/dist/svelte-kit.d.ts +6 -5
- package/dist/svelte-kit.js +10 -9
- package/dist/svelte-kit.js.map +1 -1
- package/dist/svelte.d.ts +89 -2713
- package/dist/svelte.js +124 -138
- package/dist/svelte.js.map +1 -1
- package/dist/types-D4WrjKeJ.d.ts +81 -0
- package/dist/types.d.ts +31 -5
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -1
- package/dist/vue.d.ts +313 -12
- package/dist/vue.js +131 -145
- package/dist/vue.js.map +1 -1
- package/package.json +8 -3
- package/dist/index-CGeV0d2g.d.ts +0 -1498
- package/dist/preact.d.ts +0 -8
- package/dist/preact.js +0 -291
- package/dist/preact.js.map +0 -1
- package/dist/type-tYx_kmry.d.ts +0 -5724
package/dist/plugins.js
CHANGED
|
@@ -1,42 +1,45 @@
|
|
|
1
|
+
import { createMiddleware, createMiddlewareCreator, createEndpointCreator, APIError, serializeSigned } from 'better-call';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { generateCodeVerifier, generateState as generateState$1 } from 'oslo/oauth2';
|
|
4
|
+
import { Discord, Facebook, GitHub, Google, Spotify, Twitch, Twitter } from 'arctic';
|
|
5
|
+
import { createJWT, validateJWT, parseJWT } from 'oslo/jwt';
|
|
6
|
+
import { betterFetch } from '@better-fetch/fetch';
|
|
7
|
+
import { createOAuth2Request, sendTokenRequest } from 'arctic/dist/request';
|
|
8
|
+
import { createConsola } from 'consola';
|
|
9
|
+
import { TimeSpan } from 'oslo';
|
|
10
|
+
import { generateRandomString, alphabet, generateRandomInteger } from 'oslo/crypto';
|
|
11
|
+
import { xchacha20poly1305 } from '@noble/ciphers/chacha';
|
|
12
|
+
import { utf8ToBytes, bytesToHex, hexToBytes } from '@noble/ciphers/utils';
|
|
13
|
+
import { managedNonce } from '@noble/ciphers/webcrypto';
|
|
14
|
+
import { sha256 } from '@noble/hashes/sha256';
|
|
15
|
+
import { generateHOTP, TOTPController, createTOTPKeyURI } from 'oslo/otp';
|
|
16
|
+
import { generateRegistrationOptions, generateAuthenticationOptions, verifyRegistrationResponse, verifyAuthenticationResponse } from '@simplewebauthn/server';
|
|
17
|
+
import { startAuthentication, startRegistration, WebAuthnError } from '@simplewebauthn/browser';
|
|
18
|
+
|
|
1
19
|
var __defProp = Object.defineProperty;
|
|
2
20
|
var __export = (target, all) => {
|
|
3
21
|
for (var name in all)
|
|
4
22
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
23
|
};
|
|
6
|
-
|
|
7
|
-
// src/plugins/organization/organization.ts
|
|
8
|
-
import { APIError as APIError5 } from "better-call";
|
|
9
|
-
import {
|
|
10
|
-
z as z11
|
|
11
|
-
} from "zod";
|
|
12
|
-
|
|
13
|
-
// src/api/call.ts
|
|
14
|
-
import {
|
|
15
|
-
createEndpointCreator,
|
|
16
|
-
createMiddleware,
|
|
17
|
-
createMiddlewareCreator
|
|
18
|
-
} from "better-call";
|
|
19
24
|
var optionsMiddleware = createMiddleware(async () => {
|
|
20
25
|
return {};
|
|
21
26
|
});
|
|
22
27
|
var createAuthMiddleware = createMiddlewareCreator({
|
|
23
|
-
use: [
|
|
28
|
+
use: [
|
|
29
|
+
optionsMiddleware,
|
|
30
|
+
/**
|
|
31
|
+
* This of for hooks. to tell ts there will a
|
|
32
|
+
* return response object
|
|
33
|
+
*/
|
|
34
|
+
createMiddleware(async () => {
|
|
35
|
+
return {};
|
|
36
|
+
})
|
|
37
|
+
]
|
|
24
38
|
});
|
|
25
39
|
var createAuthEndpoint = createEndpointCreator({
|
|
26
40
|
use: [optionsMiddleware]
|
|
27
41
|
});
|
|
28
42
|
|
|
29
|
-
// src/api/routes/sign-in.ts
|
|
30
|
-
import { APIError } from "better-call";
|
|
31
|
-
import { generateCodeVerifier } from "oslo/oauth2";
|
|
32
|
-
import { Argon2id } from "oslo/password";
|
|
33
|
-
import { z } from "zod";
|
|
34
|
-
|
|
35
|
-
// src/social-providers/apple.ts
|
|
36
|
-
import "arctic";
|
|
37
|
-
import { parseJWT } from "oslo/jwt";
|
|
38
|
-
import { betterFetch } from "@better-fetch/fetch";
|
|
39
|
-
|
|
40
43
|
// src/error/better-auth-error.ts
|
|
41
44
|
var BetterAuthError = class extends Error {
|
|
42
45
|
constructor(message) {
|
|
@@ -57,41 +60,44 @@ function checkHasPath(url) {
|
|
|
57
60
|
function withPath(url, path = "/api/auth") {
|
|
58
61
|
const hasPath = checkHasPath(url);
|
|
59
62
|
if (hasPath) {
|
|
60
|
-
return
|
|
61
|
-
baseURL: new URL(url).origin,
|
|
62
|
-
withPath: url
|
|
63
|
-
};
|
|
63
|
+
return url;
|
|
64
64
|
}
|
|
65
65
|
path = path.startsWith("/") ? path : `/${path}`;
|
|
66
|
-
return {
|
|
67
|
-
baseURL: url,
|
|
68
|
-
withPath: `${url}${path}`
|
|
69
|
-
};
|
|
66
|
+
return `${url}${path}`;
|
|
70
67
|
}
|
|
71
68
|
function getBaseURL(url, path) {
|
|
72
|
-
if (url) {
|
|
73
|
-
return withPath(url, path);
|
|
74
|
-
}
|
|
75
69
|
const env = typeof process !== "undefined" ? process.env : {};
|
|
76
|
-
const fromEnv = env.BETTER_AUTH_URL || env.
|
|
70
|
+
const fromEnv = env.BETTER_AUTH_URL || env.NEXT_PUBLIC_BETTER_AUTH_URL || env.PUBLIC_BETTER_AUTH_URL || env.NUXT_PUBLIC_BETTER_AUTH_URL || env.NUXT_PUBLIC_AUTH_URL;
|
|
77
71
|
if (fromEnv) {
|
|
78
72
|
return withPath(fromEnv, path);
|
|
79
73
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return {
|
|
83
|
-
baseURL: "http://localhost:3000",
|
|
84
|
-
withPath: "http://localhost:3000/api/auth"
|
|
85
|
-
};
|
|
74
|
+
if (typeof window !== "undefined") {
|
|
75
|
+
return withPath(window.location.origin, path);
|
|
86
76
|
}
|
|
87
|
-
|
|
88
|
-
"Could not infer baseURL from environment variables"
|
|
89
|
-
);
|
|
77
|
+
return void 0;
|
|
90
78
|
}
|
|
91
79
|
|
|
92
80
|
// src/social-providers/utils.ts
|
|
93
81
|
function getRedirectURI(providerId, redirectURI) {
|
|
94
|
-
return redirectURI || `${getBaseURL()}/
|
|
82
|
+
return redirectURI || `${getBaseURL()}/callback/${providerId}`;
|
|
83
|
+
}
|
|
84
|
+
async function validateAuthorizationCode({
|
|
85
|
+
code,
|
|
86
|
+
codeVerifier,
|
|
87
|
+
redirectURI,
|
|
88
|
+
options,
|
|
89
|
+
tokenEndpoint
|
|
90
|
+
}) {
|
|
91
|
+
const body = new URLSearchParams();
|
|
92
|
+
body.set("grant_type", "authorization_code");
|
|
93
|
+
body.set("code", code);
|
|
94
|
+
body.set("code_verifier", codeVerifier || "");
|
|
95
|
+
body.set("redirect_uri", redirectURI);
|
|
96
|
+
body.set("client_id", options.clientId);
|
|
97
|
+
body.set("client_secret", options.clientSecret);
|
|
98
|
+
const request = createOAuth2Request(tokenEndpoint, body);
|
|
99
|
+
const tokens = await sendTokenRequest(request);
|
|
100
|
+
return tokens;
|
|
95
101
|
}
|
|
96
102
|
|
|
97
103
|
// src/social-providers/apple.ts
|
|
@@ -148,19 +154,11 @@ var apple = ({
|
|
|
148
154
|
}
|
|
149
155
|
};
|
|
150
156
|
};
|
|
151
|
-
|
|
152
|
-
// src/social-providers/discord.ts
|
|
153
|
-
import { betterFetch as betterFetch2 } from "@better-fetch/fetch";
|
|
154
|
-
import { Discord } from "arctic";
|
|
155
|
-
var discord = ({
|
|
156
|
-
clientId,
|
|
157
|
-
clientSecret,
|
|
158
|
-
redirectURI
|
|
159
|
-
}) => {
|
|
157
|
+
var discord = (options) => {
|
|
160
158
|
const discordArctic = new Discord(
|
|
161
|
-
clientId,
|
|
162
|
-
clientSecret,
|
|
163
|
-
getRedirectURI("discord", redirectURI)
|
|
159
|
+
options.clientId,
|
|
160
|
+
options.clientSecret,
|
|
161
|
+
getRedirectURI("discord", options.redirectURI)
|
|
164
162
|
);
|
|
165
163
|
return {
|
|
166
164
|
id: "discord",
|
|
@@ -169,14 +167,22 @@ var discord = ({
|
|
|
169
167
|
const _scope = scopes || ["email"];
|
|
170
168
|
return discordArctic.createAuthorizationURL(state, _scope);
|
|
171
169
|
},
|
|
172
|
-
validateAuthorizationCode:
|
|
170
|
+
validateAuthorizationCode: async (code, codeVerifier, redirectURI) => {
|
|
171
|
+
return validateAuthorizationCode({
|
|
172
|
+
code,
|
|
173
|
+
codeVerifier,
|
|
174
|
+
redirectURI: redirectURI || getRedirectURI("discord", options.redirectURI),
|
|
175
|
+
options,
|
|
176
|
+
tokenEndpoint: "https://discord.com/api/oauth2/token"
|
|
177
|
+
});
|
|
178
|
+
},
|
|
173
179
|
async getUserInfo(token) {
|
|
174
|
-
const { data: profile, error } = await
|
|
180
|
+
const { data: profile, error } = await betterFetch(
|
|
175
181
|
"https://discord.com/api/users/@me",
|
|
176
182
|
{
|
|
177
183
|
auth: {
|
|
178
184
|
type: "Bearer",
|
|
179
|
-
token: token.accessToken
|
|
185
|
+
token: token.accessToken()
|
|
180
186
|
}
|
|
181
187
|
}
|
|
182
188
|
);
|
|
@@ -195,19 +201,11 @@ var discord = ({
|
|
|
195
201
|
}
|
|
196
202
|
};
|
|
197
203
|
};
|
|
198
|
-
|
|
199
|
-
// src/social-providers/facebook.ts
|
|
200
|
-
import { betterFetch as betterFetch3 } from "@better-fetch/fetch";
|
|
201
|
-
import { Facebook } from "arctic";
|
|
202
|
-
var facebook = ({
|
|
203
|
-
clientId,
|
|
204
|
-
clientSecret,
|
|
205
|
-
redirectURI
|
|
206
|
-
}) => {
|
|
204
|
+
var facebook = (options) => {
|
|
207
205
|
const facebookArctic = new Facebook(
|
|
208
|
-
clientId,
|
|
209
|
-
clientSecret,
|
|
210
|
-
getRedirectURI("facebook", redirectURI)
|
|
206
|
+
options.clientId,
|
|
207
|
+
options.clientSecret,
|
|
208
|
+
getRedirectURI("facebook", options.redirectURI)
|
|
211
209
|
);
|
|
212
210
|
return {
|
|
213
211
|
id: "facebook",
|
|
@@ -216,14 +214,22 @@ var facebook = ({
|
|
|
216
214
|
const _scopes = scopes || ["email", "public_profile"];
|
|
217
215
|
return facebookArctic.createAuthorizationURL(state, _scopes);
|
|
218
216
|
},
|
|
219
|
-
validateAuthorizationCode:
|
|
217
|
+
validateAuthorizationCode: async (code, codeVerifier, redirectURI) => {
|
|
218
|
+
return validateAuthorizationCode({
|
|
219
|
+
code,
|
|
220
|
+
codeVerifier,
|
|
221
|
+
redirectURI: redirectURI || getRedirectURI("facebook", options.redirectURI),
|
|
222
|
+
options,
|
|
223
|
+
tokenEndpoint: "https://graph.facebook.com/v16.0/oauth/access_token"
|
|
224
|
+
});
|
|
225
|
+
},
|
|
220
226
|
async getUserInfo(token) {
|
|
221
|
-
const { data: profile, error } = await
|
|
227
|
+
const { data: profile, error } = await betterFetch(
|
|
222
228
|
"https://graph.facebook.com/me",
|
|
223
229
|
{
|
|
224
230
|
auth: {
|
|
225
231
|
type: "Bearer",
|
|
226
|
-
token: token.accessToken
|
|
232
|
+
token: token.accessToken()
|
|
227
233
|
}
|
|
228
234
|
}
|
|
229
235
|
);
|
|
@@ -242,10 +248,6 @@ var facebook = ({
|
|
|
242
248
|
}
|
|
243
249
|
};
|
|
244
250
|
};
|
|
245
|
-
|
|
246
|
-
// src/social-providers/github.ts
|
|
247
|
-
import { betterFetch as betterFetch4 } from "@better-fetch/fetch";
|
|
248
|
-
import { GitHub } from "arctic";
|
|
249
251
|
var github = ({
|
|
250
252
|
clientId,
|
|
251
253
|
clientSecret,
|
|
@@ -263,14 +265,17 @@ var github = ({
|
|
|
263
265
|
const _scopes = scopes || ["user:email"];
|
|
264
266
|
return githubArctic.createAuthorizationURL(state, _scopes);
|
|
265
267
|
},
|
|
266
|
-
validateAuthorizationCode:
|
|
268
|
+
validateAuthorizationCode: async (state) => {
|
|
269
|
+
return await githubArctic.validateAuthorizationCode(state);
|
|
270
|
+
},
|
|
267
271
|
async getUserInfo(token) {
|
|
268
|
-
|
|
272
|
+
console.log(`Bearer ${token.accessToken()}`);
|
|
273
|
+
const { data: profile, error } = await betterFetch(
|
|
269
274
|
"https://api.github.com/user",
|
|
270
275
|
{
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
276
|
+
auth: {
|
|
277
|
+
type: "Bearer",
|
|
278
|
+
token: token.accessToken()
|
|
274
279
|
}
|
|
275
280
|
}
|
|
276
281
|
);
|
|
@@ -279,10 +284,10 @@ var github = ({
|
|
|
279
284
|
}
|
|
280
285
|
let emailVerified = false;
|
|
281
286
|
if (!profile.email) {
|
|
282
|
-
const { data, error: error2 } = await
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
287
|
+
const { data, error: error2 } = await betterFetch("https://api.github.com/user/emails", {
|
|
288
|
+
auth: {
|
|
289
|
+
type: "Bearer",
|
|
290
|
+
token: token.accessToken()
|
|
286
291
|
}
|
|
287
292
|
});
|
|
288
293
|
if (!error2) {
|
|
@@ -305,41 +310,81 @@ var github = ({
|
|
|
305
310
|
}
|
|
306
311
|
};
|
|
307
312
|
};
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
}
|
|
313
|
+
var consola = createConsola({
|
|
314
|
+
formatOptions: {
|
|
315
|
+
date: false,
|
|
316
|
+
colors: true,
|
|
317
|
+
compact: true
|
|
318
|
+
},
|
|
319
|
+
defaults: {
|
|
320
|
+
tag: "Better Auth"
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
var createLogger = (options) => {
|
|
324
|
+
return {
|
|
325
|
+
log: (...args) => {
|
|
326
|
+
consola.log("", ...args);
|
|
327
|
+
},
|
|
328
|
+
error: (...args) => {
|
|
329
|
+
consola.error("", ...args);
|
|
330
|
+
},
|
|
331
|
+
warn: (...args) => {
|
|
332
|
+
consola.warn("", ...args);
|
|
333
|
+
},
|
|
334
|
+
info: (...args) => {
|
|
335
|
+
consola.info("", ...args);
|
|
336
|
+
},
|
|
337
|
+
debug: (...args) => {
|
|
338
|
+
consola.debug("", ...args);
|
|
339
|
+
},
|
|
340
|
+
box: (...args) => {
|
|
341
|
+
consola.box("", ...args);
|
|
342
|
+
},
|
|
343
|
+
success: (...args) => {
|
|
344
|
+
consola.success("", ...args);
|
|
345
|
+
},
|
|
346
|
+
break: (...args) => {
|
|
347
|
+
console.log("\n");
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
};
|
|
351
|
+
var logger = createLogger();
|
|
352
|
+
var google = (options) => {
|
|
317
353
|
const googleArctic = new Google(
|
|
318
|
-
clientId,
|
|
319
|
-
clientSecret,
|
|
320
|
-
getRedirectURI("google", redirectURI)
|
|
354
|
+
options.clientId,
|
|
355
|
+
options.clientSecret,
|
|
356
|
+
getRedirectURI("google", options.redirectURI)
|
|
321
357
|
);
|
|
322
358
|
return {
|
|
323
359
|
id: "google",
|
|
324
360
|
name: "Google",
|
|
325
|
-
createAuthorizationURL({ state, scopes, codeVerifier }) {
|
|
361
|
+
createAuthorizationURL({ state, scopes, codeVerifier, redirectURI }) {
|
|
362
|
+
if (!options.clientId || !options.clientSecret) {
|
|
363
|
+
logger.error(
|
|
364
|
+
"clientId and clientSecret is required for Google. Make sure to you have provided them in the options"
|
|
365
|
+
);
|
|
366
|
+
throw new BetterAuthError("clientId is required for Google");
|
|
367
|
+
}
|
|
326
368
|
if (!codeVerifier) {
|
|
327
369
|
throw new BetterAuthError("codeVerifier is required for Google");
|
|
328
370
|
}
|
|
329
371
|
const _scopes = scopes || ["email", "profile"];
|
|
330
372
|
return googleArctic.createAuthorizationURL(state, codeVerifier, _scopes);
|
|
331
373
|
},
|
|
332
|
-
validateAuthorizationCode: async (code, codeVerifier) => {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
374
|
+
validateAuthorizationCode: async (code, codeVerifier, redirectURI) => {
|
|
375
|
+
return validateAuthorizationCode({
|
|
376
|
+
code,
|
|
377
|
+
codeVerifier,
|
|
378
|
+
redirectURI: redirectURI || getRedirectURI("google", options.redirectURI),
|
|
379
|
+
options,
|
|
380
|
+
tokenEndpoint: "https://oauth2.googleapis.com/token"
|
|
381
|
+
});
|
|
337
382
|
},
|
|
338
383
|
async getUserInfo(token) {
|
|
339
384
|
if (!token.idToken) {
|
|
340
385
|
return null;
|
|
341
386
|
}
|
|
342
|
-
const user =
|
|
387
|
+
const user = parseJWT(token.idToken())?.payload;
|
|
343
388
|
return {
|
|
344
389
|
user: {
|
|
345
390
|
id: user.sub,
|
|
@@ -353,19 +398,11 @@ var google = ({
|
|
|
353
398
|
}
|
|
354
399
|
};
|
|
355
400
|
};
|
|
356
|
-
|
|
357
|
-
// src/social-providers/spotify.ts
|
|
358
|
-
import { betterFetch as betterFetch5 } from "@better-fetch/fetch";
|
|
359
|
-
import { Spotify } from "arctic";
|
|
360
|
-
var spotify = ({
|
|
361
|
-
clientId,
|
|
362
|
-
clientSecret,
|
|
363
|
-
redirectURI
|
|
364
|
-
}) => {
|
|
401
|
+
var spotify = (options) => {
|
|
365
402
|
const spotifyArctic = new Spotify(
|
|
366
|
-
clientId,
|
|
367
|
-
clientSecret,
|
|
368
|
-
getRedirectURI("spotify", redirectURI)
|
|
403
|
+
options.clientId,
|
|
404
|
+
options.clientSecret,
|
|
405
|
+
getRedirectURI("spotify", options.redirectURI)
|
|
369
406
|
);
|
|
370
407
|
return {
|
|
371
408
|
id: "spotify",
|
|
@@ -374,14 +411,22 @@ var spotify = ({
|
|
|
374
411
|
const _scopes = scopes || ["user-read-email"];
|
|
375
412
|
return spotifyArctic.createAuthorizationURL(state, _scopes);
|
|
376
413
|
},
|
|
377
|
-
validateAuthorizationCode:
|
|
414
|
+
validateAuthorizationCode: async (code, codeVerifier, redirectURI) => {
|
|
415
|
+
return validateAuthorizationCode({
|
|
416
|
+
code,
|
|
417
|
+
codeVerifier,
|
|
418
|
+
redirectURI: redirectURI || getRedirectURI("spotify", options.redirectURI),
|
|
419
|
+
options,
|
|
420
|
+
tokenEndpoint: "https://accounts.spotify.com/api/token"
|
|
421
|
+
});
|
|
422
|
+
},
|
|
378
423
|
async getUserInfo(token) {
|
|
379
|
-
const { data: profile, error } = await
|
|
424
|
+
const { data: profile, error } = await betterFetch(
|
|
380
425
|
"https://api.spotify.com/v1/me",
|
|
381
426
|
{
|
|
382
427
|
method: "GET",
|
|
383
428
|
headers: {
|
|
384
|
-
Authorization: `Bearer ${token.accessToken}`
|
|
429
|
+
Authorization: `Bearer ${token.accessToken()}`
|
|
385
430
|
}
|
|
386
431
|
}
|
|
387
432
|
);
|
|
@@ -401,19 +446,11 @@ var spotify = ({
|
|
|
401
446
|
}
|
|
402
447
|
};
|
|
403
448
|
};
|
|
404
|
-
|
|
405
|
-
// src/social-providers/twitch.ts
|
|
406
|
-
import { betterFetch as betterFetch6 } from "@better-fetch/fetch";
|
|
407
|
-
import { Twitch } from "arctic";
|
|
408
|
-
var twitch = ({
|
|
409
|
-
clientId,
|
|
410
|
-
clientSecret,
|
|
411
|
-
redirectURI
|
|
412
|
-
}) => {
|
|
449
|
+
var twitch = (options) => {
|
|
413
450
|
const twitchArctic = new Twitch(
|
|
414
|
-
clientId,
|
|
415
|
-
clientSecret,
|
|
416
|
-
getRedirectURI("twitch", redirectURI)
|
|
451
|
+
options.clientId,
|
|
452
|
+
options.clientSecret,
|
|
453
|
+
getRedirectURI("twitch", options.redirectURI)
|
|
417
454
|
);
|
|
418
455
|
return {
|
|
419
456
|
id: "twitch",
|
|
@@ -422,14 +459,22 @@ var twitch = ({
|
|
|
422
459
|
const _scopes = scopes || ["activity:write", "read"];
|
|
423
460
|
return twitchArctic.createAuthorizationURL(state, _scopes);
|
|
424
461
|
},
|
|
425
|
-
validateAuthorizationCode:
|
|
462
|
+
validateAuthorizationCode: async (code, codeVerifier, redirectURI) => {
|
|
463
|
+
return validateAuthorizationCode({
|
|
464
|
+
code,
|
|
465
|
+
codeVerifier,
|
|
466
|
+
redirectURI: redirectURI || getRedirectURI("twitch", options.redirectURI),
|
|
467
|
+
options,
|
|
468
|
+
tokenEndpoint: "https://id.twitch.tv/oauth2/token"
|
|
469
|
+
});
|
|
470
|
+
},
|
|
426
471
|
async getUserInfo(token) {
|
|
427
|
-
const { data: profile, error } = await
|
|
472
|
+
const { data: profile, error } = await betterFetch(
|
|
428
473
|
"https://api.twitch.tv/helix/users",
|
|
429
474
|
{
|
|
430
475
|
method: "GET",
|
|
431
476
|
headers: {
|
|
432
|
-
Authorization: `Bearer ${token.accessToken}`
|
|
477
|
+
Authorization: `Bearer ${token.accessToken()}`
|
|
433
478
|
}
|
|
434
479
|
}
|
|
435
480
|
);
|
|
@@ -449,19 +494,11 @@ var twitch = ({
|
|
|
449
494
|
}
|
|
450
495
|
};
|
|
451
496
|
};
|
|
452
|
-
|
|
453
|
-
// src/social-providers/twitter.ts
|
|
454
|
-
import { betterFetch as betterFetch7 } from "@better-fetch/fetch";
|
|
455
|
-
import { Twitter } from "arctic";
|
|
456
|
-
var twitter = ({
|
|
457
|
-
clientId,
|
|
458
|
-
clientSecret,
|
|
459
|
-
redirectURI
|
|
460
|
-
}) => {
|
|
497
|
+
var twitter = (options) => {
|
|
461
498
|
const twitterArctic = new Twitter(
|
|
462
|
-
clientId,
|
|
463
|
-
clientSecret,
|
|
464
|
-
getRedirectURI("twitter", redirectURI)
|
|
499
|
+
options.clientId,
|
|
500
|
+
options.clientSecret,
|
|
501
|
+
getRedirectURI("twitter", options.redirectURI)
|
|
465
502
|
);
|
|
466
503
|
return {
|
|
467
504
|
id: "twitter",
|
|
@@ -474,19 +511,22 @@ var twitter = ({
|
|
|
474
511
|
_scopes
|
|
475
512
|
);
|
|
476
513
|
},
|
|
477
|
-
validateAuthorizationCode: async (code, codeVerifier) => {
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
514
|
+
validateAuthorizationCode: async (code, codeVerifier, redirectURI) => {
|
|
515
|
+
return validateAuthorizationCode({
|
|
516
|
+
code,
|
|
517
|
+
codeVerifier,
|
|
518
|
+
redirectURI: redirectURI || getRedirectURI("twitch", options.redirectURI),
|
|
519
|
+
options,
|
|
520
|
+
tokenEndpoint: "https://id.twitch.tv/oauth2/token"
|
|
521
|
+
});
|
|
482
522
|
},
|
|
483
523
|
async getUserInfo(token) {
|
|
484
|
-
const { data: profile, error } = await
|
|
524
|
+
const { data: profile, error } = await betterFetch(
|
|
485
525
|
"https://api.x.com/2/users/me?user.fields=profile_image_url",
|
|
486
526
|
{
|
|
487
527
|
method: "GET",
|
|
488
528
|
headers: {
|
|
489
|
-
Authorization: `Bearer ${token.accessToken}`
|
|
529
|
+
Authorization: `Bearer ${token.accessToken()}`
|
|
490
530
|
}
|
|
491
531
|
}
|
|
492
532
|
);
|
|
@@ -510,9 +550,6 @@ var twitter = ({
|
|
|
510
550
|
};
|
|
511
551
|
};
|
|
512
552
|
|
|
513
|
-
// src/types/provider.ts
|
|
514
|
-
import "arctic";
|
|
515
|
-
|
|
516
553
|
// src/social-providers/index.ts
|
|
517
554
|
var oAuthProviders = {
|
|
518
555
|
apple,
|
|
@@ -525,17 +562,61 @@ var oAuthProviders = {
|
|
|
525
562
|
twitter
|
|
526
563
|
};
|
|
527
564
|
var oAuthProviderList = Object.keys(oAuthProviders);
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
565
|
+
function generateState(callbackURL, currentURL, dontRememberMe) {
|
|
566
|
+
const code = generateState$1();
|
|
567
|
+
const state = JSON.stringify({
|
|
568
|
+
code,
|
|
569
|
+
callbackURL,
|
|
570
|
+
currentURL,
|
|
571
|
+
dontRememberMe
|
|
572
|
+
});
|
|
534
573
|
return { state, code };
|
|
535
574
|
}
|
|
536
575
|
function parseState(state) {
|
|
537
|
-
const
|
|
538
|
-
|
|
576
|
+
const data = z.object({
|
|
577
|
+
code: z.string(),
|
|
578
|
+
callbackURL: z.string().optional(),
|
|
579
|
+
currentURL: z.string().optional(),
|
|
580
|
+
dontRememberMe: z.boolean().optional()
|
|
581
|
+
}).safeParse(JSON.parse(state));
|
|
582
|
+
return data;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// src/utils/date.ts
|
|
586
|
+
var getDate = (span, isSeconds = false) => {
|
|
587
|
+
const date = /* @__PURE__ */ new Date();
|
|
588
|
+
return new Date(date.getTime() + (isSeconds ? span * 1e3 : span));
|
|
589
|
+
};
|
|
590
|
+
async function setSessionCookie(ctx, sessionToken, dontRememberMe, overrides) {
|
|
591
|
+
await ctx.setSignedCookie(
|
|
592
|
+
ctx.context.authCookies.sessionToken.name,
|
|
593
|
+
sessionToken,
|
|
594
|
+
ctx.context.secret,
|
|
595
|
+
dontRememberMe ? {
|
|
596
|
+
...ctx.context.authCookies.sessionToken.options,
|
|
597
|
+
maxAge: void 0,
|
|
598
|
+
...overrides
|
|
599
|
+
} : {
|
|
600
|
+
...ctx.context.authCookies.sessionToken.options,
|
|
601
|
+
...overrides
|
|
602
|
+
}
|
|
603
|
+
);
|
|
604
|
+
if (dontRememberMe) {
|
|
605
|
+
await ctx.setSignedCookie(
|
|
606
|
+
ctx.context.authCookies.dontRememberToken.name,
|
|
607
|
+
"true",
|
|
608
|
+
ctx.context.secret,
|
|
609
|
+
ctx.context.authCookies.dontRememberToken.options
|
|
610
|
+
);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
function deleteSessionCookie(ctx) {
|
|
614
|
+
ctx.setCookie(ctx.context.authCookies.sessionToken.name, "", {
|
|
615
|
+
maxAge: 0
|
|
616
|
+
});
|
|
617
|
+
ctx.setCookie(ctx.context.authCookies.dontRememberToken.name, "", {
|
|
618
|
+
maxAge: 0
|
|
619
|
+
});
|
|
539
620
|
}
|
|
540
621
|
|
|
541
622
|
// src/api/routes/session.ts
|
|
@@ -546,45 +627,62 @@ var getSession = createAuthEndpoint(
|
|
|
546
627
|
requireHeaders: true
|
|
547
628
|
},
|
|
548
629
|
async (ctx) => {
|
|
549
|
-
|
|
550
|
-
ctx.
|
|
551
|
-
ctx.context.secret
|
|
552
|
-
);
|
|
553
|
-
if (!sessionCookieToken) {
|
|
554
|
-
return ctx.json(null, {
|
|
555
|
-
status: 401
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
const session = await ctx.context.internalAdapter.findSession(sessionCookieToken);
|
|
559
|
-
if (!session || session.session.expiresAt < /* @__PURE__ */ new Date()) {
|
|
560
|
-
ctx.setSignedCookie(
|
|
630
|
+
try {
|
|
631
|
+
const sessionCookieToken = await ctx.getSignedCookie(
|
|
561
632
|
ctx.context.authCookies.sessionToken.name,
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
633
|
+
ctx.context.secret
|
|
634
|
+
);
|
|
635
|
+
if (!sessionCookieToken) {
|
|
636
|
+
return ctx.json(null, {
|
|
637
|
+
status: 401
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
const session = await ctx.context.internalAdapter.findSession(sessionCookieToken);
|
|
641
|
+
if (!session || session.session.expiresAt < /* @__PURE__ */ new Date()) {
|
|
642
|
+
deleteSessionCookie(ctx);
|
|
643
|
+
if (session) {
|
|
644
|
+
await ctx.context.internalAdapter.deleteSession(session.session.id);
|
|
566
645
|
}
|
|
646
|
+
return ctx.json(null, {
|
|
647
|
+
status: 401
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
const dontRememberMe = await ctx.getSignedCookie(
|
|
651
|
+
ctx.context.authCookies.dontRememberToken.name,
|
|
652
|
+
ctx.context.secret
|
|
567
653
|
);
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
});
|
|
571
|
-
}
|
|
572
|
-
const updatedSession = await ctx.context.internalAdapter.updateSession(
|
|
573
|
-
session.session
|
|
574
|
-
);
|
|
575
|
-
await ctx.setSignedCookie(
|
|
576
|
-
ctx.context.authCookies.sessionToken.name,
|
|
577
|
-
updatedSession.id,
|
|
578
|
-
ctx.context.secret,
|
|
579
|
-
{
|
|
580
|
-
...ctx.context.authCookies.sessionToken.options,
|
|
581
|
-
maxAge: updatedSession.expiresAt.valueOf() - Date.now()
|
|
654
|
+
if (dontRememberMe) {
|
|
655
|
+
return ctx.json(session);
|
|
582
656
|
}
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
session
|
|
586
|
-
|
|
587
|
-
|
|
657
|
+
const expiresIn = ctx.context.session.expiresIn;
|
|
658
|
+
const updateAge = ctx.context.session.updateAge;
|
|
659
|
+
const sessionIsDueToBeUpdatedDate = session.session.expiresAt.valueOf() - expiresIn * 1e3 + updateAge * 1e3;
|
|
660
|
+
const shouldBeUpdated = sessionIsDueToBeUpdatedDate <= Date.now();
|
|
661
|
+
if (shouldBeUpdated) {
|
|
662
|
+
const updatedSession = await ctx.context.internalAdapter.updateSession(
|
|
663
|
+
session.session.id,
|
|
664
|
+
{
|
|
665
|
+
expiresAt: getDate(ctx.context.session.expiresIn, true)
|
|
666
|
+
}
|
|
667
|
+
);
|
|
668
|
+
if (!updatedSession) {
|
|
669
|
+
deleteSessionCookie(ctx);
|
|
670
|
+
return ctx.json(null, { status: 401 });
|
|
671
|
+
}
|
|
672
|
+
const maxAge = (updatedSession.expiresAt.valueOf() - Date.now()) / 1e3;
|
|
673
|
+
await setSessionCookie(ctx, updatedSession.id, false, {
|
|
674
|
+
maxAge
|
|
675
|
+
});
|
|
676
|
+
return ctx.json({
|
|
677
|
+
session: updatedSession,
|
|
678
|
+
user: session.user
|
|
679
|
+
});
|
|
680
|
+
}
|
|
681
|
+
return ctx.json(session);
|
|
682
|
+
} catch (error) {
|
|
683
|
+
ctx.context.logger.error(error);
|
|
684
|
+
return ctx.json(null, { status: 500 });
|
|
685
|
+
}
|
|
588
686
|
}
|
|
589
687
|
);
|
|
590
688
|
var getSessionFromCtx = async (ctx) => {
|
|
@@ -597,7 +695,7 @@ var getSessionFromCtx = async (ctx) => {
|
|
|
597
695
|
};
|
|
598
696
|
|
|
599
697
|
// src/api/routes/sign-in.ts
|
|
600
|
-
|
|
698
|
+
createAuthEndpoint(
|
|
601
699
|
"/sign-in/social",
|
|
602
700
|
{
|
|
603
701
|
method: "POST",
|
|
@@ -617,7 +715,11 @@ var signInOAuth = createAuthEndpoint(
|
|
|
617
715
|
/**
|
|
618
716
|
* OAuth2 provider to use`
|
|
619
717
|
*/
|
|
620
|
-
provider: z.enum(oAuthProviderList)
|
|
718
|
+
provider: z.enum(oAuthProviderList),
|
|
719
|
+
/**
|
|
720
|
+
* If this is true the session will only be valid for the current browser session
|
|
721
|
+
*/
|
|
722
|
+
dontRememberMe: z.boolean().default(false).optional()
|
|
621
723
|
})
|
|
622
724
|
},
|
|
623
725
|
async (c) => {
|
|
@@ -631,7 +733,9 @@ var signInOAuth = createAuthEndpoint(
|
|
|
631
733
|
provider: c.body.provider
|
|
632
734
|
}
|
|
633
735
|
);
|
|
634
|
-
throw new APIError("NOT_FOUND"
|
|
736
|
+
throw new APIError("NOT_FOUND", {
|
|
737
|
+
message: "Provider not found"
|
|
738
|
+
});
|
|
635
739
|
}
|
|
636
740
|
const cookie = c.context.authCookies;
|
|
637
741
|
const currentURL = c.query?.currentURL ? new URL(c.query?.currentURL) : null;
|
|
@@ -657,6 +761,10 @@ var signInOAuth = createAuthEndpoint(
|
|
|
657
761
|
state: state.state,
|
|
658
762
|
codeVerifier
|
|
659
763
|
});
|
|
764
|
+
url.searchParams.set(
|
|
765
|
+
"redirect_uri",
|
|
766
|
+
`${c.context.baseURL}/callback/${c.body.provider}`
|
|
767
|
+
);
|
|
660
768
|
return {
|
|
661
769
|
url: url.toString(),
|
|
662
770
|
state: state.state,
|
|
@@ -668,7 +776,7 @@ var signInOAuth = createAuthEndpoint(
|
|
|
668
776
|
}
|
|
669
777
|
}
|
|
670
778
|
);
|
|
671
|
-
|
|
779
|
+
createAuthEndpoint(
|
|
672
780
|
"/sign-in/email",
|
|
673
781
|
{
|
|
674
782
|
method: "POST",
|
|
@@ -692,18 +800,20 @@ var signInEmail = createAuthEndpoint(
|
|
|
692
800
|
}
|
|
693
801
|
const currentSession = await getSessionFromCtx(ctx);
|
|
694
802
|
if (currentSession) {
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
redirect: !!ctx.body.callbackURL,
|
|
699
|
-
url: ctx.body.callbackURL
|
|
700
|
-
});
|
|
803
|
+
await ctx.context.internalAdapter.deleteSession(
|
|
804
|
+
currentSession.session.id
|
|
805
|
+
);
|
|
701
806
|
}
|
|
702
807
|
const { email, password } = ctx.body;
|
|
703
|
-
const
|
|
808
|
+
const checkEmail = z.string().email().safeParse(email);
|
|
809
|
+
if (!checkEmail.success) {
|
|
810
|
+
throw new APIError("BAD_REQUEST", {
|
|
811
|
+
message: "Invalid email"
|
|
812
|
+
});
|
|
813
|
+
}
|
|
704
814
|
const user = await ctx.context.internalAdapter.findUserByEmail(email);
|
|
705
815
|
if (!user) {
|
|
706
|
-
await
|
|
816
|
+
await ctx.context.password.hash(password);
|
|
707
817
|
ctx.context.logger.error("User not found", { email });
|
|
708
818
|
throw new APIError("UNAUTHORIZED", {
|
|
709
819
|
message: "Invalid email or password"
|
|
@@ -725,7 +835,10 @@ var signInEmail = createAuthEndpoint(
|
|
|
725
835
|
message: "Unexpected error"
|
|
726
836
|
});
|
|
727
837
|
}
|
|
728
|
-
const validPassword = await
|
|
838
|
+
const validPassword = await ctx.context.password.verify(
|
|
839
|
+
currentPassword,
|
|
840
|
+
password
|
|
841
|
+
);
|
|
729
842
|
if (!validPassword) {
|
|
730
843
|
ctx.context.logger.error("Invalid password");
|
|
731
844
|
throw new APIError("UNAUTHORIZED", {
|
|
@@ -734,17 +847,10 @@ var signInEmail = createAuthEndpoint(
|
|
|
734
847
|
}
|
|
735
848
|
const session = await ctx.context.internalAdapter.createSession(
|
|
736
849
|
user.user.id,
|
|
737
|
-
ctx.request
|
|
738
|
-
|
|
739
|
-
await ctx.setSignedCookie(
|
|
740
|
-
ctx.context.authCookies.sessionToken.name,
|
|
741
|
-
session.id,
|
|
742
|
-
ctx.context.secret,
|
|
743
|
-
ctx.body.dontRememberMe ? {
|
|
744
|
-
...ctx.context.authCookies.sessionToken.options,
|
|
745
|
-
maxAge: void 0
|
|
746
|
-
} : ctx.context.authCookies.sessionToken.options
|
|
850
|
+
ctx.request,
|
|
851
|
+
ctx.body.dontRememberMe
|
|
747
852
|
);
|
|
853
|
+
await setSessionCookie(ctx, session.id, ctx.body.dontRememberMe);
|
|
748
854
|
return ctx.json({
|
|
749
855
|
user: user.user,
|
|
750
856
|
session,
|
|
@@ -753,65 +859,80 @@ var signInEmail = createAuthEndpoint(
|
|
|
753
859
|
});
|
|
754
860
|
}
|
|
755
861
|
);
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
accountId: z2.string(),
|
|
767
|
-
userId: z2.string(),
|
|
768
|
-
accessToken: z2.string().nullable().optional(),
|
|
769
|
-
refreshToken: z2.string().nullable().optional(),
|
|
770
|
-
idToken: z2.string().nullable().optional(),
|
|
771
|
-
accessTokenExpiresAt: z2.date().nullable().optional(),
|
|
772
|
-
refreshTokenExpiresAt: z2.date().nullable().optional(),
|
|
862
|
+
z.object({
|
|
863
|
+
id: z.string(),
|
|
864
|
+
providerId: z.string(),
|
|
865
|
+
accountId: z.string(),
|
|
866
|
+
userId: z.string(),
|
|
867
|
+
accessToken: z.string().nullable().optional(),
|
|
868
|
+
refreshToken: z.string().nullable().optional(),
|
|
869
|
+
idToken: z.string().nullable().optional(),
|
|
870
|
+
accessTokenExpiresAt: z.date().nullable().optional(),
|
|
871
|
+
refreshTokenExpiresAt: z.date().nullable().optional(),
|
|
773
872
|
/**
|
|
774
873
|
* Password is only stored in the credential provider
|
|
775
874
|
*/
|
|
776
|
-
password:
|
|
875
|
+
password: z.string().optional().nullable()
|
|
777
876
|
});
|
|
778
|
-
var userSchema =
|
|
779
|
-
id:
|
|
780
|
-
email:
|
|
781
|
-
emailVerified:
|
|
782
|
-
name:
|
|
783
|
-
image:
|
|
784
|
-
createdAt:
|
|
785
|
-
updatedAt:
|
|
877
|
+
var userSchema = z.object({
|
|
878
|
+
id: z.string(),
|
|
879
|
+
email: z.string().transform((val) => val.toLowerCase()),
|
|
880
|
+
emailVerified: z.boolean().default(false),
|
|
881
|
+
name: z.string(),
|
|
882
|
+
image: z.string().optional(),
|
|
883
|
+
createdAt: z.date().default(/* @__PURE__ */ new Date()),
|
|
884
|
+
updatedAt: z.date().default(/* @__PURE__ */ new Date())
|
|
786
885
|
});
|
|
787
|
-
|
|
788
|
-
id:
|
|
789
|
-
userId:
|
|
790
|
-
expiresAt:
|
|
791
|
-
ipAddress:
|
|
792
|
-
userAgent:
|
|
886
|
+
z.object({
|
|
887
|
+
id: z.string(),
|
|
888
|
+
userId: z.string(),
|
|
889
|
+
expiresAt: z.date(),
|
|
890
|
+
ipAddress: z.string().optional(),
|
|
891
|
+
userAgent: z.string().optional()
|
|
793
892
|
});
|
|
893
|
+
var generateId = () => {
|
|
894
|
+
return generateRandomString(36, alphabet("a-z", "0-9"));
|
|
895
|
+
};
|
|
794
896
|
|
|
795
897
|
// src/client/client-utils.ts
|
|
796
898
|
var HIDE_ON_CLIENT_METADATA = {
|
|
797
899
|
onClient: "hide"
|
|
798
900
|
};
|
|
799
901
|
|
|
800
|
-
// src/utils/
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
902
|
+
// src/utils/getAccount.ts
|
|
903
|
+
function getAccountTokens(tokens) {
|
|
904
|
+
const accessToken = tokens.accessToken();
|
|
905
|
+
let refreshToken = void 0;
|
|
906
|
+
try {
|
|
907
|
+
refreshToken = tokens.refreshToken();
|
|
908
|
+
} catch {
|
|
909
|
+
}
|
|
910
|
+
let accessTokenExpiresAt = void 0;
|
|
911
|
+
let refreshTokenExpiresAt = void 0;
|
|
912
|
+
try {
|
|
913
|
+
accessTokenExpiresAt = tokens.accessTokenExpiresAt();
|
|
914
|
+
} catch {
|
|
915
|
+
}
|
|
916
|
+
try {
|
|
917
|
+
refreshTokenExpiresAt = tokens.refreshTokenExpiresAt();
|
|
918
|
+
} catch {
|
|
919
|
+
}
|
|
920
|
+
return {
|
|
921
|
+
accessToken,
|
|
922
|
+
refreshToken,
|
|
923
|
+
accessTokenExpiresAt,
|
|
924
|
+
refreshTokenExpiresAt
|
|
925
|
+
};
|
|
926
|
+
}
|
|
805
927
|
|
|
806
928
|
// src/api/routes/callback.ts
|
|
807
|
-
|
|
929
|
+
createAuthEndpoint(
|
|
808
930
|
"/callback/:id",
|
|
809
931
|
{
|
|
810
932
|
method: "GET",
|
|
811
|
-
query:
|
|
812
|
-
state:
|
|
813
|
-
code:
|
|
814
|
-
code_verifier: z3.string().optional()
|
|
933
|
+
query: z.object({
|
|
934
|
+
state: z.string(),
|
|
935
|
+
code: z.string()
|
|
815
936
|
}),
|
|
816
937
|
metadata: HIDE_ON_CLIENT_METADATA
|
|
817
938
|
},
|
|
@@ -825,15 +946,20 @@ var callbackOAuth = createAuthEndpoint(
|
|
|
825
946
|
c.params.id,
|
|
826
947
|
"not found"
|
|
827
948
|
);
|
|
828
|
-
throw new
|
|
949
|
+
throw new APIError("NOT_FOUND");
|
|
829
950
|
}
|
|
951
|
+
const codeVerifier = await c.getSignedCookie(
|
|
952
|
+
c.context.authCookies.pkCodeVerifier.name,
|
|
953
|
+
c.context.secret
|
|
954
|
+
);
|
|
830
955
|
const tokens = await provider.validateAuthorizationCode(
|
|
831
956
|
c.query.code,
|
|
832
|
-
|
|
957
|
+
codeVerifier,
|
|
958
|
+
`${c.context.baseURL}/callback/${provider.id}`
|
|
833
959
|
);
|
|
834
960
|
if (!tokens) {
|
|
835
961
|
c.context.logger.error("Code verification failed");
|
|
836
|
-
throw new
|
|
962
|
+
throw new APIError("UNAUTHORIZED");
|
|
837
963
|
}
|
|
838
964
|
const user = await provider.getUserInfo(tokens).then((res) => res?.user);
|
|
839
965
|
const id = generateId();
|
|
@@ -841,17 +967,24 @@ var callbackOAuth = createAuthEndpoint(
|
|
|
841
967
|
...user,
|
|
842
968
|
id
|
|
843
969
|
});
|
|
844
|
-
const
|
|
970
|
+
const parsedState = parseState(c.query.state);
|
|
971
|
+
if (!parsedState.success) {
|
|
972
|
+
c.context.logger.error("Unable to parse state");
|
|
973
|
+
throw new APIError("BAD_REQUEST", {
|
|
974
|
+
message: "invalid state"
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
const { callbackURL, currentURL, dontRememberMe } = parsedState.data;
|
|
845
978
|
if (!user || data.success === false) {
|
|
846
979
|
if (currentURL) {
|
|
847
980
|
throw c.redirect(`${currentURL}?error=oauth_validation_failed`);
|
|
848
981
|
} else {
|
|
849
|
-
throw new
|
|
982
|
+
throw new APIError("BAD_REQUEST");
|
|
850
983
|
}
|
|
851
984
|
}
|
|
852
985
|
if (!callbackURL) {
|
|
853
986
|
c.context.logger.error("Callback URL not found");
|
|
854
|
-
throw new
|
|
987
|
+
throw new APIError("FORBIDDEN");
|
|
855
988
|
}
|
|
856
989
|
const dbUser = await c.context.internalAdapter.findUserByEmail(user.email);
|
|
857
990
|
const userId = dbUser?.user.id;
|
|
@@ -871,13 +1004,13 @@ var callbackOAuth = createAuthEndpoint(
|
|
|
871
1004
|
accountId: user.id,
|
|
872
1005
|
id: `${provider.id}:${user.id}`,
|
|
873
1006
|
userId: dbUser.user.id,
|
|
874
|
-
...tokens
|
|
1007
|
+
...getAccountTokens(tokens)
|
|
875
1008
|
});
|
|
876
1009
|
}
|
|
877
1010
|
} else {
|
|
878
1011
|
try {
|
|
879
1012
|
await c.context.internalAdapter.createOAuthUser(data.data, {
|
|
880
|
-
...tokens,
|
|
1013
|
+
...getAccountTokens(tokens),
|
|
881
1014
|
id: `${provider.id}:${user.id}`,
|
|
882
1015
|
providerId: provider.id,
|
|
883
1016
|
accountId: user.id,
|
|
@@ -891,20 +1024,16 @@ var callbackOAuth = createAuthEndpoint(
|
|
|
891
1024
|
}
|
|
892
1025
|
}
|
|
893
1026
|
if (!userId && !id)
|
|
894
|
-
throw new
|
|
1027
|
+
throw new APIError("INTERNAL_SERVER_ERROR", {
|
|
895
1028
|
message: "Unable to create user"
|
|
896
1029
|
});
|
|
897
1030
|
const session = await c.context.internalAdapter.createSession(
|
|
898
1031
|
userId || id,
|
|
899
|
-
c.request
|
|
1032
|
+
c.request,
|
|
1033
|
+
dontRememberMe
|
|
900
1034
|
);
|
|
901
1035
|
try {
|
|
902
|
-
await c.
|
|
903
|
-
c.context.authCookies.sessionToken.name,
|
|
904
|
-
session.id,
|
|
905
|
-
c.context.secret,
|
|
906
|
-
c.context.authCookies.sessionToken.options
|
|
907
|
-
);
|
|
1036
|
+
await setSessionCookie(c, session.id, dontRememberMe);
|
|
908
1037
|
} catch (e) {
|
|
909
1038
|
c.context.logger.error("Unable to set session cookie", e);
|
|
910
1039
|
const url = new URL(currentURL || callbackURL);
|
|
@@ -914,15 +1043,12 @@ var callbackOAuth = createAuthEndpoint(
|
|
|
914
1043
|
throw c.redirect(callbackURL);
|
|
915
1044
|
}
|
|
916
1045
|
);
|
|
917
|
-
|
|
918
|
-
// src/api/routes/sign-out.ts
|
|
919
|
-
import { z as z4 } from "zod";
|
|
920
|
-
var signOut = createAuthEndpoint(
|
|
1046
|
+
createAuthEndpoint(
|
|
921
1047
|
"/sign-out",
|
|
922
1048
|
{
|
|
923
1049
|
method: "POST",
|
|
924
|
-
body:
|
|
925
|
-
callbackURL:
|
|
1050
|
+
body: z.object({
|
|
1051
|
+
callbackURL: z.string().optional()
|
|
926
1052
|
}).optional()
|
|
927
1053
|
},
|
|
928
1054
|
async (ctx) => {
|
|
@@ -934,9 +1060,7 @@ var signOut = createAuthEndpoint(
|
|
|
934
1060
|
return ctx.json(null);
|
|
935
1061
|
}
|
|
936
1062
|
await ctx.context.internalAdapter.deleteSession(sessionCookieToken);
|
|
937
|
-
|
|
938
|
-
maxAge: 0
|
|
939
|
-
});
|
|
1063
|
+
deleteSessionCookie(ctx);
|
|
940
1064
|
return ctx.json(null, {
|
|
941
1065
|
body: {
|
|
942
1066
|
redirect: !!ctx.body?.callbackURL,
|
|
@@ -945,22 +1069,15 @@ var signOut = createAuthEndpoint(
|
|
|
945
1069
|
});
|
|
946
1070
|
}
|
|
947
1071
|
);
|
|
948
|
-
|
|
949
|
-
// src/api/routes/forget-password.ts
|
|
950
|
-
import { TimeSpan } from "oslo";
|
|
951
|
-
import { createJWT } from "oslo/jwt";
|
|
952
|
-
import { validateJWT } from "oslo/jwt";
|
|
953
|
-
import { Argon2id as Argon2id2 } from "oslo/password";
|
|
954
|
-
import { z as z5 } from "zod";
|
|
955
|
-
var forgetPassword = createAuthEndpoint(
|
|
1072
|
+
createAuthEndpoint(
|
|
956
1073
|
"/forget-password",
|
|
957
1074
|
{
|
|
958
1075
|
method: "POST",
|
|
959
|
-
body:
|
|
1076
|
+
body: z.object({
|
|
960
1077
|
/**
|
|
961
1078
|
* The email address of the user to send a password reset email to.
|
|
962
1079
|
*/
|
|
963
|
-
email:
|
|
1080
|
+
email: z.string().email()
|
|
964
1081
|
})
|
|
965
1082
|
},
|
|
966
1083
|
async (ctx) => {
|
|
@@ -1015,14 +1132,14 @@ var forgetPassword = createAuthEndpoint(
|
|
|
1015
1132
|
});
|
|
1016
1133
|
}
|
|
1017
1134
|
);
|
|
1018
|
-
|
|
1135
|
+
createAuthEndpoint(
|
|
1019
1136
|
"/reset-password",
|
|
1020
1137
|
{
|
|
1021
1138
|
method: "POST",
|
|
1022
|
-
body:
|
|
1023
|
-
token:
|
|
1024
|
-
newPassword:
|
|
1025
|
-
callbackURL:
|
|
1139
|
+
body: z.object({
|
|
1140
|
+
token: z.string(),
|
|
1141
|
+
newPassword: z.string(),
|
|
1142
|
+
callbackURL: z.string().optional()
|
|
1026
1143
|
})
|
|
1027
1144
|
},
|
|
1028
1145
|
async (ctx) => {
|
|
@@ -1033,7 +1150,7 @@ var resetPassword = createAuthEndpoint(
|
|
|
1033
1150
|
Buffer.from(ctx.context.secret),
|
|
1034
1151
|
token
|
|
1035
1152
|
);
|
|
1036
|
-
const email =
|
|
1153
|
+
const email = z.string().email().parse(jwt.payload.email);
|
|
1037
1154
|
const user = await ctx.context.internalAdapter.findUserByEmail(email);
|
|
1038
1155
|
if (!user) {
|
|
1039
1156
|
return ctx.json(null, {
|
|
@@ -1053,8 +1170,7 @@ var resetPassword = createAuthEndpoint(
|
|
|
1053
1170
|
}
|
|
1054
1171
|
});
|
|
1055
1172
|
}
|
|
1056
|
-
const
|
|
1057
|
-
const hashedPassword = await argon2id.hash(newPassword);
|
|
1173
|
+
const hashedPassword = await ctx.context.password.hash(newPassword);
|
|
1058
1174
|
const updatedUser = await ctx.context.internalAdapter.updatePassword(
|
|
1059
1175
|
user.user.id,
|
|
1060
1176
|
hashedPassword
|
|
@@ -1085,18 +1201,30 @@ var resetPassword = createAuthEndpoint(
|
|
|
1085
1201
|
}
|
|
1086
1202
|
}
|
|
1087
1203
|
);
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1204
|
+
async function createEmailVerificationToken(secret, email) {
|
|
1205
|
+
const token = await createJWT(
|
|
1206
|
+
"HS256",
|
|
1207
|
+
Buffer.from(secret),
|
|
1208
|
+
{
|
|
1209
|
+
email: email.toLowerCase()
|
|
1210
|
+
},
|
|
1211
|
+
{
|
|
1212
|
+
expiresIn: new TimeSpan(1, "h"),
|
|
1213
|
+
issuer: "better-auth",
|
|
1214
|
+
subject: "verify-email",
|
|
1215
|
+
audiences: [email],
|
|
1216
|
+
includeIssuedTimestamp: true
|
|
1217
|
+
}
|
|
1218
|
+
);
|
|
1219
|
+
return token;
|
|
1220
|
+
}
|
|
1221
|
+
createAuthEndpoint(
|
|
1094
1222
|
"/send-verification-email",
|
|
1095
1223
|
{
|
|
1096
1224
|
method: "POST",
|
|
1097
|
-
body:
|
|
1098
|
-
email:
|
|
1099
|
-
callbackURL:
|
|
1225
|
+
body: z.object({
|
|
1226
|
+
email: z.string().email(),
|
|
1227
|
+
callbackURL: z.string().optional()
|
|
1100
1228
|
})
|
|
1101
1229
|
},
|
|
1102
1230
|
async (ctx) => {
|
|
@@ -1110,83 +1238,34 @@ var sendVerificationEmail = createAuthEndpoint(
|
|
|
1110
1238
|
});
|
|
1111
1239
|
}
|
|
1112
1240
|
const { email } = ctx.body;
|
|
1113
|
-
const token = await
|
|
1114
|
-
"HS256",
|
|
1115
|
-
Buffer.from(ctx.context.secret),
|
|
1116
|
-
{
|
|
1117
|
-
email: email.toLowerCase()
|
|
1118
|
-
},
|
|
1119
|
-
{
|
|
1120
|
-
expiresIn: new TimeSpan2(1, "h"),
|
|
1121
|
-
issuer: "better-auth",
|
|
1122
|
-
subject: "verify-email",
|
|
1123
|
-
audiences: [email],
|
|
1124
|
-
includeIssuedTimestamp: true
|
|
1125
|
-
}
|
|
1126
|
-
);
|
|
1241
|
+
const token = await createEmailVerificationToken(ctx.context.secret, email);
|
|
1127
1242
|
const url = `${ctx.context.baseURL}/verify-email?token=${token}?callbackURL=${ctx.body.callbackURL}`;
|
|
1128
1243
|
await ctx.context.options.emailAndPassword.sendVerificationEmail(
|
|
1129
1244
|
email,
|
|
1130
|
-
url
|
|
1245
|
+
url,
|
|
1246
|
+
token
|
|
1131
1247
|
);
|
|
1132
1248
|
return ctx.json({
|
|
1133
1249
|
status: true
|
|
1134
1250
|
});
|
|
1135
1251
|
}
|
|
1136
1252
|
);
|
|
1137
|
-
|
|
1253
|
+
createAuthEndpoint(
|
|
1138
1254
|
"/verify-email",
|
|
1139
1255
|
{
|
|
1140
1256
|
method: "GET",
|
|
1141
|
-
query:
|
|
1142
|
-
token:
|
|
1143
|
-
callbackURL:
|
|
1257
|
+
query: z.object({
|
|
1258
|
+
token: z.string(),
|
|
1259
|
+
callbackURL: z.string().optional()
|
|
1144
1260
|
})
|
|
1145
1261
|
},
|
|
1146
1262
|
async (ctx) => {
|
|
1147
1263
|
const { token } = ctx.query;
|
|
1264
|
+
let jwt;
|
|
1148
1265
|
try {
|
|
1149
|
-
|
|
1150
|
-
"HS256",
|
|
1151
|
-
Buffer.from(ctx.context.secret),
|
|
1152
|
-
token
|
|
1153
|
-
);
|
|
1154
|
-
const schema = z6.object({
|
|
1155
|
-
email: z6.string().email()
|
|
1156
|
-
});
|
|
1157
|
-
const parsed = schema.parse(jwt.payload);
|
|
1158
|
-
const user = await ctx.context.internalAdapter.findUserByEmail(
|
|
1159
|
-
parsed.email
|
|
1160
|
-
);
|
|
1161
|
-
if (!user) {
|
|
1162
|
-
return ctx.json(null, {
|
|
1163
|
-
status: 400,
|
|
1164
|
-
statusText: "USER_NOT_FOUND",
|
|
1165
|
-
body: {
|
|
1166
|
-
message: "User not found"
|
|
1167
|
-
}
|
|
1168
|
-
});
|
|
1169
|
-
}
|
|
1170
|
-
const account = user.accounts.find((a) => a.providerId === "credential");
|
|
1171
|
-
if (!account) {
|
|
1172
|
-
return ctx.json(null, {
|
|
1173
|
-
status: 400,
|
|
1174
|
-
statusText: "ACCOUNT_NOT_FOUND",
|
|
1175
|
-
body: {
|
|
1176
|
-
message: "Account not found"
|
|
1177
|
-
}
|
|
1178
|
-
});
|
|
1179
|
-
}
|
|
1180
|
-
await ctx.context.internalAdapter.updateUserByEmail(parsed.email, {
|
|
1181
|
-
emailVerified: true
|
|
1182
|
-
});
|
|
1183
|
-
if (ctx.query.callbackURL) {
|
|
1184
|
-
throw ctx.redirect(ctx.query.callbackURL);
|
|
1185
|
-
}
|
|
1186
|
-
return ctx.json({
|
|
1187
|
-
status: true
|
|
1188
|
-
});
|
|
1266
|
+
jwt = await validateJWT("HS256", Buffer.from(ctx.context.secret), token);
|
|
1189
1267
|
} catch (e) {
|
|
1268
|
+
ctx.context.logger.error("Failed to verify email", e);
|
|
1190
1269
|
return ctx.json(null, {
|
|
1191
1270
|
status: 400,
|
|
1192
1271
|
statusText: "INVALID_TOKEN",
|
|
@@ -1195,6 +1274,41 @@ var verifyEmail = createAuthEndpoint(
|
|
|
1195
1274
|
}
|
|
1196
1275
|
});
|
|
1197
1276
|
}
|
|
1277
|
+
const schema = z.object({
|
|
1278
|
+
email: z.string().email()
|
|
1279
|
+
});
|
|
1280
|
+
const parsed = schema.parse(jwt.payload);
|
|
1281
|
+
const user = await ctx.context.internalAdapter.findUserByEmail(
|
|
1282
|
+
parsed.email
|
|
1283
|
+
);
|
|
1284
|
+
if (!user) {
|
|
1285
|
+
return ctx.json(null, {
|
|
1286
|
+
status: 400,
|
|
1287
|
+
statusText: "USER_NOT_FOUND",
|
|
1288
|
+
body: {
|
|
1289
|
+
message: "User not found"
|
|
1290
|
+
}
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
const account = user.accounts.find((a) => a.providerId === "credential");
|
|
1294
|
+
if (!account) {
|
|
1295
|
+
return ctx.json(null, {
|
|
1296
|
+
status: 400,
|
|
1297
|
+
statusText: "ACCOUNT_NOT_FOUND",
|
|
1298
|
+
body: {
|
|
1299
|
+
message: "Account not found"
|
|
1300
|
+
}
|
|
1301
|
+
});
|
|
1302
|
+
}
|
|
1303
|
+
await ctx.context.internalAdapter.updateUserByEmail(parsed.email, {
|
|
1304
|
+
emailVerified: true
|
|
1305
|
+
});
|
|
1306
|
+
if (ctx.query.callbackURL) {
|
|
1307
|
+
throw ctx.redirect(ctx.query.callbackURL);
|
|
1308
|
+
}
|
|
1309
|
+
return ctx.json({
|
|
1310
|
+
status: true
|
|
1311
|
+
});
|
|
1198
1312
|
}
|
|
1199
1313
|
);
|
|
1200
1314
|
|
|
@@ -1348,12 +1462,6 @@ var permissionFromString = (permission) => {
|
|
|
1348
1462
|
return Role.fromString(permission ?? "");
|
|
1349
1463
|
};
|
|
1350
1464
|
|
|
1351
|
-
// src/utils/date.ts
|
|
1352
|
-
var getDate = (span) => {
|
|
1353
|
-
const date = /* @__PURE__ */ new Date();
|
|
1354
|
-
return new Date(date.getTime() + span);
|
|
1355
|
-
};
|
|
1356
|
-
|
|
1357
1465
|
// src/plugins/organization/adapter.ts
|
|
1358
1466
|
var getOrgAdapter = (adapter, options) => {
|
|
1359
1467
|
return {
|
|
@@ -1482,7 +1590,7 @@ var getOrgAdapter = (adapter, options) => {
|
|
|
1482
1590
|
return organization2;
|
|
1483
1591
|
},
|
|
1484
1592
|
deleteOrganization: async (orgId) => {
|
|
1485
|
-
|
|
1593
|
+
await adapter.delete({
|
|
1486
1594
|
model: "organization",
|
|
1487
1595
|
where: [
|
|
1488
1596
|
{
|
|
@@ -1491,7 +1599,7 @@ var getOrgAdapter = (adapter, options) => {
|
|
|
1491
1599
|
}
|
|
1492
1600
|
]
|
|
1493
1601
|
});
|
|
1494
|
-
return
|
|
1602
|
+
return orgId;
|
|
1495
1603
|
},
|
|
1496
1604
|
setActiveOrganization: async (sessionId, orgId) => {
|
|
1497
1605
|
const session = await adapter.update({
|
|
@@ -1568,7 +1676,6 @@ var getOrgAdapter = (adapter, options) => {
|
|
|
1568
1676
|
]
|
|
1569
1677
|
});
|
|
1570
1678
|
const organizationIds = members?.map((member) => member.organizationId);
|
|
1571
|
-
console.log({ organizationIds });
|
|
1572
1679
|
if (!organizationIds) {
|
|
1573
1680
|
return [];
|
|
1574
1681
|
}
|
|
@@ -1662,16 +1769,10 @@ var getOrgAdapter = (adapter, options) => {
|
|
|
1662
1769
|
}
|
|
1663
1770
|
};
|
|
1664
1771
|
};
|
|
1665
|
-
|
|
1666
|
-
// src/plugins/organization/call.ts
|
|
1667
|
-
import "better-call";
|
|
1668
|
-
|
|
1669
|
-
// src/api/middlewares/session.ts
|
|
1670
|
-
import { APIError as APIError3 } from "better-call";
|
|
1671
1772
|
var sessionMiddleware = createAuthMiddleware(async (ctx) => {
|
|
1672
1773
|
const session = await getSessionFromCtx(ctx);
|
|
1673
1774
|
if (!session?.session) {
|
|
1674
|
-
throw new
|
|
1775
|
+
throw new APIError("UNAUTHORIZED");
|
|
1675
1776
|
}
|
|
1676
1777
|
return {
|
|
1677
1778
|
session
|
|
@@ -1693,38 +1794,32 @@ var orgSessionMiddleware = createAuthMiddleware(
|
|
|
1693
1794
|
};
|
|
1694
1795
|
}
|
|
1695
1796
|
);
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
var role = z7.enum(["admin", "member", "owner"]);
|
|
1703
|
-
var invitationStatus = z7.enum(["pending", "accepted", "rejected", "canceled"]).default("pending");
|
|
1704
|
-
var organizationSchema = z7.object({
|
|
1705
|
-
id: z7.string(),
|
|
1706
|
-
name: z7.string(),
|
|
1707
|
-
slug: z7.string()
|
|
1797
|
+
var role = z.enum(["admin", "member", "owner"]);
|
|
1798
|
+
var invitationStatus = z.enum(["pending", "accepted", "rejected", "canceled"]).default("pending");
|
|
1799
|
+
z.object({
|
|
1800
|
+
id: z.string(),
|
|
1801
|
+
name: z.string(),
|
|
1802
|
+
slug: z.string()
|
|
1708
1803
|
});
|
|
1709
|
-
|
|
1710
|
-
id:
|
|
1711
|
-
name:
|
|
1712
|
-
email:
|
|
1713
|
-
organizationId:
|
|
1714
|
-
userId:
|
|
1804
|
+
z.object({
|
|
1805
|
+
id: z.string(),
|
|
1806
|
+
name: z.string(),
|
|
1807
|
+
email: z.string(),
|
|
1808
|
+
organizationId: z.string(),
|
|
1809
|
+
userId: z.string(),
|
|
1715
1810
|
role
|
|
1716
1811
|
});
|
|
1717
|
-
|
|
1718
|
-
id:
|
|
1719
|
-
organizationId:
|
|
1720
|
-
email:
|
|
1812
|
+
z.object({
|
|
1813
|
+
id: z.string(),
|
|
1814
|
+
organizationId: z.string(),
|
|
1815
|
+
email: z.string(),
|
|
1721
1816
|
role,
|
|
1722
1817
|
status: invitationStatus,
|
|
1723
1818
|
/**
|
|
1724
1819
|
* The id of the user who invited the user.
|
|
1725
1820
|
*/
|
|
1726
|
-
inviterId:
|
|
1727
|
-
expiresAt:
|
|
1821
|
+
inviterId: z.string(),
|
|
1822
|
+
expiresAt: z.date()
|
|
1728
1823
|
});
|
|
1729
1824
|
|
|
1730
1825
|
// src/plugins/organization/routes/crud-invites.ts
|
|
@@ -1733,11 +1828,11 @@ var createInvitation = createAuthEndpoint(
|
|
|
1733
1828
|
{
|
|
1734
1829
|
method: "POST",
|
|
1735
1830
|
use: [orgMiddleware, orgSessionMiddleware],
|
|
1736
|
-
body:
|
|
1737
|
-
email:
|
|
1831
|
+
body: z.object({
|
|
1832
|
+
email: z.string(),
|
|
1738
1833
|
role,
|
|
1739
|
-
organizationId:
|
|
1740
|
-
resend:
|
|
1834
|
+
organizationId: z.string().optional(),
|
|
1835
|
+
resend: z.boolean().optional()
|
|
1741
1836
|
})
|
|
1742
1837
|
},
|
|
1743
1838
|
async (ctx) => {
|
|
@@ -1827,8 +1922,8 @@ var acceptInvitation = createAuthEndpoint(
|
|
|
1827
1922
|
"/organization/accept-invitation",
|
|
1828
1923
|
{
|
|
1829
1924
|
method: "POST",
|
|
1830
|
-
body:
|
|
1831
|
-
invitationId:
|
|
1925
|
+
body: z.object({
|
|
1926
|
+
invitationId: z.string()
|
|
1832
1927
|
}),
|
|
1833
1928
|
use: [orgMiddleware, orgSessionMiddleware]
|
|
1834
1929
|
},
|
|
@@ -1864,6 +1959,18 @@ var acceptInvitation = createAuthEndpoint(
|
|
|
1864
1959
|
role: invitation.role,
|
|
1865
1960
|
name: session.user.name
|
|
1866
1961
|
});
|
|
1962
|
+
await adapter.setActiveOrganization(
|
|
1963
|
+
session.session.id,
|
|
1964
|
+
invitation.organizationId
|
|
1965
|
+
);
|
|
1966
|
+
if (!acceptedI) {
|
|
1967
|
+
return ctx.json(null, {
|
|
1968
|
+
status: 400,
|
|
1969
|
+
body: {
|
|
1970
|
+
message: "Invitation not found!"
|
|
1971
|
+
}
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1867
1974
|
return ctx.json({
|
|
1868
1975
|
invitation: acceptedI,
|
|
1869
1976
|
member
|
|
@@ -1874,8 +1981,8 @@ var rejectInvitation = createAuthEndpoint(
|
|
|
1874
1981
|
"/organization/reject-invitation",
|
|
1875
1982
|
{
|
|
1876
1983
|
method: "POST",
|
|
1877
|
-
body:
|
|
1878
|
-
invitationId:
|
|
1984
|
+
body: z.object({
|
|
1985
|
+
invitationId: z.string()
|
|
1879
1986
|
}),
|
|
1880
1987
|
use: [orgMiddleware, orgSessionMiddleware]
|
|
1881
1988
|
},
|
|
@@ -1913,8 +2020,8 @@ var cancelInvitation = createAuthEndpoint(
|
|
|
1913
2020
|
"/organization/cancel-invitation",
|
|
1914
2021
|
{
|
|
1915
2022
|
method: "POST",
|
|
1916
|
-
body:
|
|
1917
|
-
invitationId:
|
|
2023
|
+
body: z.object({
|
|
2024
|
+
invitationId: z.string()
|
|
1918
2025
|
}),
|
|
1919
2026
|
use: [orgMiddleware, orgSessionMiddleware]
|
|
1920
2027
|
},
|
|
@@ -1965,8 +2072,8 @@ var getActiveInvitation = createAuthEndpoint(
|
|
|
1965
2072
|
{
|
|
1966
2073
|
method: "GET",
|
|
1967
2074
|
use: [orgMiddleware],
|
|
1968
|
-
query:
|
|
1969
|
-
id:
|
|
2075
|
+
query: z.object({
|
|
2076
|
+
id: z.string()
|
|
1970
2077
|
})
|
|
1971
2078
|
},
|
|
1972
2079
|
async (ctx) => {
|
|
@@ -2029,21 +2136,22 @@ var getActiveInvitation = createAuthEndpoint(
|
|
|
2029
2136
|
});
|
|
2030
2137
|
}
|
|
2031
2138
|
);
|
|
2032
|
-
|
|
2033
|
-
// src/plugins/organization/routes/crud-members.ts
|
|
2034
|
-
import { z as z9 } from "zod";
|
|
2035
2139
|
var removeMember = createAuthEndpoint(
|
|
2036
2140
|
"/organization/remove-member",
|
|
2037
2141
|
{
|
|
2038
2142
|
method: "POST",
|
|
2039
|
-
body:
|
|
2040
|
-
|
|
2143
|
+
body: z.object({
|
|
2144
|
+
memberIdOrEmail: z.string(),
|
|
2145
|
+
/**
|
|
2146
|
+
* If not provided, the active organization will be used
|
|
2147
|
+
*/
|
|
2148
|
+
organizationId: z.string().optional()
|
|
2041
2149
|
}),
|
|
2042
2150
|
use: [orgMiddleware, orgSessionMiddleware]
|
|
2043
2151
|
},
|
|
2044
2152
|
async (ctx) => {
|
|
2045
2153
|
const session = ctx.context.session;
|
|
2046
|
-
const orgId = session.session.activeOrganizationId;
|
|
2154
|
+
const orgId = ctx.body.organizationId || session.session.activeOrganizationId;
|
|
2047
2155
|
if (!orgId) {
|
|
2048
2156
|
return ctx.json(null, {
|
|
2049
2157
|
status: 400,
|
|
@@ -2074,7 +2182,7 @@ var removeMember = createAuthEndpoint(
|
|
|
2074
2182
|
}
|
|
2075
2183
|
});
|
|
2076
2184
|
}
|
|
2077
|
-
if (session.user.id ===
|
|
2185
|
+
if ((session.user.email === ctx.body.memberIdOrEmail || session.user.id === ctx.body.memberIdOrEmail) && member.role === (ctx.context.orgOptions?.creatorRole || "owner")) {
|
|
2078
2186
|
return ctx.json(null, {
|
|
2079
2187
|
status: 400,
|
|
2080
2188
|
body: {
|
|
@@ -2093,7 +2201,15 @@ var removeMember = createAuthEndpoint(
|
|
|
2093
2201
|
status: 403
|
|
2094
2202
|
});
|
|
2095
2203
|
}
|
|
2096
|
-
|
|
2204
|
+
let existing = null;
|
|
2205
|
+
if (ctx.body.memberIdOrEmail.includes("@")) {
|
|
2206
|
+
existing = await adapter.findMemberByEmail({
|
|
2207
|
+
email: ctx.body.memberIdOrEmail,
|
|
2208
|
+
organizationId: orgId
|
|
2209
|
+
});
|
|
2210
|
+
} else {
|
|
2211
|
+
existing = await adapter.findMemberById(ctx.body.memberIdOrEmail);
|
|
2212
|
+
}
|
|
2097
2213
|
if (existing?.organizationId !== orgId) {
|
|
2098
2214
|
return ctx.json(null, {
|
|
2099
2215
|
status: 400,
|
|
@@ -2102,26 +2218,32 @@ var removeMember = createAuthEndpoint(
|
|
|
2102
2218
|
}
|
|
2103
2219
|
});
|
|
2104
2220
|
}
|
|
2105
|
-
|
|
2221
|
+
await adapter.deleteMember(existing.id);
|
|
2106
2222
|
if (session.user.id === existing.userId && session.session.activeOrganizationId === existing.organizationId) {
|
|
2107
2223
|
await adapter.setActiveOrganization(session.session.id, null);
|
|
2108
2224
|
}
|
|
2109
|
-
return ctx.json(
|
|
2225
|
+
return ctx.json({
|
|
2226
|
+
member: existing
|
|
2227
|
+
});
|
|
2110
2228
|
}
|
|
2111
2229
|
);
|
|
2112
|
-
var
|
|
2113
|
-
"/organization/update-member",
|
|
2230
|
+
var updateMemberRole = createAuthEndpoint(
|
|
2231
|
+
"/organization/update-member-role",
|
|
2114
2232
|
{
|
|
2115
2233
|
method: "POST",
|
|
2116
|
-
body:
|
|
2117
|
-
|
|
2118
|
-
|
|
2234
|
+
body: z.object({
|
|
2235
|
+
role: z.enum(["admin", "member", "owner"]),
|
|
2236
|
+
memberId: z.string(),
|
|
2237
|
+
/**
|
|
2238
|
+
* If not provided, the active organization will be used
|
|
2239
|
+
*/
|
|
2240
|
+
organizationId: z.string().optional()
|
|
2119
2241
|
}),
|
|
2120
2242
|
use: [orgMiddleware, orgSessionMiddleware]
|
|
2121
2243
|
},
|
|
2122
2244
|
async (ctx) => {
|
|
2123
2245
|
const session = ctx.context.session;
|
|
2124
|
-
const orgId = session.session.activeOrganizationId;
|
|
2246
|
+
const orgId = ctx.body.organizationId || session.session.activeOrganizationId;
|
|
2125
2247
|
if (!orgId) {
|
|
2126
2248
|
return ctx.json(null, {
|
|
2127
2249
|
status: 400,
|
|
@@ -2154,8 +2276,8 @@ var updateMember = createAuthEndpoint(
|
|
|
2154
2276
|
}
|
|
2155
2277
|
const canUpdateMember = role2.authorize({
|
|
2156
2278
|
member: ["update"]
|
|
2157
|
-
});
|
|
2158
|
-
if (canUpdateMember
|
|
2279
|
+
}).error || ctx.body.role === "owner" && member.role !== "owner";
|
|
2280
|
+
if (canUpdateMember) {
|
|
2159
2281
|
return ctx.json(null, {
|
|
2160
2282
|
body: {
|
|
2161
2283
|
message: "You are not allowed to update this member"
|
|
@@ -2167,20 +2289,25 @@ var updateMember = createAuthEndpoint(
|
|
|
2167
2289
|
ctx.body.memberId,
|
|
2168
2290
|
ctx.body.role
|
|
2169
2291
|
);
|
|
2292
|
+
if (!updatedMember) {
|
|
2293
|
+
return ctx.json(null, {
|
|
2294
|
+
status: 400,
|
|
2295
|
+
body: {
|
|
2296
|
+
message: "Member not found!"
|
|
2297
|
+
}
|
|
2298
|
+
});
|
|
2299
|
+
}
|
|
2170
2300
|
return ctx.json(updatedMember);
|
|
2171
2301
|
}
|
|
2172
2302
|
);
|
|
2173
|
-
|
|
2174
|
-
// src/plugins/organization/routes/crud-org.ts
|
|
2175
|
-
import { z as z10 } from "zod";
|
|
2176
2303
|
var createOrganization = createAuthEndpoint(
|
|
2177
2304
|
"/organization/create",
|
|
2178
2305
|
{
|
|
2179
2306
|
method: "POST",
|
|
2180
|
-
body:
|
|
2181
|
-
name:
|
|
2182
|
-
slug:
|
|
2183
|
-
userId:
|
|
2307
|
+
body: z.object({
|
|
2308
|
+
name: z.string(),
|
|
2309
|
+
slug: z.string(),
|
|
2310
|
+
userId: z.string().optional()
|
|
2184
2311
|
}),
|
|
2185
2312
|
use: [orgMiddleware, orgSessionMiddleware]
|
|
2186
2313
|
},
|
|
@@ -2228,10 +2355,12 @@ var updateOrganization = createAuthEndpoint(
|
|
|
2228
2355
|
"/organization/update",
|
|
2229
2356
|
{
|
|
2230
2357
|
method: "POST",
|
|
2231
|
-
body:
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2358
|
+
body: z.object({
|
|
2359
|
+
data: z.object({
|
|
2360
|
+
name: z.string().optional(),
|
|
2361
|
+
slug: z.string().optional()
|
|
2362
|
+
}).partial(),
|
|
2363
|
+
orgId: z.string().optional()
|
|
2235
2364
|
}),
|
|
2236
2365
|
requireHeaders: true,
|
|
2237
2366
|
use: [orgMiddleware]
|
|
@@ -2285,7 +2414,7 @@ var updateOrganization = createAuthEndpoint(
|
|
|
2285
2414
|
status: 403
|
|
2286
2415
|
});
|
|
2287
2416
|
}
|
|
2288
|
-
const updatedOrg = await adapter.updateOrganization(orgId, ctx.body);
|
|
2417
|
+
const updatedOrg = await adapter.updateOrganization(orgId, ctx.body.data);
|
|
2289
2418
|
return ctx.json(updatedOrg);
|
|
2290
2419
|
}
|
|
2291
2420
|
);
|
|
@@ -2293,8 +2422,8 @@ var deleteOrganization = createAuthEndpoint(
|
|
|
2293
2422
|
"/organization/delete",
|
|
2294
2423
|
{
|
|
2295
2424
|
method: "POST",
|
|
2296
|
-
body:
|
|
2297
|
-
orgId:
|
|
2425
|
+
body: z.object({
|
|
2426
|
+
orgId: z.string()
|
|
2298
2427
|
}),
|
|
2299
2428
|
requireHeaders: true,
|
|
2300
2429
|
use: [orgMiddleware]
|
|
@@ -2351,16 +2480,16 @@ var deleteOrganization = createAuthEndpoint(
|
|
|
2351
2480
|
if (orgId === session.session.activeOrganizationId) {
|
|
2352
2481
|
await adapter.setActiveOrganization(session.session.id, null);
|
|
2353
2482
|
}
|
|
2354
|
-
|
|
2355
|
-
return ctx.json(
|
|
2483
|
+
await adapter.deleteOrganization(orgId);
|
|
2484
|
+
return ctx.json(orgId);
|
|
2356
2485
|
}
|
|
2357
2486
|
);
|
|
2358
2487
|
var getFullOrganization = createAuthEndpoint(
|
|
2359
|
-
"/organization/full",
|
|
2488
|
+
"/organization/get-full",
|
|
2360
2489
|
{
|
|
2361
2490
|
method: "GET",
|
|
2362
|
-
query:
|
|
2363
|
-
orgId:
|
|
2491
|
+
query: z.object({
|
|
2492
|
+
orgId: z.string().optional()
|
|
2364
2493
|
}),
|
|
2365
2494
|
requireHeaders: true,
|
|
2366
2495
|
use: [orgMiddleware, orgSessionMiddleware]
|
|
@@ -2390,11 +2519,11 @@ var getFullOrganization = createAuthEndpoint(
|
|
|
2390
2519
|
}
|
|
2391
2520
|
);
|
|
2392
2521
|
var setActiveOrganization = createAuthEndpoint(
|
|
2393
|
-
"/organization/
|
|
2522
|
+
"/organization/activate",
|
|
2394
2523
|
{
|
|
2395
2524
|
method: "POST",
|
|
2396
|
-
body:
|
|
2397
|
-
orgId:
|
|
2525
|
+
body: z.object({
|
|
2526
|
+
orgId: z.string()
|
|
2398
2527
|
}),
|
|
2399
2528
|
use: [sessionMiddleware, orgMiddleware]
|
|
2400
2529
|
},
|
|
@@ -2427,6 +2556,7 @@ var organization = (options) => {
|
|
|
2427
2556
|
const endpoints = {
|
|
2428
2557
|
createOrganization,
|
|
2429
2558
|
updateOrganization,
|
|
2559
|
+
deleteOrganization,
|
|
2430
2560
|
setActiveOrganization,
|
|
2431
2561
|
getFullOrganization,
|
|
2432
2562
|
listOrganization,
|
|
@@ -2436,7 +2566,7 @@ var organization = (options) => {
|
|
|
2436
2566
|
getActiveInvitation,
|
|
2437
2567
|
rejectInvitation,
|
|
2438
2568
|
removeMember,
|
|
2439
|
-
|
|
2569
|
+
updateMemberRole
|
|
2440
2570
|
};
|
|
2441
2571
|
const roles = {
|
|
2442
2572
|
...defaultRoles,
|
|
@@ -2458,14 +2588,14 @@ var organization = (options) => {
|
|
|
2458
2588
|
{
|
|
2459
2589
|
method: "POST",
|
|
2460
2590
|
requireHeaders: true,
|
|
2461
|
-
body:
|
|
2462
|
-
permission:
|
|
2591
|
+
body: z.object({
|
|
2592
|
+
permission: z.record(z.string(), z.array(z.string()))
|
|
2463
2593
|
}),
|
|
2464
2594
|
use: [orgSessionMiddleware]
|
|
2465
2595
|
},
|
|
2466
2596
|
async (ctx) => {
|
|
2467
2597
|
if (!ctx.context.session.session.activeOrganizationId) {
|
|
2468
|
-
throw new
|
|
2598
|
+
throw new APIError("BAD_REQUEST", {
|
|
2469
2599
|
message: "No active organization"
|
|
2470
2600
|
});
|
|
2471
2601
|
}
|
|
@@ -2475,7 +2605,7 @@ var organization = (options) => {
|
|
|
2475
2605
|
organizationId: ctx.context.session.session.activeOrganizationId || ""
|
|
2476
2606
|
});
|
|
2477
2607
|
if (!member) {
|
|
2478
|
-
throw new
|
|
2608
|
+
throw new APIError("UNAUTHORIZED", {
|
|
2479
2609
|
message: "You are not a member of this organization"
|
|
2480
2610
|
});
|
|
2481
2611
|
}
|
|
@@ -2578,16 +2708,6 @@ var organization = (options) => {
|
|
|
2578
2708
|
}
|
|
2579
2709
|
};
|
|
2580
2710
|
};
|
|
2581
|
-
|
|
2582
|
-
// src/plugins/two-factor/index.ts
|
|
2583
|
-
import { alphabet as alphabet3, generateRandomString as generateRandomString3 } from "oslo/crypto";
|
|
2584
|
-
import "zod";
|
|
2585
|
-
|
|
2586
|
-
// src/crypto/index.ts
|
|
2587
|
-
import { xchacha20poly1305 } from "@noble/ciphers/chacha";
|
|
2588
|
-
import { bytesToHex, hexToBytes, utf8ToBytes } from "@noble/ciphers/utils";
|
|
2589
|
-
import { managedNonce } from "@noble/ciphers/webcrypto";
|
|
2590
|
-
import { sha256 } from "@noble/hashes/sha256";
|
|
2591
2711
|
async function hs256(secretKey, message) {
|
|
2592
2712
|
const enc = new TextEncoder();
|
|
2593
2713
|
const algorithm = { name: "HMAC", hash: "SHA-256" };
|
|
@@ -2618,13 +2738,6 @@ var symmetricDecrypt = ({ key, data }) => {
|
|
|
2618
2738
|
return chacha.decrypt(dataAsBytes);
|
|
2619
2739
|
};
|
|
2620
2740
|
|
|
2621
|
-
// src/plugins/two-factor/backup-codes/index.ts
|
|
2622
|
-
import { alphabet as alphabet2, generateRandomString as generateRandomString2 } from "oslo/crypto";
|
|
2623
|
-
import { z as z12 } from "zod";
|
|
2624
|
-
|
|
2625
|
-
// src/plugins/two-factor/verify-middleware.ts
|
|
2626
|
-
import { APIError as APIError6 } from "better-call";
|
|
2627
|
-
|
|
2628
2741
|
// src/plugins/two-factor/constant.ts
|
|
2629
2742
|
var TWO_FACTOR_COOKIE_NAME = "better-auth.two-factor";
|
|
2630
2743
|
var OTP_RANDOM_NUMBER_COOKIE_NAME = "otp.counter";
|
|
@@ -2636,13 +2749,13 @@ var verifyTwoFactorMiddleware = createAuthMiddleware(async (ctx) => {
|
|
|
2636
2749
|
ctx.context.secret
|
|
2637
2750
|
);
|
|
2638
2751
|
if (!cookie) {
|
|
2639
|
-
throw new
|
|
2752
|
+
throw new APIError("UNAUTHORIZED", {
|
|
2640
2753
|
message: "two factor isn't enabled"
|
|
2641
2754
|
});
|
|
2642
2755
|
}
|
|
2643
2756
|
const [userId, hash] = cookie.split("!");
|
|
2644
2757
|
if (!userId || !hash) {
|
|
2645
|
-
throw new
|
|
2758
|
+
throw new APIError("UNAUTHORIZED", {
|
|
2646
2759
|
message: "invalid two factor cookie"
|
|
2647
2760
|
});
|
|
2648
2761
|
}
|
|
@@ -2656,7 +2769,7 @@ var verifyTwoFactorMiddleware = createAuthMiddleware(async (ctx) => {
|
|
|
2656
2769
|
]
|
|
2657
2770
|
});
|
|
2658
2771
|
if (!sessions.length) {
|
|
2659
|
-
throw new
|
|
2772
|
+
throw new APIError("UNAUTHORIZED", {
|
|
2660
2773
|
message: "invalid session"
|
|
2661
2774
|
});
|
|
2662
2775
|
}
|
|
@@ -2664,7 +2777,7 @@ var verifyTwoFactorMiddleware = createAuthMiddleware(async (ctx) => {
|
|
|
2664
2777
|
(session) => session.expiresAt > /* @__PURE__ */ new Date()
|
|
2665
2778
|
);
|
|
2666
2779
|
if (!activeSessions) {
|
|
2667
|
-
throw new
|
|
2780
|
+
throw new APIError("UNAUTHORIZED", {
|
|
2668
2781
|
message: "invalid session"
|
|
2669
2782
|
});
|
|
2670
2783
|
}
|
|
@@ -2680,19 +2793,14 @@ var verifyTwoFactorMiddleware = createAuthMiddleware(async (ctx) => {
|
|
|
2680
2793
|
]
|
|
2681
2794
|
});
|
|
2682
2795
|
if (!user) {
|
|
2683
|
-
throw new
|
|
2796
|
+
throw new APIError("UNAUTHORIZED", {
|
|
2684
2797
|
message: "invalid session"
|
|
2685
2798
|
});
|
|
2686
2799
|
}
|
|
2687
2800
|
if (hashToMatch === hash) {
|
|
2688
2801
|
return {
|
|
2689
2802
|
valid: async () => {
|
|
2690
|
-
await ctx.
|
|
2691
|
-
ctx.context.authCookies.sessionToken.name,
|
|
2692
|
-
session.id,
|
|
2693
|
-
ctx.context.secret,
|
|
2694
|
-
ctx.context.authCookies.sessionToken.options
|
|
2695
|
-
);
|
|
2803
|
+
await setSessionCookie(ctx, session.id, false);
|
|
2696
2804
|
if (ctx.body.callbackURL) {
|
|
2697
2805
|
return ctx.json({
|
|
2698
2806
|
status: true,
|
|
@@ -2722,15 +2830,15 @@ var verifyTwoFactorMiddleware = createAuthMiddleware(async (ctx) => {
|
|
|
2722
2830
|
};
|
|
2723
2831
|
}
|
|
2724
2832
|
}
|
|
2725
|
-
throw new
|
|
2833
|
+
throw new APIError("UNAUTHORIZED", {
|
|
2726
2834
|
message: "invalid two factor authentication"
|
|
2727
2835
|
});
|
|
2728
2836
|
});
|
|
2729
2837
|
|
|
2730
2838
|
// src/plugins/two-factor/backup-codes/index.ts
|
|
2731
2839
|
function generateBackupCodesFn(options) {
|
|
2732
|
-
return Array.from({ length:
|
|
2733
|
-
() =>
|
|
2840
|
+
return Array.from({ length: 10 }).fill(null).map(
|
|
2841
|
+
() => generateRandomString(10, alphabet("a-z", "0-9"))
|
|
2734
2842
|
).map((code) => `${code.slice(0, 5)}-${code.slice(5)}`);
|
|
2735
2843
|
}
|
|
2736
2844
|
async function generateBackupCodes(secret, options) {
|
|
@@ -2757,7 +2865,7 @@ async function getBackupCodes(user, key) {
|
|
|
2757
2865
|
await symmetricDecrypt({ key, data: user.twoFactorBackupCodes })
|
|
2758
2866
|
).toString("utf-8");
|
|
2759
2867
|
const data = JSON.parse(secret);
|
|
2760
|
-
const result =
|
|
2868
|
+
const result = z.array(z.string()).safeParse(data);
|
|
2761
2869
|
if (result.success) {
|
|
2762
2870
|
return result.data;
|
|
2763
2871
|
}
|
|
@@ -2771,8 +2879,8 @@ var backupCode2fa = (options) => {
|
|
|
2771
2879
|
"/two-factor/verify-backup-code",
|
|
2772
2880
|
{
|
|
2773
2881
|
method: "POST",
|
|
2774
|
-
body:
|
|
2775
|
-
code:
|
|
2882
|
+
body: z.object({
|
|
2883
|
+
code: z.string()
|
|
2776
2884
|
}),
|
|
2777
2885
|
use: [verifyTwoFactorMiddleware]
|
|
2778
2886
|
},
|
|
@@ -2843,17 +2951,19 @@ var backupCode2fa = (options) => {
|
|
|
2843
2951
|
}
|
|
2844
2952
|
};
|
|
2845
2953
|
};
|
|
2846
|
-
|
|
2847
|
-
// src/plugins/two-factor/otp/index.ts
|
|
2848
|
-
import { APIError as APIError7 } from "better-call";
|
|
2849
|
-
import { generateRandomInteger } from "oslo/crypto";
|
|
2850
|
-
import { generateHOTP } from "oslo/otp";
|
|
2851
|
-
import { z as z13 } from "zod";
|
|
2852
2954
|
var otp2fa = (options) => {
|
|
2853
2955
|
const send2FaOTP = createAuthEndpoint(
|
|
2854
2956
|
"/two-factor/send-otp",
|
|
2855
2957
|
{
|
|
2856
2958
|
method: "POST",
|
|
2959
|
+
body: z.object({
|
|
2960
|
+
/**
|
|
2961
|
+
* should only be used for testing
|
|
2962
|
+
* purposes. This will return the otp
|
|
2963
|
+
* on the response body.
|
|
2964
|
+
*/
|
|
2965
|
+
returnOTP: z.boolean().default(false)
|
|
2966
|
+
}).optional(),
|
|
2857
2967
|
use: [verifyTwoFactorMiddleware]
|
|
2858
2968
|
},
|
|
2859
2969
|
async (ctx) => {
|
|
@@ -2861,7 +2971,7 @@ var otp2fa = (options) => {
|
|
|
2861
2971
|
ctx.context.logger.error(
|
|
2862
2972
|
"otp isn't configured. please pass otp option on two factor plugin to enable otp"
|
|
2863
2973
|
);
|
|
2864
|
-
throw new
|
|
2974
|
+
throw new APIError("BAD_REQUEST", {
|
|
2865
2975
|
message: "otp isn't configured"
|
|
2866
2976
|
});
|
|
2867
2977
|
}
|
|
@@ -2883,22 +2993,25 @@ var otp2fa = (options) => {
|
|
|
2883
2993
|
ctx.context.secret,
|
|
2884
2994
|
cookie.options
|
|
2885
2995
|
);
|
|
2886
|
-
|
|
2996
|
+
if (ctx.body?.returnOTP) {
|
|
2997
|
+
return ctx.json({ OTP: otp, status: true });
|
|
2998
|
+
}
|
|
2999
|
+
return ctx.json({ status: true, OTP: void 0 });
|
|
2887
3000
|
}
|
|
2888
3001
|
);
|
|
2889
3002
|
const verifyOTP = createAuthEndpoint(
|
|
2890
3003
|
"/two-factor/verify-otp",
|
|
2891
3004
|
{
|
|
2892
3005
|
method: "POST",
|
|
2893
|
-
body:
|
|
2894
|
-
code:
|
|
3006
|
+
body: z.object({
|
|
3007
|
+
code: z.string()
|
|
2895
3008
|
}),
|
|
2896
3009
|
use: [verifyTwoFactorMiddleware]
|
|
2897
3010
|
},
|
|
2898
3011
|
async (ctx) => {
|
|
2899
3012
|
const user = ctx.context.session.user;
|
|
2900
3013
|
if (!user.twoFactorEnabled) {
|
|
2901
|
-
throw new
|
|
3014
|
+
throw new APIError("BAD_REQUEST", {
|
|
2902
3015
|
message: "two factor isn't enabled"
|
|
2903
3016
|
});
|
|
2904
3017
|
}
|
|
@@ -2910,7 +3023,7 @@ var otp2fa = (options) => {
|
|
|
2910
3023
|
ctx.context.secret
|
|
2911
3024
|
);
|
|
2912
3025
|
if (!randomNumber) {
|
|
2913
|
-
throw new
|
|
3026
|
+
throw new APIError("UNAUTHORIZED", {
|
|
2914
3027
|
message: "OTP is expired"
|
|
2915
3028
|
});
|
|
2916
3029
|
}
|
|
@@ -2940,16 +3053,10 @@ var otp2fa = (options) => {
|
|
|
2940
3053
|
}
|
|
2941
3054
|
};
|
|
2942
3055
|
};
|
|
2943
|
-
|
|
2944
|
-
// src/plugins/two-factor/totp/index.ts
|
|
2945
|
-
import { APIError as APIError8 } from "better-call";
|
|
2946
|
-
import { TimeSpan as TimeSpan3 } from "oslo";
|
|
2947
|
-
import { TOTPController, createTOTPKeyURI } from "oslo/otp";
|
|
2948
|
-
import { z as z14 } from "zod";
|
|
2949
3056
|
var totp2fa = (options) => {
|
|
2950
3057
|
const opts = {
|
|
2951
3058
|
digits: 6,
|
|
2952
|
-
period: new
|
|
3059
|
+
period: new TimeSpan(options?.period || 30, "s")
|
|
2953
3060
|
};
|
|
2954
3061
|
const generateTOTP = createAuthEndpoint(
|
|
2955
3062
|
"/totp/generate",
|
|
@@ -2962,7 +3069,7 @@ var totp2fa = (options) => {
|
|
|
2962
3069
|
ctx.context.logger.error(
|
|
2963
3070
|
"totp isn't configured. please pass totp option on two factor plugin to enable totp"
|
|
2964
3071
|
);
|
|
2965
|
-
throw new
|
|
3072
|
+
throw new APIError("BAD_REQUEST", {
|
|
2966
3073
|
message: "totp isn't configured"
|
|
2967
3074
|
});
|
|
2968
3075
|
}
|
|
@@ -2983,7 +3090,7 @@ var totp2fa = (options) => {
|
|
|
2983
3090
|
ctx.context.logger.error(
|
|
2984
3091
|
"totp isn't configured. please pass totp option on two factor plugin to enable totp"
|
|
2985
3092
|
);
|
|
2986
|
-
throw new
|
|
3093
|
+
throw new APIError("BAD_REQUEST", {
|
|
2987
3094
|
message: "totp isn't configured"
|
|
2988
3095
|
});
|
|
2989
3096
|
}
|
|
@@ -3002,9 +3109,9 @@ var totp2fa = (options) => {
|
|
|
3002
3109
|
"/two-factor/verify-totp",
|
|
3003
3110
|
{
|
|
3004
3111
|
method: "POST",
|
|
3005
|
-
body:
|
|
3006
|
-
code:
|
|
3007
|
-
callbackURL:
|
|
3112
|
+
body: z.object({
|
|
3113
|
+
code: z.string(),
|
|
3114
|
+
callbackURL: z.string().optional()
|
|
3008
3115
|
}),
|
|
3009
3116
|
use: [verifyTwoFactorMiddleware]
|
|
3010
3117
|
},
|
|
@@ -3013,7 +3120,7 @@ var totp2fa = (options) => {
|
|
|
3013
3120
|
ctx.context.logger.error(
|
|
3014
3121
|
"totp isn't configured. please pass totp option on two factor plugin to enable totp"
|
|
3015
3122
|
);
|
|
3016
|
-
throw new
|
|
3123
|
+
throw new APIError("BAD_REQUEST", {
|
|
3017
3124
|
message: "totp isn't configured"
|
|
3018
3125
|
});
|
|
3019
3126
|
}
|
|
@@ -3041,57 +3148,42 @@ var totp2fa = (options) => {
|
|
|
3041
3148
|
};
|
|
3042
3149
|
};
|
|
3043
3150
|
|
|
3044
|
-
// src/client/create-client-plugin.ts
|
|
3045
|
-
var createClientPlugin = () => {
|
|
3046
|
-
return ($fn) => {
|
|
3047
|
-
return ($fetch) => {
|
|
3048
|
-
const data = $fn($fetch);
|
|
3049
|
-
return {
|
|
3050
|
-
...data,
|
|
3051
|
-
integrations: data.integrations,
|
|
3052
|
-
plugin: {}
|
|
3053
|
-
};
|
|
3054
|
-
};
|
|
3055
|
-
};
|
|
3056
|
-
};
|
|
3057
|
-
|
|
3058
3151
|
// src/plugins/two-factor/client.ts
|
|
3059
3152
|
var twoFactorClient = (options = {
|
|
3060
3153
|
redirect: true,
|
|
3061
3154
|
twoFactorPage: "/"
|
|
3062
3155
|
}) => {
|
|
3063
|
-
return
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
}
|
|
3156
|
+
return {
|
|
3157
|
+
id: "two-factor",
|
|
3158
|
+
$InferServerPlugin: {},
|
|
3159
|
+
atomListeners: [
|
|
3160
|
+
{
|
|
3161
|
+
matcher: (path) => path === "/two-factor/enable" || path === "/two-factor/send-otp" || path === "/two-factor/disable",
|
|
3162
|
+
signal: "_sessionSignal"
|
|
3163
|
+
}
|
|
3164
|
+
],
|
|
3165
|
+
pathMethods: {
|
|
3166
|
+
"enable/totp": "POST",
|
|
3167
|
+
"/two-factor/disable": "POST",
|
|
3168
|
+
"/two-factor/enable": "POST",
|
|
3169
|
+
"/two-factor/send-otp": "POST"
|
|
3170
|
+
},
|
|
3171
|
+
fetchPlugins: [
|
|
3172
|
+
{
|
|
3173
|
+
id: "two-factor",
|
|
3174
|
+
name: "two-factor",
|
|
3175
|
+
hooks: {
|
|
3176
|
+
async onSuccess(context) {
|
|
3177
|
+
if (context.data?.twoFactorRedirect) {
|
|
3178
|
+
if (options.redirect || options.twoFactorPage) {
|
|
3179
|
+
window.location.href = options.twoFactorPage;
|
|
3088
3180
|
}
|
|
3089
3181
|
}
|
|
3090
3182
|
}
|
|
3091
3183
|
}
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
}
|
|
3184
|
+
}
|
|
3185
|
+
]
|
|
3186
|
+
};
|
|
3095
3187
|
};
|
|
3096
3188
|
|
|
3097
3189
|
// src/plugins/two-factor/index.ts
|
|
@@ -3102,7 +3194,6 @@ var twoFactor = (options) => {
|
|
|
3102
3194
|
});
|
|
3103
3195
|
const backupCode = backupCode2fa(options.backupCodeOptions);
|
|
3104
3196
|
const otp = otp2fa(options.otpOptions);
|
|
3105
|
-
const providers = [totp, backupCode, otp];
|
|
3106
3197
|
return {
|
|
3107
3198
|
id: "two-factor",
|
|
3108
3199
|
endpoints: {
|
|
@@ -3117,7 +3208,7 @@ var twoFactor = (options) => {
|
|
|
3117
3208
|
},
|
|
3118
3209
|
async (ctx) => {
|
|
3119
3210
|
const user = ctx.context.session.user;
|
|
3120
|
-
const secret =
|
|
3211
|
+
const secret = generateRandomString(16, alphabet("a-z", "0-9", "-"));
|
|
3121
3212
|
const encryptedSecret = await symmetricEncrypt({
|
|
3122
3213
|
key: ctx.context.secret,
|
|
3123
3214
|
data: secret
|
|
@@ -3175,11 +3266,11 @@ var twoFactor = (options) => {
|
|
|
3175
3266
|
return context.path === "/sign-in/email" || context.path === "/sign-in/username";
|
|
3176
3267
|
},
|
|
3177
3268
|
handler: createAuthMiddleware(async (ctx) => {
|
|
3178
|
-
const returned =
|
|
3269
|
+
const returned = ctx.context.returned;
|
|
3179
3270
|
if (returned?.status !== 200) {
|
|
3180
3271
|
return;
|
|
3181
3272
|
}
|
|
3182
|
-
const response = await returned.json();
|
|
3273
|
+
const response = await returned.clone().json();
|
|
3183
3274
|
if (!response.user.twoFactorEnabled) {
|
|
3184
3275
|
return;
|
|
3185
3276
|
}
|
|
@@ -3234,24 +3325,6 @@ var twoFactor = (options) => {
|
|
|
3234
3325
|
}
|
|
3235
3326
|
};
|
|
3236
3327
|
};
|
|
3237
|
-
|
|
3238
|
-
// src/plugins/passkey/index.ts
|
|
3239
|
-
import {
|
|
3240
|
-
generateAuthenticationOptions,
|
|
3241
|
-
generateRegistrationOptions,
|
|
3242
|
-
verifyAuthenticationResponse,
|
|
3243
|
-
verifyRegistrationResponse
|
|
3244
|
-
} from "@simplewebauthn/server";
|
|
3245
|
-
import { APIError as APIError9 } from "better-call";
|
|
3246
|
-
import { alphabet as alphabet4, generateRandomString as generateRandomString4 } from "oslo/crypto";
|
|
3247
|
-
import { z as z16 } from "zod";
|
|
3248
|
-
|
|
3249
|
-
// src/plugins/passkey/client.ts
|
|
3250
|
-
import {
|
|
3251
|
-
WebAuthnError,
|
|
3252
|
-
startAuthentication,
|
|
3253
|
-
startRegistration
|
|
3254
|
-
} from "@simplewebauthn/browser";
|
|
3255
3328
|
var getPasskeyActions = ($fetch) => {
|
|
3256
3329
|
const signInPasskey = async (opts) => {
|
|
3257
3330
|
const response = await $fetch(
|
|
@@ -3321,18 +3394,25 @@ var getPasskeyActions = ($fetch) => {
|
|
|
3321
3394
|
}
|
|
3322
3395
|
};
|
|
3323
3396
|
return {
|
|
3324
|
-
|
|
3325
|
-
|
|
3397
|
+
signIn: {
|
|
3398
|
+
passkey: signInPasskey
|
|
3399
|
+
},
|
|
3400
|
+
passkey: {
|
|
3401
|
+
register: registerPasskey
|
|
3402
|
+
}
|
|
3403
|
+
};
|
|
3404
|
+
};
|
|
3405
|
+
var passkeyClient = () => {
|
|
3406
|
+
return {
|
|
3407
|
+
id: "passkey",
|
|
3408
|
+
$InferServerPlugin: {},
|
|
3409
|
+
getActions: ($fetch) => getPasskeyActions($fetch),
|
|
3410
|
+
pathMethods: {
|
|
3411
|
+
"/passkey/register": "POST",
|
|
3412
|
+
"/passkey/authenticate": "POST"
|
|
3413
|
+
}
|
|
3326
3414
|
};
|
|
3327
3415
|
};
|
|
3328
|
-
var passkeyClient = createClientPlugin()(
|
|
3329
|
-
($fetch) => {
|
|
3330
|
-
return {
|
|
3331
|
-
id: "passkey",
|
|
3332
|
-
actions: getPasskeyActions($fetch)
|
|
3333
|
-
};
|
|
3334
|
-
}
|
|
3335
|
-
);
|
|
3336
3416
|
|
|
3337
3417
|
// src/plugins/passkey/index.ts
|
|
3338
3418
|
var passkey = (options) => {
|
|
@@ -3370,7 +3450,7 @@ var passkey = (options) => {
|
|
|
3370
3450
|
]
|
|
3371
3451
|
});
|
|
3372
3452
|
const userID = new Uint8Array(
|
|
3373
|
-
Buffer.from(
|
|
3453
|
+
Buffer.from(generateRandomString(32, alphabet("a-z", "0-9")))
|
|
3374
3454
|
);
|
|
3375
3455
|
let options2;
|
|
3376
3456
|
options2 = await generateRegistrationOptions({
|
|
@@ -3418,9 +3498,9 @@ var passkey = (options) => {
|
|
|
3418
3498
|
"/passkey/generate-authenticate-options",
|
|
3419
3499
|
{
|
|
3420
3500
|
method: "POST",
|
|
3421
|
-
body:
|
|
3422
|
-
email:
|
|
3423
|
-
callbackURL:
|
|
3501
|
+
body: z.object({
|
|
3502
|
+
email: z.string().optional(),
|
|
3503
|
+
callbackURL: z.string().optional()
|
|
3424
3504
|
}).optional()
|
|
3425
3505
|
},
|
|
3426
3506
|
async (ctx) => {
|
|
@@ -3477,8 +3557,8 @@ var passkey = (options) => {
|
|
|
3477
3557
|
"/passkey/verify-registration",
|
|
3478
3558
|
{
|
|
3479
3559
|
method: "POST",
|
|
3480
|
-
body:
|
|
3481
|
-
response:
|
|
3560
|
+
body: z.object({
|
|
3561
|
+
response: z.any()
|
|
3482
3562
|
}),
|
|
3483
3563
|
use: [sessionMiddleware]
|
|
3484
3564
|
},
|
|
@@ -3503,7 +3583,7 @@ var passkey = (options) => {
|
|
|
3503
3583
|
challengeString
|
|
3504
3584
|
);
|
|
3505
3585
|
if (userData.id !== ctx.context.session.user.id) {
|
|
3506
|
-
throw new
|
|
3586
|
+
throw new APIError("UNAUTHORIZED", {
|
|
3507
3587
|
message: "You are not authorized to register this passkey"
|
|
3508
3588
|
});
|
|
3509
3589
|
}
|
|
@@ -3528,7 +3608,7 @@ var passkey = (options) => {
|
|
|
3528
3608
|
credentialBackedUp
|
|
3529
3609
|
} = registrationInfo;
|
|
3530
3610
|
const pubKey = Buffer.from(credentialPublicKey).toString("base64");
|
|
3531
|
-
const userID =
|
|
3611
|
+
const userID = generateRandomString(32, alphabet("a-z", "0-9"));
|
|
3532
3612
|
const newPasskey = {
|
|
3533
3613
|
userId: userData.id,
|
|
3534
3614
|
webauthnUserID: userID,
|
|
@@ -3562,8 +3642,8 @@ var passkey = (options) => {
|
|
|
3562
3642
|
"/passkey/verify-authentication",
|
|
3563
3643
|
{
|
|
3564
3644
|
method: "POST",
|
|
3565
|
-
body:
|
|
3566
|
-
response:
|
|
3645
|
+
body: z.object({
|
|
3646
|
+
response: z.any()
|
|
3567
3647
|
})
|
|
3568
3648
|
},
|
|
3569
3649
|
async (ctx) => {
|
|
@@ -3644,12 +3724,7 @@ var passkey = (options) => {
|
|
|
3644
3724
|
passkey2.userId,
|
|
3645
3725
|
ctx.request
|
|
3646
3726
|
);
|
|
3647
|
-
await ctx.
|
|
3648
|
-
ctx.context.authCookies.sessionToken.name,
|
|
3649
|
-
s.id,
|
|
3650
|
-
ctx.context.secret,
|
|
3651
|
-
ctx.context.authCookies.sessionToken.options
|
|
3652
|
-
);
|
|
3727
|
+
await setSessionCookie(ctx, s.id);
|
|
3653
3728
|
if (callbackURL) {
|
|
3654
3729
|
return ctx.json({
|
|
3655
3730
|
url: callbackURL,
|
|
@@ -3716,26 +3791,16 @@ var passkey = (options) => {
|
|
|
3716
3791
|
}
|
|
3717
3792
|
};
|
|
3718
3793
|
};
|
|
3719
|
-
|
|
3720
|
-
// src/plugins/username/index.ts
|
|
3721
|
-
import { z as z18 } from "zod";
|
|
3722
|
-
import { Argon2id as Argon2id4 } from "oslo/password";
|
|
3723
|
-
import { APIError as APIError10 } from "better-call";
|
|
3724
|
-
|
|
3725
|
-
// src/api/routes/sign-up.ts
|
|
3726
|
-
import { alphabet as alphabet5, generateRandomString as generateRandomString5 } from "oslo/crypto";
|
|
3727
|
-
import { Argon2id as Argon2id3 } from "oslo/password";
|
|
3728
|
-
import { z as z17 } from "zod";
|
|
3729
3794
|
var signUpEmail = createAuthEndpoint(
|
|
3730
3795
|
"/sign-up/email",
|
|
3731
3796
|
{
|
|
3732
3797
|
method: "POST",
|
|
3733
|
-
body:
|
|
3734
|
-
name:
|
|
3735
|
-
email:
|
|
3736
|
-
password:
|
|
3737
|
-
image:
|
|
3738
|
-
callbackURL:
|
|
3798
|
+
body: z.object({
|
|
3799
|
+
name: z.string(),
|
|
3800
|
+
email: z.string().email(),
|
|
3801
|
+
password: z.string(),
|
|
3802
|
+
image: z.string().optional(),
|
|
3803
|
+
callbackURL: z.string().optional()
|
|
3739
3804
|
})
|
|
3740
3805
|
},
|
|
3741
3806
|
async (ctx) => {
|
|
@@ -3756,9 +3821,8 @@ var signUpEmail = createAuthEndpoint(
|
|
|
3756
3821
|
body: { message: "Password is too short" }
|
|
3757
3822
|
});
|
|
3758
3823
|
}
|
|
3759
|
-
const argon2id = new Argon2id3();
|
|
3760
3824
|
const dbUser = await ctx.context.internalAdapter.findUserByEmail(email);
|
|
3761
|
-
const hash = await
|
|
3825
|
+
const hash = await ctx.context.password.hash(password);
|
|
3762
3826
|
if (dbUser?.user) {
|
|
3763
3827
|
return ctx.json(null, {
|
|
3764
3828
|
status: 400,
|
|
@@ -3768,7 +3832,7 @@ var signUpEmail = createAuthEndpoint(
|
|
|
3768
3832
|
});
|
|
3769
3833
|
}
|
|
3770
3834
|
const createdUser = await ctx.context.internalAdapter.createUser({
|
|
3771
|
-
id:
|
|
3835
|
+
id: generateRandomString(32, alphabet("a-z", "0-9", "A-Z")),
|
|
3772
3836
|
email: email.toLowerCase(),
|
|
3773
3837
|
name,
|
|
3774
3838
|
image,
|
|
@@ -3777,7 +3841,7 @@ var signUpEmail = createAuthEndpoint(
|
|
|
3777
3841
|
updatedAt: /* @__PURE__ */ new Date()
|
|
3778
3842
|
});
|
|
3779
3843
|
await ctx.context.internalAdapter.linkAccount({
|
|
3780
|
-
id:
|
|
3844
|
+
id: generateRandomString(32, alphabet("a-z", "0-9", "A-Z")),
|
|
3781
3845
|
userId: createdUser.id,
|
|
3782
3846
|
providerId: "credential",
|
|
3783
3847
|
accountId: createdUser.id,
|
|
@@ -3793,6 +3857,18 @@ var signUpEmail = createAuthEndpoint(
|
|
|
3793
3857
|
ctx.context.secret,
|
|
3794
3858
|
ctx.context.authCookies.sessionToken.options
|
|
3795
3859
|
);
|
|
3860
|
+
if (ctx.context.options.emailAndPassword.sendEmailVerificationOnSignUp) {
|
|
3861
|
+
const token = await createEmailVerificationToken(
|
|
3862
|
+
ctx.context.secret,
|
|
3863
|
+
createdUser.email
|
|
3864
|
+
);
|
|
3865
|
+
const url = `${ctx.context.baseURL}/verify-email?token=${token}?callbackURL=${ctx.body.callbackURL}`;
|
|
3866
|
+
await ctx.context.options.emailAndPassword.sendVerificationEmail?.(
|
|
3867
|
+
createdUser.email,
|
|
3868
|
+
url,
|
|
3869
|
+
token
|
|
3870
|
+
);
|
|
3871
|
+
}
|
|
3796
3872
|
return ctx.json(
|
|
3797
3873
|
{
|
|
3798
3874
|
user: createdUser,
|
|
@@ -3820,11 +3896,11 @@ var username = () => {
|
|
|
3820
3896
|
"/sign-in/username",
|
|
3821
3897
|
{
|
|
3822
3898
|
method: "POST",
|
|
3823
|
-
body:
|
|
3824
|
-
username:
|
|
3825
|
-
password:
|
|
3826
|
-
dontRememberMe:
|
|
3827
|
-
callbackURL:
|
|
3899
|
+
body: z.object({
|
|
3900
|
+
username: z.string(),
|
|
3901
|
+
password: z.string(),
|
|
3902
|
+
dontRememberMe: z.boolean().optional(),
|
|
3903
|
+
callbackURL: z.string().optional()
|
|
3828
3904
|
})
|
|
3829
3905
|
},
|
|
3830
3906
|
async (ctx) => {
|
|
@@ -3837,11 +3913,10 @@ var username = () => {
|
|
|
3837
3913
|
}
|
|
3838
3914
|
]
|
|
3839
3915
|
});
|
|
3840
|
-
const argon2id = new Argon2id4();
|
|
3841
3916
|
if (!user) {
|
|
3842
|
-
await
|
|
3917
|
+
await ctx.context.password.hash(ctx.body.password);
|
|
3843
3918
|
ctx.context.logger.error("User not found", { username });
|
|
3844
|
-
throw new
|
|
3919
|
+
throw new APIError("UNAUTHORIZED", {
|
|
3845
3920
|
message: "Invalid email or password"
|
|
3846
3921
|
});
|
|
3847
3922
|
}
|
|
@@ -3859,24 +3934,24 @@ var username = () => {
|
|
|
3859
3934
|
]
|
|
3860
3935
|
});
|
|
3861
3936
|
if (!account) {
|
|
3862
|
-
throw new
|
|
3937
|
+
throw new APIError("UNAUTHORIZED", {
|
|
3863
3938
|
message: "Invalid email or password"
|
|
3864
3939
|
});
|
|
3865
3940
|
}
|
|
3866
3941
|
const currentPassword = account?.password;
|
|
3867
3942
|
if (!currentPassword) {
|
|
3868
3943
|
ctx.context.logger.error("Password not found", { username });
|
|
3869
|
-
throw new
|
|
3944
|
+
throw new APIError("UNAUTHORIZED", {
|
|
3870
3945
|
message: "Unexpected error"
|
|
3871
3946
|
});
|
|
3872
3947
|
}
|
|
3873
|
-
const validPassword = await
|
|
3948
|
+
const validPassword = await ctx.context.password.verify(
|
|
3874
3949
|
currentPassword,
|
|
3875
3950
|
ctx.body.password
|
|
3876
3951
|
);
|
|
3877
3952
|
if (!validPassword) {
|
|
3878
3953
|
ctx.context.logger.error("Invalid password");
|
|
3879
|
-
throw new
|
|
3954
|
+
throw new APIError("UNAUTHORIZED", {
|
|
3880
3955
|
message: "Invalid email or password"
|
|
3881
3956
|
});
|
|
3882
3957
|
}
|
|
@@ -3905,13 +3980,13 @@ var username = () => {
|
|
|
3905
3980
|
"/sign-up/username",
|
|
3906
3981
|
{
|
|
3907
3982
|
method: "POST",
|
|
3908
|
-
body:
|
|
3909
|
-
username:
|
|
3910
|
-
name:
|
|
3911
|
-
email:
|
|
3912
|
-
password:
|
|
3913
|
-
image:
|
|
3914
|
-
callbackURL:
|
|
3983
|
+
body: z.object({
|
|
3984
|
+
username: z.string().min(3).max(20),
|
|
3985
|
+
name: z.string(),
|
|
3986
|
+
email: z.string().email(),
|
|
3987
|
+
password: z.string(),
|
|
3988
|
+
image: z.string().optional(),
|
|
3989
|
+
callbackURL: z.string().optional()
|
|
3915
3990
|
})
|
|
3916
3991
|
},
|
|
3917
3992
|
async (ctx) => {
|
|
@@ -3959,9 +4034,6 @@ var username = () => {
|
|
|
3959
4034
|
}
|
|
3960
4035
|
};
|
|
3961
4036
|
};
|
|
3962
|
-
|
|
3963
|
-
// src/plugins/bearer/index.ts
|
|
3964
|
-
import { serializeSigned } from "better-call";
|
|
3965
4037
|
var bearer = () => {
|
|
3966
4038
|
return {
|
|
3967
4039
|
id: "bearer",
|
|
@@ -3992,15 +4064,7 @@ var bearer = () => {
|
|
|
3992
4064
|
}
|
|
3993
4065
|
};
|
|
3994
4066
|
};
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
getPasskeyActions,
|
|
3999
|
-
organization,
|
|
4000
|
-
passkey,
|
|
4001
|
-
passkeyClient,
|
|
4002
|
-
twoFactor,
|
|
4003
|
-
twoFactorClient,
|
|
4004
|
-
username
|
|
4005
|
-
};
|
|
4067
|
+
|
|
4068
|
+
export { access_exports as ac, bearer, getPasskeyActions, organization, passkey, passkeyClient, twoFactor, twoFactorClient, username };
|
|
4069
|
+
//# sourceMappingURL=plugins.js.map
|
|
4006
4070
|
//# sourceMappingURL=plugins.js.map
|