prostgles-server 4.2.202 → 4.2.204

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.
Files changed (95) hide show
  1. package/dist/Auth/AuthHandler.d.ts +9 -12
  2. package/dist/Auth/AuthHandler.d.ts.map +1 -1
  3. package/dist/Auth/AuthHandler.js +39 -170
  4. package/dist/Auth/AuthHandler.js.map +1 -1
  5. package/dist/Auth/AuthTypes.d.ts +37 -48
  6. package/dist/Auth/AuthTypes.d.ts.map +1 -1
  7. package/dist/Auth/endpoints/setCatchAllRequestHandler.d.ts +1 -2
  8. package/dist/Auth/endpoints/setCatchAllRequestHandler.d.ts.map +1 -1
  9. package/dist/Auth/endpoints/setCatchAllRequestHandler.js +4 -4
  10. package/dist/Auth/endpoints/setCatchAllRequestHandler.js.map +1 -1
  11. package/dist/Auth/endpoints/setConfirmEmailRequestHandler.d.ts +3 -5
  12. package/dist/Auth/endpoints/setConfirmEmailRequestHandler.d.ts.map +1 -1
  13. package/dist/Auth/endpoints/setConfirmEmailRequestHandler.js +4 -5
  14. package/dist/Auth/endpoints/setConfirmEmailRequestHandler.js.map +1 -1
  15. package/dist/Auth/endpoints/setLoginRequestHandler.d.ts +5 -6
  16. package/dist/Auth/endpoints/setLoginRequestHandler.d.ts.map +1 -1
  17. package/dist/Auth/endpoints/setLoginRequestHandler.js +5 -8
  18. package/dist/Auth/endpoints/setLoginRequestHandler.js.map +1 -1
  19. package/dist/Auth/endpoints/setMagicLinkRequestHandler.d.ts +2 -3
  20. package/dist/Auth/endpoints/setMagicLinkRequestHandler.d.ts.map +1 -1
  21. package/dist/Auth/endpoints/setMagicLinkRequestHandler.js +4 -4
  22. package/dist/Auth/endpoints/setMagicLinkRequestHandler.js.map +1 -1
  23. package/dist/Auth/endpoints/setOAuthRequestHandlers.d.ts +5 -0
  24. package/dist/Auth/endpoints/setOAuthRequestHandlers.d.ts.map +1 -0
  25. package/dist/Auth/{authProviders/setOAuthProviders.js → endpoints/setOAuthRequestHandlers.js} +19 -15
  26. package/dist/Auth/endpoints/setOAuthRequestHandlers.js.map +1 -0
  27. package/dist/Auth/endpoints/setRegisterRequestHandler.d.ts +2 -2
  28. package/dist/Auth/endpoints/setRegisterRequestHandler.d.ts.map +1 -1
  29. package/dist/Auth/endpoints/setRegisterRequestHandler.js +26 -44
  30. package/dist/Auth/endpoints/setRegisterRequestHandler.js.map +1 -1
  31. package/dist/Auth/getClientAuth.d.ts +8 -0
  32. package/dist/Auth/getClientAuth.d.ts.map +1 -0
  33. package/dist/Auth/getClientAuth.js +76 -0
  34. package/dist/Auth/getClientAuth.js.map +1 -0
  35. package/dist/Auth/login.d.ts +5 -0
  36. package/dist/Auth/login.d.ts.map +1 -0
  37. package/dist/Auth/login.js +111 -0
  38. package/dist/Auth/login.js.map +1 -0
  39. package/dist/Auth/sendEmail.d.ts +3 -5
  40. package/dist/Auth/sendEmail.d.ts.map +1 -1
  41. package/dist/Auth/sendEmail.js +27 -2
  42. package/dist/Auth/sendEmail.js.map +1 -1
  43. package/dist/Auth/setupAuthRoutes.d.ts.map +1 -1
  44. package/dist/Auth/setupAuthRoutes.js +15 -9
  45. package/dist/Auth/setupAuthRoutes.js.map +1 -1
  46. package/dist/Auth/utils/getSidAndUserFromRequest.d.ts.map +1 -1
  47. package/dist/Auth/utils/getSidAndUserFromRequest.js +2 -1
  48. package/dist/Auth/utils/getSidAndUserFromRequest.js.map +1 -1
  49. package/dist/Auth/utils/throttledReject.d.ts +5 -0
  50. package/dist/Auth/utils/throttledReject.d.ts.map +1 -0
  51. package/dist/Auth/utils/throttledReject.js +34 -0
  52. package/dist/Auth/utils/throttledReject.js.map +1 -0
  53. package/dist/Auth/utils/upsertNamedExpressMiddleware.d.ts +6 -0
  54. package/dist/Auth/utils/upsertNamedExpressMiddleware.d.ts.map +1 -0
  55. package/dist/Auth/utils/upsertNamedExpressMiddleware.js +12 -0
  56. package/dist/Auth/utils/upsertNamedExpressMiddleware.js.map +1 -0
  57. package/dist/DBSchemaBuilder.js.map +1 -1
  58. package/dist/Prostgles.d.ts +1 -1
  59. package/dist/Prostgles.d.ts.map +1 -1
  60. package/dist/Prostgles.js +2 -2
  61. package/dist/Prostgles.js.map +1 -1
  62. package/dist/ProstglesTypes.d.ts +2 -2
  63. package/dist/ProstglesTypes.d.ts.map +1 -1
  64. package/lib/Auth/AuthHandler.ts +50 -218
  65. package/lib/Auth/AuthTypes.ts +72 -72
  66. package/lib/Auth/endpoints/setCatchAllRequestHandler.ts +8 -4
  67. package/lib/Auth/endpoints/setConfirmEmailRequestHandler.ts +9 -13
  68. package/lib/Auth/endpoints/setLoginRequestHandler.ts +8 -14
  69. package/lib/Auth/endpoints/setMagicLinkRequestHandler.ts +6 -6
  70. package/lib/Auth/{authProviders/setOAuthProviders.ts → endpoints/setOAuthRequestHandlers.ts} +24 -17
  71. package/lib/Auth/endpoints/setRegisterRequestHandler.ts +30 -54
  72. package/lib/Auth/getClientAuth.ts +100 -0
  73. package/lib/Auth/login.ts +139 -0
  74. package/lib/Auth/sendEmail.ts +31 -7
  75. package/lib/Auth/setupAuthRoutes.ts +22 -9
  76. package/lib/Auth/utils/getSidAndUserFromRequest.ts +2 -1
  77. package/lib/Auth/utils/throttledReject.ts +33 -0
  78. package/lib/Auth/utils/upsertNamedExpressMiddleware.ts +14 -0
  79. package/lib/DBSchemaBuilder.ts +2 -2
  80. package/lib/Prostgles.ts +1 -1
  81. package/lib/ProstglesTypes.ts +2 -2
  82. package/package.json +2 -2
  83. package/dist/Auth/authProviders/setEmailProvider.d.ts +0 -4
  84. package/dist/Auth/authProviders/setEmailProvider.d.ts.map +0 -1
  85. package/dist/Auth/authProviders/setEmailProvider.js +0 -26
  86. package/dist/Auth/authProviders/setEmailProvider.js.map +0 -1
  87. package/dist/Auth/authProviders/setOAuthProviders.d.ts +0 -5
  88. package/dist/Auth/authProviders/setOAuthProviders.d.ts.map +0 -1
  89. package/dist/Auth/authProviders/setOAuthProviders.js.map +0 -1
  90. package/dist/Auth/setAuthProviders.d.ts +0 -11
  91. package/dist/Auth/setAuthProviders.d.ts.map +0 -1
  92. package/dist/Auth/setAuthProviders.js +0 -41
  93. package/dist/Auth/setAuthProviders.js.map +0 -1
  94. package/lib/Auth/authProviders/setEmailProvider.ts +0 -26
  95. package/lib/Auth/setAuthProviders.ts +0 -47
@@ -1,35 +1,24 @@
1
- import {
2
- AnyObject,
3
- AuthFailure,
4
- AuthGuardLocation,
5
- AuthGuardLocationResponse,
6
- AuthResponse,
7
- AuthSocketSchema,
8
- CHANNELS,
9
- } from "prostgles-types";
1
+ import { AnyObject, AuthResponse, CHANNELS } from "prostgles-types";
10
2
  import { PRGLIOSocket } from "../DboBuilder/DboBuilder";
11
3
  import { DBOFullyTyped } from "../DBSchemaBuilder";
12
4
  import { removeExpressRoute } from "../FileManager/FileManager";
13
5
  import { DB, DBHandlerServer, Prostgles } from "../Prostgles";
14
6
  import {
15
- Auth,
7
+ AuthConfig,
16
8
  AuthClientRequest,
17
9
  AuthResult,
18
10
  AuthResultWithSID,
19
11
  BasicSession,
20
12
  ExpressReq,
21
- ExpressRes,
22
- LoginClientInfo,
23
- LoginParams,
24
- LoginResponse,
25
13
  } from "./AuthTypes";
26
- import { getProviders } from "./setAuthProviders";
14
+ import { LoginResponseHandler } from "./endpoints/setLoginRequestHandler";
15
+ import { getClientAuth } from "./getClientAuth";
16
+ import { login } from "./login";
27
17
  import { setupAuthRoutes } from "./setupAuthRoutes";
28
18
  import { getClientRequestIPsInfo } from "./utils/getClientRequestIPsInfo";
29
19
  import { getReturnUrl } from "./utils/getReturnUrl";
30
20
  import { getSidAndUserFromRequest } from "./utils/getSidAndUserFromRequest";
31
- import type { Response } from "express";
32
- import { LoginResponseHandler } from "./endpoints/setLoginRequestHandler";
21
+ import { throttledReject } from "./utils/throttledReject";
33
22
 
34
23
  export { getClientRequestIPsInfo };
35
24
  export const HTTP_FAIL_CODES = {
@@ -48,7 +37,7 @@ export const HTTP_SUCCESS_CODES = {
48
37
 
49
38
  export const AUTH_ROUTES_AND_PARAMS = {
50
39
  login: "/login",
51
- loginWithProvider: "/auth",
40
+ loginWithProvider: "/oauth",
52
41
  emailRegistration: "/register",
53
42
  returnUrlParamName: "returnURL",
54
43
  sidKeyName: "session_id",
@@ -62,7 +51,7 @@ export const AUTH_ROUTES_AND_PARAMS = {
62
51
 
63
52
  export class AuthHandler {
64
53
  protected readonly prostgles: Prostgles;
65
- protected readonly opts: Auth;
54
+ protected readonly opts: AuthConfig;
66
55
  dbo: DBHandlerServer;
67
56
  db: DB;
68
57
 
@@ -98,7 +87,7 @@ export class AuthHandler {
98
87
  isUserRoute = (pathname: string) => {
99
88
  const { login, logoutGetPath, magicLinksRoute, loginWithProvider } = AUTH_ROUTES_AND_PARAMS;
100
89
  const pubRoutes = [
101
- ...(this.opts.expressConfig?.publicRoutes || []),
90
+ ...(this.opts.loginSignupConfig?.publicRoutes || []),
102
91
  login,
103
92
  logoutGetPath,
104
93
  magicLinksRoute,
@@ -116,42 +105,43 @@ export class AuthHandler {
116
105
  ) => {
117
106
  const { sid, expires } = cookie;
118
107
  const { res, req } = r;
119
- if (sid) {
120
- const maxAgeOneDay = 60 * 60 * 24; // 24 hours;
121
- type CD = { maxAge: number } | { expires: Date };
122
- let cookieDuration: CD = {
123
- maxAge: maxAgeOneDay,
124
- };
125
- if (expires && Number.isFinite(expires) && !isNaN(+new Date(expires))) {
126
- // const maxAge = (+new Date(expires)) - Date.now();
127
- cookieDuration = { expires: new Date(expires) };
128
- const days = (+cookieDuration.expires - Date.now()) / (24 * 60 * 60e3);
129
- if (days >= 400) {
130
- console.warn(`Cookie expiration is higher than the Chrome 400 day limit: ${days}days`);
131
- }
132
- }
108
+ if (!sid) {
109
+ throw "no sid";
110
+ }
133
111
 
134
- const cookieOpts = {
135
- ...cookieDuration,
136
- httpOnly: true, // The cookie only accessible by the web server
137
- //signed: true // Indicates if the cookie should be signed
138
- secure: true,
139
- sameSite: "strict" as const,
140
- ...(this.opts.expressConfig?.cookieOptions || {}),
141
- };
142
- const cookieData = sid;
143
- res.cookie(this.sidKeyName, cookieData, cookieOpts);
144
- const successURL = getReturnUrl(req) || "/";
145
- res.redirect(successURL);
146
- } else {
147
- throw "no user or session";
112
+ const maxAgeOneDay = 60 * 60 * 24; // 24 hours;
113
+ type CD = { maxAge: number } | { expires: Date };
114
+ let cookieDuration: CD = {
115
+ maxAge: maxAgeOneDay,
116
+ };
117
+
118
+ if (expires && Number.isFinite(expires) && !isNaN(+new Date(expires))) {
119
+ cookieDuration = { expires: new Date(expires) };
120
+ const days = (+cookieDuration.expires - Date.now()) / (24 * 60 * 60e3);
121
+ if (days >= 400) {
122
+ console.warn(`Cookie expiration is higher than the Chrome 400 day limit: ${days}days`);
123
+ }
148
124
  }
125
+
126
+ const cookieOpts = {
127
+ ...cookieDuration,
128
+ // The cookie only accessible by the web server
129
+ httpOnly: true,
130
+ //signed: true
131
+ secure: true,
132
+ sameSite: "strict" as const,
133
+ ...(this.opts.loginSignupConfig?.cookieOptions ?? {}),
134
+ };
135
+ const cookieData = sid;
136
+ res.cookie(this.sidKeyName, cookieData, cookieOpts);
137
+ const successURL = getReturnUrl(req) || "/";
138
+ res.redirect(successURL);
149
139
  };
150
140
 
151
141
  getUserAndHandleError = async (localParams: AuthClientRequest): Promise<AuthResultWithSID> => {
152
142
  const sid = this.getSID(localParams);
153
143
  if (!sid) return { sid };
154
- const handlerError = (code: AuthFailure["code"]) => {
144
+ const handlerError = (code: AuthResponse.AuthFailure["code"]) => {
155
145
  if (localParams.httpReq) {
156
146
  localParams.res
157
147
  .status(HTTP_FAIL_CODES.BAD_REQUEST)
@@ -160,7 +150,7 @@ export class AuthHandler {
160
150
  throw code;
161
151
  };
162
152
  try {
163
- const userOrErrorCode = await this.throttledFunc(async () => {
153
+ const userOrErrorCode = await throttledReject(async () => {
164
154
  return this.opts.getUser(
165
155
  this.validateSid(sid),
166
156
  this.dbo as DBOFullyTyped,
@@ -186,7 +176,7 @@ export class AuthHandler {
186
176
  init = setupAuthRoutes.bind(this);
187
177
 
188
178
  destroy = () => {
189
- const app = this.opts.expressConfig?.app;
179
+ const app = this.opts.loginSignupConfig?.app;
190
180
  const {
191
181
  login,
192
182
  logoutGetPath,
@@ -211,111 +201,13 @@ export class AuthHandler {
211
201
  ]);
212
202
  };
213
203
 
214
- throttledFunc = <T>(func: () => Promise<T>, throttle = 500): Promise<T> => {
215
- return new Promise(async (resolve, reject) => {
216
- let result: T,
217
- error: any,
218
- finished = false;
219
-
220
- /**
221
- * Throttle reject response times to prevent timing attacks
222
- */
223
- const interval = setInterval(() => {
224
- if (finished) {
225
- clearInterval(interval);
226
- if (error) {
227
- reject(error);
228
- } else {
229
- resolve(result);
230
- }
231
- }
232
- }, throttle);
233
-
234
- try {
235
- result = await func();
236
- resolve(result);
237
- clearInterval(interval);
238
- } catch (err) {
239
- console.log(err);
240
- error = err;
241
- }
242
-
243
- finished = true;
244
- });
245
- };
246
-
247
- loginThrottledAndValidate = async (
248
- params: LoginParams,
249
- client: LoginClientInfo
250
- ): Promise<LoginResponse> => {
251
- if (!this.opts.login) throw "Auth login config missing";
252
- const { responseThrottle = 500 } = this.opts;
253
- return this.throttledFunc(async () => {
254
- const result = await this.opts.login?.(params, this.dbo as DBOFullyTyped, this.db, client);
255
-
256
- if (!result) {
257
- return "server-error";
258
- }
259
- if (typeof result === "string") return result;
260
-
261
- const { sid, expires } = result.session;
262
- if (!sid) {
263
- // return withServerError("Invalid sid");
264
- return "server-error";
265
- }
266
- if (sid && (typeof sid !== "string" || typeof expires !== "number")) {
267
- // return withServerError(
268
- // "Bad login result type. \nExpecting: undefined | null | { sid: string; expires: number }"
269
- // );
270
- return "server-error";
271
- }
272
- if (expires < Date.now()) {
273
- // return withServerError(
274
- // "auth.login() is returning an expired session. Can only login with a session.expires greater than Date.now()"
275
- // );
276
- return "server-error";
277
- }
278
-
279
- return result;
280
- }, responseThrottle);
281
- };
282
-
283
- loginThrottledAndSetCookie = async (
284
- req: ExpressReq,
285
- res: LoginResponseHandler,
286
- loginParams: LoginParams
287
- ) => {
288
- const start = Date.now();
289
- const errCodeOrSession = await this.loginThrottledAndValidate(
290
- loginParams,
291
- getClientRequestIPsInfo({ httpReq: req, res })
292
- );
293
- const loginResponse =
294
- typeof errCodeOrSession === "string" ?
295
- {
296
- session: undefined,
297
- response: { success: false, code: errCodeOrSession } as const,
298
- }
299
- : errCodeOrSession;
300
- await this.prostgles.opts.onLog?.({
301
- type: "auth",
302
- command: "login",
303
- success: !!loginResponse.session,
304
- duration: Date.now() - start,
305
- sid: loginResponse.session?.sid,
306
- socketId: undefined,
307
- });
308
- if (!loginResponse.session) {
309
- return res.status(HTTP_FAIL_CODES.BAD_REQUEST).json(loginResponse.response);
310
- }
311
- this.setCookieAndGoToReturnURLIFSet(loginResponse.session, { req, res });
312
- };
204
+ login = login.bind(this);
313
205
 
314
206
  /**
315
207
  * Will return first sid value found in:
316
- * Bearer header
317
- * http cookie
318
- * query params
208
+ * - Bearer header
209
+ * - http cookie
210
+ * - query params
319
211
  * Based on sid names in auth
320
212
  */
321
213
  getSID(maybeClientReq: AuthClientRequest | undefined): string | undefined {
@@ -385,7 +277,10 @@ export class AuthHandler {
385
277
  session: BasicSession | undefined
386
278
  ): boolean => {
387
279
  const hasExpired = Boolean(session && session.expires <= Date.now());
388
- if (this.opts.expressConfig?.publicRoutes && !this.opts.expressConfig.disableSocketAuthGuard) {
280
+ if (
281
+ this.opts.loginSignupConfig?.publicRoutes &&
282
+ !this.opts.loginSignupConfig.disableSocketAuthGuard
283
+ ) {
389
284
  const error = "Session has expired";
390
285
  if (hasExpired) {
391
286
  if (session?.onExpiration === "redirect")
@@ -399,68 +294,5 @@ export class AuthHandler {
399
294
  return Boolean(session && !hasExpired);
400
295
  };
401
296
 
402
- getClientAuth = async (
403
- clientReq: AuthClientRequest
404
- ): Promise<{ auth: AuthSocketSchema; userData: AuthResultWithSID }> => {
405
- let pathGuard = false;
406
- if (this.opts.expressConfig?.publicRoutes && !this.opts.expressConfig.disableSocketAuthGuard) {
407
- pathGuard = true;
408
-
409
- /**
410
- * Due to SPA nature of some clients, we need to check if the connected client ends up on a protected route
411
- */
412
- if (clientReq.socket) {
413
- const { socket } = clientReq;
414
- socket.removeAllListeners(CHANNELS.AUTHGUARD);
415
- socket.on(
416
- CHANNELS.AUTHGUARD,
417
- async (
418
- params: AuthGuardLocation,
419
- cb = (_err: any, _res?: AuthGuardLocationResponse) => {
420
- /** EMPTY */
421
- }
422
- ) => {
423
- try {
424
- const { pathname, origin } =
425
- typeof params === "string" ? (JSON.parse(params) as AuthGuardLocation) : params;
426
- if (pathname && typeof pathname !== "string") {
427
- console.warn("Invalid pathname provided for AuthGuardLocation: ", pathname);
428
- }
429
-
430
- /** These origins */
431
- const IGNORED_API_ORIGINS = ["file://"];
432
- if (
433
- !IGNORED_API_ORIGINS.includes(origin) &&
434
- pathname &&
435
- typeof pathname === "string" &&
436
- this.isUserRoute(pathname) &&
437
- !(await this.getUserFromRequest({ socket }))
438
- ) {
439
- cb(null, { shouldReload: true });
440
- } else {
441
- cb(null, { shouldReload: false });
442
- }
443
- } catch (err) {
444
- console.error("AUTHGUARD err: ", err);
445
- cb(err);
446
- }
447
- }
448
- );
449
- }
450
- }
451
-
452
- const userData = await this.getSidAndUserFromRequest(clientReq);
453
- const { email } = this.opts.expressConfig?.registrations ?? {};
454
- const auth: AuthSocketSchema = {
455
- providers: getProviders.bind(this)(),
456
- register: email && {
457
- type: email.signupType,
458
- url: AUTH_ROUTES_AND_PARAMS.emailRegistration,
459
- },
460
- user: userData.clientUser,
461
- loginType: email?.signupType ?? "withPassword",
462
- pathGuard,
463
- };
464
- return { auth, userData };
465
- };
297
+ getClientAuth = getClientAuth.bind(this);
466
298
  }
@@ -13,12 +13,12 @@ import type {
13
13
  import type { MicrosoftStrategyOptions } from "passport-microsoft";
14
14
  import {
15
15
  AnyObject,
16
- AuthFailure,
17
16
  AuthRequest,
18
17
  AuthResponse,
19
18
  FieldFilter,
20
19
  IdentityProvider,
21
20
  UserLike,
21
+ AuthSocketSchema,
22
22
  } from "prostgles-types";
23
23
  import { DBOFullyTyped } from "../DBSchemaBuilder";
24
24
  import { PRGLIOSocket } from "../DboBuilder/DboBuilderTypes";
@@ -96,58 +96,43 @@ export type Email = {
96
96
  attachments?: { filename: string; content: string }[] | Mail.Attachment[];
97
97
  };
98
98
 
99
- type EmailWithoutTo = Omit<Email, "to">;
100
-
101
- type MagicLinkAuthResponse =
102
- | AuthResponse.MagicLinkAuthFailure["code"]
103
- | { response: AuthResponse.MagicLinkAuthSuccess; email: EmailWithoutTo };
104
-
105
99
  type PasswordRegisterResponse =
106
- | AuthResponse.PasswordRegisterFailure["code"]
107
- | { response: AuthResponse.PasswordRegisterSuccess; email: EmailWithoutTo };
100
+ | AuthResponse.PasswordRegisterFailure
101
+ | AuthResponse.PasswordRegisterSuccess;
102
+
103
+ /**
104
+ * Users have to provide an email and a password.
105
+ * Account should be activated after email confirmation
106
+ */
107
+ export type SignupWithEmailAndPassword = {
108
+ /**
109
+ * Defaults to 8
110
+ */
111
+ minPasswordLength?: number;
108
112
 
109
- export type EmailProvider =
110
- | {
111
- signupType: "withMagicLink";
112
- onRegister: (data: {
113
- email: string;
114
- magicLinkUrlPath: string;
115
- clientInfo: LoginClientInfo;
116
- req: ExpressReq;
117
- }) => Awaitable<MagicLinkAuthResponse>;
118
- smtp: SMTPConfig;
119
- }
120
- | {
121
- /**
122
- * Users have to provide an email and a password.
123
- * Account should be activated after email confirmation
124
- */
125
- signupType: "withPassword";
126
- /**
127
- * Defaults to 8
128
- */
129
- minPasswordLength?: number;
130
- /**
131
- * Called when the user has registered
132
- */
133
- onRegister: (data: {
134
- email: string;
135
- password: string;
136
- confirmationUrlPath: string;
137
- clientInfo: LoginClientInfo;
138
- req: ExpressReq;
139
- }) => Awaitable<PasswordRegisterResponse>;
140
- smtp: SMTPConfig;
113
+ /**
114
+ * Called when the user has registered
115
+ */
116
+ onRegister: (data: {
117
+ email: string;
118
+ /**
119
+ * Password after validation
120
+ */
121
+ password: string;
122
+ clientInfo: LoginClientInfo;
123
+ confirmationUrlPath: string;
124
+ req: ExpressReq;
125
+ }) => Awaitable<PasswordRegisterResponse>;
141
126
 
142
- /**
143
- * Called after the user has clicked the URL to confirm their email address
144
- */
145
- onEmailConfirmation: (data: {
146
- confirmationCode: string;
147
- clientInfo: LoginClientInfo;
148
- req: ExpressReq;
149
- }) => Awaitable<AuthFailure["code"] | (AuthResponse.AuthSuccess & { redirect_to?: string })>;
150
- };
127
+ /**
128
+ * Called after the user has clicked the URL to confirm their email address
129
+ */
130
+ onEmailConfirmation: (data: {
131
+ confirmationCode: string;
132
+ clientInfo: LoginClientInfo;
133
+ req: ExpressReq;
134
+ }) => Awaitable<AuthResponse.AuthFailure | (AuthResponse.AuthSuccess & { redirect_to?: string })>;
135
+ };
151
136
 
152
137
  export type AuthProviderUserData =
153
138
  | {
@@ -185,10 +170,8 @@ export type RegistrationData =
185
170
  }
186
171
  | AuthProviderUserData;
187
172
 
188
- export type AuthRegistrationConfig<S> = {
189
- email?: EmailProvider;
190
-
191
- OAuthProviders?: ThirdPartyProviders;
173
+ export type LoginWithOAuthConfig<S> = {
174
+ OAuthProviders: ThirdPartyProviders;
192
175
 
193
176
  /**
194
177
  * Required for social login callback
@@ -205,7 +188,9 @@ export type AuthRegistrationConfig<S> = {
205
188
  req: ExpressReq;
206
189
  res: ExpressRes;
207
190
  clientInfo: LoginClientInfo;
208
- }) => Promise<{ error: string } | { ok: true }>;
191
+ }) => Promise<
192
+ AuthResponse.OAuthRegisterSuccess | AuthResponse.OAuthRegisterFailure | AuthResponse.AuthFailure
193
+ >;
209
194
 
210
195
  /**
211
196
  * Used to identify abuse
@@ -256,7 +241,7 @@ export type AuthResultWithSID<SU = SessionUser> =
256
241
  });
257
242
 
258
243
  export type AuthResult<SU = SessionUser> = SU | undefined;
259
- export type AuthResultOrError<SU = SessionUser> = AuthFailure["code"] | AuthResult<SU>;
244
+ export type AuthResultOrError<SU = SessionUser> = AuthResponse.AuthFailure["code"] | AuthResult<SU>;
260
245
 
261
246
  export type AuthRequestParams<S, SUser extends SessionUser> = {
262
247
  db: DB;
@@ -264,7 +249,7 @@ export type AuthRequestParams<S, SUser extends SessionUser> = {
264
249
  getUser: () => Promise<AuthResultWithSID<SUser>>;
265
250
  };
266
251
 
267
- export type Auth<S = void, SUser extends SessionUser = SessionUser> = {
252
+ export type AuthConfig<S = void, SUser extends SessionUser = SessionUser> = {
268
253
  /**
269
254
  * Name of the cookie or socket hadnshake query param that represents the session id.
270
255
  * Defaults to "session_id"
@@ -291,15 +276,7 @@ export type Auth<S = void, SUser extends SessionUser = SessionUser> = {
291
276
  * /logout
292
277
  * /magic-link/:id
293
278
  */
294
- expressConfig?: ExpressConfig<S, SUser>;
295
-
296
- login?: (
297
- params: LoginParams,
298
- dbo: DBOFullyTyped<S>,
299
- db: DB,
300
- client: LoginClientInfo
301
- ) => Awaitable<LoginResponse>;
302
- logout?: (sid: string | undefined, dbo: DBOFullyTyped<S>, db: DB) => Awaitable<any>;
279
+ loginSignupConfig?: LoginSignupConfig<S, SUser>;
303
280
 
304
281
  /**
305
282
  * Response time rounding in milliseconds to prevent timing attacks on login. Login response time should always be a multiple of this value. Defaults to 500 milliseconds
@@ -321,20 +298,23 @@ export type Auth<S = void, SUser extends SessionUser = SessionUser> = {
321
298
  export type LoginResponse =
322
299
  | {
323
300
  session: BasicSession;
324
- response?: AuthResponse.PasswordLoginSuccess | AuthResponse.MagicLinkAuthSuccess;
301
+ response?: AuthResponse.PasswordLoginSuccess | AuthResponse.OAuthRegisterSuccess;
325
302
  }
303
+ | {
304
+ session?: undefined;
305
+ response: AuthResponse.MagicLinkAuthSuccess;
306
+ }
307
+ | AuthResponse.OAuthRegisterFailure["code"]
326
308
  | AuthResponse.PasswordLoginFailure["code"]
327
309
  | AuthResponse.MagicLinkAuthFailure["code"];
328
310
 
329
311
  export type LoginParams =
330
312
  | ({
331
313
  type: "username";
332
- signupType: undefined | EmailProvider["signupType"];
333
- magicLinkUrlPath: undefined | string;
334
314
  } & AuthRequest.LoginData)
335
- | ({ type: "provider" } & AuthProviderUserData);
315
+ | ({ type: "OAuth" } & AuthProviderUserData);
336
316
 
337
- export type ExpressConfig<S, SUser extends SessionUser> = {
317
+ export type LoginSignupConfig<S, SUser extends SessionUser> = {
338
318
  /**
339
319
  * Express app instance. If provided Prostgles will attempt to set sidKeyName to user cookie
340
320
  */
@@ -386,7 +366,27 @@ export type ExpressConfig<S, SUser extends SessionUser> = {
386
366
  | { session?: undefined; response: AuthResponse.MagicLinkAuthFailure }
387
367
  >;
388
368
 
389
- registrations?: AuthRegistrationConfig<S>;
369
+ signupWithEmailAndPassword?: SignupWithEmailAndPassword;
370
+
371
+ loginWithOAuth?: LoginWithOAuthConfig<S>;
372
+
373
+ /**
374
+ * Used to hint to the client which login mode is available
375
+ * Defaults to username and password
376
+ */
377
+ localLoginMode?: AuthSocketSchema["loginType"];
378
+
379
+ /**
380
+ * If provided then the user will be able to login with a username and password
381
+ */
382
+ login: (
383
+ params: LoginParams,
384
+ dbo: DBOFullyTyped<S>,
385
+ db: DB,
386
+ client: LoginClientInfo
387
+ ) => Awaitable<LoginResponse>;
388
+
389
+ logout: (sid: string | undefined, dbo: DBOFullyTyped<S>, db: DB) => Awaitable<void>;
390
390
  };
391
391
 
392
392
  type ExpressMiddleware<S, SUser extends SessionUser> = (
@@ -3,14 +3,19 @@ import { AuthClientRequest } from "../AuthTypes";
3
3
  import { AUTH_ROUTES_AND_PARAMS, AuthHandler, HTTP_FAIL_CODES } from "../AuthHandler";
4
4
  import { getReturnUrl } from "../utils/getReturnUrl";
5
5
  import { DBOFullyTyped } from "../../DBSchemaBuilder";
6
+ import { throttledReject } from "../utils/throttledReject";
6
7
 
7
8
  export function setCatchAllRequestHandler(this: AuthHandler, app: e.Express) {
8
9
  const onLogout = async (req: Request, res: Response) => {
9
10
  const sid = this.validateSid(req.cookies?.[this.sidKeyName]);
10
11
  if (sid) {
11
12
  try {
12
- await this.throttledFunc(() => {
13
- return this.opts.logout?.(req.cookies?.[this.sidKeyName], this.dbo as any, this.db);
13
+ await throttledReject(async () => {
14
+ return this.opts.loginSignupConfig?.logout(
15
+ req.cookies?.[this.sidKeyName],
16
+ this.dbo as DBOFullyTyped,
17
+ this.db
18
+ );
14
19
  });
15
20
  } catch (err) {
16
21
  console.error(err);
@@ -20,7 +25,7 @@ export function setCatchAllRequestHandler(this: AuthHandler, app: e.Express) {
20
25
  };
21
26
 
22
27
  const requestHandler: RequestHandler = async (req, res, next) => {
23
- const { onGetRequestOK } = this.opts.expressConfig ?? {};
28
+ const { onGetRequestOK } = this.opts.loginSignupConfig ?? {};
24
29
  const clientReq: AuthClientRequest = { httpReq: req, res };
25
30
  const getUser = async () => {
26
31
  const userOrCode = await this.getUserAndHandleError(clientReq);
@@ -103,5 +108,4 @@ export function setCatchAllRequestHandler(this: AuthHandler, app: e.Express) {
103
108
  };
104
109
 
105
110
  app.get(AUTH_ROUTES_AND_PARAMS.catchAll, requestHandler);
106
- return requestHandler;
107
111
  }
@@ -1,21 +1,19 @@
1
1
  import type { Request, Response } from "express";
2
- import { AuthFailure, AuthResponse } from "prostgles-types";
2
+ import e from "express";
3
+ import { AuthResponse } from "prostgles-types";
3
4
  import { AUTH_ROUTES_AND_PARAMS, AuthHandler, HTTP_FAIL_CODES } from "../AuthHandler";
4
- import { AuthRegistrationConfig } from "../AuthTypes";
5
+ import { SignupWithEmailAndPassword } from "../AuthTypes";
5
6
  import { getClientRequestIPsInfo } from "../utils/getClientRequestIPsInfo";
6
- import e from "express";
7
+ import { throttledReject } from "../utils/throttledReject";
7
8
 
8
9
  export function setConfirmEmailRequestHandler(
9
10
  this: AuthHandler,
10
- emailAuthConfig: Extract<
11
- Required<AuthRegistrationConfig<void>>["email"],
12
- { signupType: "withPassword" }
13
- >,
11
+ emailAuthConfig: SignupWithEmailAndPassword,
14
12
  app: e.Express
15
13
  ) {
16
14
  const requestHandler = async (
17
15
  req: Request,
18
- res: Response<AuthFailure | AuthResponse.AuthSuccess>
16
+ res: Response<AuthResponse.AuthFailure | AuthResponse.AuthSuccess>
19
17
  ) => {
20
18
  const { id } = req.params;
21
19
  try {
@@ -23,17 +21,15 @@ export function setConfirmEmailRequestHandler(
23
21
  return res.send({ success: false, code: "something-went-wrong", message: "Invalid code" });
24
22
  }
25
23
  const { httpReq, ...clientInfo } = getClientRequestIPsInfo({ httpReq: req, res });
26
- const response = await this.throttledFunc(async () =>
24
+ const response = await throttledReject(async () =>
27
25
  emailAuthConfig.onEmailConfirmation({
28
26
  confirmationCode: id,
29
27
  clientInfo,
30
28
  req: httpReq,
31
29
  })
32
30
  );
33
- if (typeof response === "string") {
34
- return res
35
- .status(HTTP_FAIL_CODES.BAD_REQUEST)
36
- .json({ success: false, code: "something-went-wrong" });
31
+ if (!response.success) {
32
+ return res.status(HTTP_FAIL_CODES.BAD_REQUEST).json(response);
37
33
  }
38
34
 
39
35
  /**