@arkstack/auth 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,85 +1,321 @@
1
1
  /// <reference path="./app.d.ts" />
2
2
  import { Exception } from "@arkstack/common";
3
- import { Request, RequestSource, Response, ResponseSource } from "@arkstack/http";
3
+ import { Request, RequestSource, Response, ResponseSource, Session } from "@arkstack/http";
4
+ import * as _$otpauth from "otpauth";
4
5
  import { Model } from "@arkstack/database";
6
+ import { User as User$1 } from "@app/models/User";
5
7
 
6
8
  //#region src/Contracts/PersonalAccessToken.d.ts
7
9
  declare abstract class PersonalAccessToken extends Model {
8
- id: number;
10
+ [key: string]: any;
9
11
  name: string;
10
12
  token: string;
11
13
  abilities: string[];
12
- userId: number;
14
+ userId: never;
13
15
  createdAt: Date;
14
16
  expiresAt: Date | null;
15
17
  lastUsedAt: Date | null;
16
18
  deviceInfo: Record<string, unknown> | null;
17
19
  }
18
20
  //#endregion
19
- //#region src/CurrentSession.d.ts
20
- declare class CurrentSession {
21
+ //#region src/AuthSession.d.ts
22
+ /**
23
+ * Represents an authenticated user session.
24
+ *
25
+ * @author 3m1n3nc3
26
+ */
27
+ declare class AuthSession extends Session {
21
28
  private auth;
22
- constructor(auth: AuthContract);
23
- destroy(): Promise<void>;
29
+ constructor(auth: AuthContract, current?: Session | undefined);
30
+ /**
31
+ * Destroy the current session
32
+ *
33
+ * @returns
34
+ */
35
+ destroy(): Promise<this>;
36
+ /**
37
+ * Get the current auth session token
38
+ *
39
+ * @returns
40
+ */
24
41
  token(): Promise<PersonalAccessToken | null>;
25
42
  }
26
43
  //#endregion
27
- //#region src/Contracts/User.d.ts
28
- declare abstract class User extends Model {
29
- id: number;
30
- email: string;
31
- name: string;
32
- password: string;
33
- createdAt: Date;
34
- updatedAt: Date;
35
- protected static table?: string | undefined;
36
- }
37
- //#endregion
38
44
  //#region src/Contracts/AuthContract.d.ts
45
+ /**
46
+ * The Auth class provides methods for user authentication, including verifying
47
+ * credentials, logging in, logging out, and managing personal access tokens.
48
+ *
49
+ * @author Legacy (3m1n3nc3)
50
+ */
39
51
  declare abstract class AuthContract {
40
- abstract setRequest(req: Request<User> | RequestSource<User>): this;
41
- abstract getRequest(): Request<User> | undefined;
42
- abstract user(): User | null;
52
+ /**
53
+ * Set the current HTTP request instance being processed.
54
+ *
55
+ * @param req The HTTP request instance to be set.
56
+ * @returns The Auth instance itself for method chaining.
57
+ */
58
+ abstract setRequest(req: Request<User$1> | RequestSource<User$1>): this;
59
+ /**
60
+ * Get the current HTTP request instance being processed, which may contain
61
+ * user information and other request-specific data relevant to authentication operations.
62
+ *
63
+ * @returns The current HTTP request instance or undefined if not set.
64
+ */
65
+ abstract getRequest(): Request<User$1> | undefined;
66
+ /**
67
+ * Get the currently authenticated user
68
+ *
69
+ * @returns The currently authenticated user or null if not authenticated.
70
+ */
71
+ abstract user(): User$1 | null;
72
+ /**
73
+ * Verify user credentials
74
+ *
75
+ * @param email The email address of the user.
76
+ * @param password The password of the user.
77
+ * @returns A boolean indicating whether the credentials are valid.
78
+ */
43
79
  abstract verify(email: string, password: string): Promise<boolean>;
44
- abstract attempt(email: string, password: string): Promise<User>;
80
+ /**
81
+ * Attempt to authenticate a user with the given email and password.
82
+ *
83
+ * @param email
84
+ * @param password
85
+ * @returns
86
+ */
87
+ abstract attempt(email: string, password: string): Promise<User$1>;
88
+ /**
89
+ * Login a user and create a personal access token
90
+ *
91
+ * @param email
92
+ * @param password
93
+ * @returns
94
+ */
45
95
  abstract login(email: string, password: string): Promise<PersonalAccessToken>;
46
- abstract createTemporaryToken(user: User, purpose: string, expiresIn?: string): Promise<string>;
47
- abstract authorizeTemporaryToken(token: string, purpose: string): Promise<User>;
96
+ /**
97
+ * Create a temporary token for a user with a specific purpose, such as
98
+ * two-factor authentication.
99
+ *
100
+ * @param user
101
+ * @param purpose
102
+ * @param expiresIn
103
+ * @returns
104
+ */
105
+ abstract createTemporaryToken(user: User$1, purpose: string, expiresIn?: string): Promise<string>;
106
+ /**
107
+ * Authorize a temporary token and return the associated user if the token is
108
+ * valid and matches the expected purpose.
109
+ *
110
+ * @param token
111
+ * @param purpose
112
+ * @returns
113
+ */
114
+ abstract authorizeTemporaryToken(token: string, purpose: string): Promise<User$1>;
115
+ /**
116
+ * Logout the currently authenticated user and delete all their personal access tokens
117
+ *
118
+ * @param token
119
+ * @returns
120
+ */
48
121
  abstract logout(token?: string | PersonalAccessToken): Promise<void>;
122
+ /**
123
+ * Check if the user is authenticated
124
+ *
125
+ * @returns
126
+ */
49
127
  abstract check(): Promise<boolean>;
50
- abstract currentSession(): CurrentSession;
51
- abstract create(user: User): Promise<PersonalAccessToken>;
52
- abstract authorizeToken(token: string): Promise<User>;
128
+ /**
129
+ * Get the current session's personal access token
130
+ *
131
+ * @returns
132
+ */
133
+ abstract session(): AuthSession;
134
+ /**
135
+ * Create a personal access token for a user
136
+ *
137
+ * @param user
138
+ * @returns
139
+ */
140
+ abstract create(user: User$1): Promise<PersonalAccessToken>;
141
+ /**
142
+ * Authorize a token and return the associated user
143
+ *
144
+ * @param token
145
+ * @returns
146
+ */
147
+ abstract authorizeToken(token: string): Promise<User$1>;
53
148
  }
54
149
  //#endregion
55
150
  //#region src/Auth.d.ts
151
+ /**
152
+ * The Auth class provides methods for user authentication, including verifying
153
+ * credentials, logging in, logging out, and managing personal access tokens.
154
+ *
155
+ * @author Legacy (3m1n3nc3)
156
+ */
56
157
  declare class Auth extends AuthContract {
57
158
  #private;
58
- protected static req?: Request<User>;
159
+ protected static req?: Request<User$1>;
59
160
  private configuredSecret?;
60
- constructor(secret?: string, req?: Request<User> | RequestSource<User>);
161
+ constructor(secret?: string, req?: Request<User$1> | RequestSource<User$1>);
162
+ /**
163
+ * Create a new instance of the Auth class with an optional secret for JWT
164
+ * signing and verification.
165
+ *
166
+ * @param secret The secret key used for signing and verifying JWTs.
167
+ * @returns A new instance of the Auth class.
168
+ */
61
169
  static make(secret?: string): Auth;
62
- static setRequest(req: Request<User> | RequestSource<User>): typeof Auth;
63
- setRequest(req: Request<User> | RequestSource<User>): this;
64
- getRequest(): Request<User> | undefined;
65
- user(): User | null;
170
+ /**
171
+ * Set the current HTTP request instance being processed.
172
+ *
173
+ * @param req The HTTP request instance to be set.
174
+ * @returns The Auth class itself for method chaining.
175
+ */
176
+ static setRequest(req: Request<User$1> | RequestSource<User$1>): typeof Auth;
177
+ /**
178
+ * Set the current HTTP request instance being processed.
179
+ *
180
+ * @param req The HTTP request instance to be set.
181
+ * @returns The Auth instance itself for method chaining.
182
+ */
183
+ setRequest(req: Request<User$1> | RequestSource<User$1>): this;
184
+ /**
185
+ * Get the current HTTP request instance being processed, which may contain
186
+ * user information and other request-specific data relevant to authentication operations.
187
+ *
188
+ * @returns The current HTTP request instance or undefined if not set.
189
+ */
190
+ getRequest(): Request<User$1> | undefined;
191
+ /**
192
+ * Get the currently authenticated user
193
+ *
194
+ * @returns The currently authenticated user or null if not authenticated.
195
+ */
196
+ user(): User$1 | null;
197
+ /**
198
+ * Verify user credentials
199
+ *
200
+ * @param email The email address of the user.
201
+ * @param password The password of the user.
202
+ * @returns A boolean indicating whether the credentials are valid.
203
+ */
66
204
  verify(email: string, password: string): Promise<boolean>;
67
- attempt(email: string, password: string): Promise<User>;
205
+ /**
206
+ * Attempt to authenticate a user with the given email and password.
207
+ *
208
+ * @param email
209
+ * @param password
210
+ * @returns
211
+ */
212
+ attempt(email: string, password: string): Promise<User$1>;
213
+ /**
214
+ * Login a user and create a personal access token
215
+ *
216
+ * @param email
217
+ * @param password
218
+ * @returns
219
+ */
68
220
  login(email: string, password: string): Promise<PersonalAccessToken>;
69
- createTemporaryToken(user: User, purpose: string, expiresIn?: string): Promise<string>;
70
- authorizeTemporaryToken(token: string, purpose: string): Promise<User>;
221
+ /**
222
+ * Create a temporary token for a user with a specific purpose, such as
223
+ * two-factor authentication.
224
+ *
225
+ * @param user
226
+ * @param purpose
227
+ * @param expiresIn
228
+ * @returns
229
+ */
230
+ createTemporaryToken(user: User$1, purpose: string, expiresIn?: string): Promise<string>;
231
+ /**
232
+ * Authorize a temporary token and return the associated user if the token is
233
+ * valid and matches the expected purpose.
234
+ *
235
+ * @param token
236
+ * @param purpose
237
+ * @returns
238
+ */
239
+ authorizeTemporaryToken(token: string, purpose: string): Promise<User$1>;
240
+ /**
241
+ * Logout the currently authenticated user and delete all their personal access tokens
242
+ *
243
+ * @param token
244
+ * @returns
245
+ */
71
246
  logout(token?: string | PersonalAccessToken): Promise<void>;
247
+ /**
248
+ * Check if the user is authenticated
249
+ *
250
+ * @returns
251
+ */
72
252
  check(): Promise<boolean>;
73
- currentSession(): CurrentSession;
74
- create(user: User): Promise<PersonalAccessToken>;
253
+ /**
254
+ * Get the current session's personal access token
255
+ *
256
+ * @returns
257
+ */
258
+ session(): AuthSession;
259
+ /**
260
+ * Create a personal access token for a user
261
+ *
262
+ * @param user
263
+ * @returns
264
+ */
265
+ create(user: User$1): Promise<PersonalAccessToken>;
266
+ /**
267
+ * Create or replace the personal access token for the same user and device
268
+ * while keeping a single active session record for that device.
269
+ *
270
+ * @param user The authenticated user.
271
+ * @param token The new bearer token to persist.
272
+ * @param deviceInfo The current request's device information.
273
+ */
75
274
  private upsertDeviceToken;
76
- authorizeToken(token: string): Promise<User>;
275
+ /**
276
+ * Authorize a token and return the associated user
277
+ *
278
+ * @param token
279
+ * @returns
280
+ */
281
+ authorizeToken(token: string): Promise<User$1>;
282
+ /**
283
+ * Create a JWT token
284
+ *
285
+ * @param payload
286
+ * @returns
287
+ */
77
288
  private createJWT;
289
+ /**
290
+ * Verify a JWT token
291
+ *
292
+ * @param token
293
+ * @returns
294
+ */
78
295
  private verifyJWT;
79
296
  private getSecret;
297
+ private setAuthenticated;
298
+ /**
299
+ * Update the last used timestamp and device information of a personal
300
+ * access token to keep the session active and reflect the latest device details.
301
+ *
302
+ * @param pat The personal access token to update.
303
+ * @returns A promise that resolves when the update is complete.
304
+ */
80
305
  private touchSession;
81
306
  }
82
307
  //#endregion
308
+ //#region src/utils.d.ts
309
+ /**
310
+ * Create a new instance of the Auth class with an optional secret for JWT
311
+ * signing and verification.
312
+ *
313
+ * @param secret — The secret key used for signing and verifying JWTs.
314
+ *
315
+ * @returns — A new instance of the Auth class.
316
+ */
317
+ declare const auth: (secret?: string | undefined) => Auth;
318
+ //#endregion
83
319
  //#region src/types/Session.d.ts
84
320
  interface SessionDeviceInfo extends Record<string, unknown> {
85
321
  browser: string | null;
@@ -93,7 +329,7 @@ interface SessionDeviceInfo extends Record<string, unknown> {
93
329
  ipAddress: string | null;
94
330
  userAgent: string | null;
95
331
  }
96
- type AuthAgentPayload = {
332
+ type DeviceAgentPayload = {
97
333
  deviceName?: string;
98
334
  manufacturer?: string;
99
335
  model?: string;
@@ -106,398 +342,268 @@ type AuthAgentPayload = {
106
342
  //#region src/SessionDevice.d.ts
107
343
  declare class SessionDevice {
108
344
  private static readonly uniqueIdentityFields;
345
+ /**
346
+ * Extracts device information from the incoming request to build a SessionDeviceInfo object.
347
+ *
348
+ * @param req The incoming HTTP request object.
349
+ * @returns A SessionDeviceInfo object containing information about the client's device.
350
+ */
109
351
  static fromRequest(req?: Request): SessionDeviceInfo;
352
+ /**
353
+ * Generates a human-readable display name for the device based on available information.
354
+ *
355
+ * @param deviceInfo A record containing device information.
356
+ * @returns A string representing the display name of the device.
357
+ */
110
358
  static getDisplayName(deviceInfo?: Record<string, unknown> | null): string;
359
+ /**
360
+ * Builds a stable device key for matching previously issued sessions to the
361
+ * current request device.
362
+ *
363
+ * @param deviceInfo A record containing device information.
364
+ * @returns A normalized device key or null when there is not enough signal.
365
+ */
111
366
  static getUniqueKey(deviceInfo?: Record<string, unknown> | null): string | null;
367
+ /**
368
+ * Determines whether two device payloads represent the same device.
369
+ *
370
+ * @param left The first device payload.
371
+ * @param right The second device payload.
372
+ * @returns True when both payloads resolve to the same device key.
373
+ */
112
374
  static matches(left?: Record<string, unknown> | null, right?: Record<string, unknown> | null): boolean;
113
- private static readUserAgent;
114
- private static readString;
115
- private static readAuthAgent;
116
- private static normalizeDeviceType;
117
- private static detectIpAddress;
118
- private static detectBrowser;
119
- private static detectOs;
120
- private static detectDeviceType;
121
- }
122
- //#endregion
123
- //#region ../../node_modules/.pnpm/otpauth@9.5.1/node_modules/otpauth/dist/otpauth.d.ts
124
- /**
125
- * OTP secret key.
126
- */
127
- declare class Secret {
128
375
  /**
129
- * Converts a Latin-1 string to a Secret object.
130
- * @param {string} str Latin-1 string.
131
- * @returns {Secret} Secret object.
376
+ * Safely reads the user agent string from the request headers.
377
+ *
378
+ * @param req
379
+ * @returns
132
380
  */
133
- static fromLatin1(str: string): Secret;
381
+ private static readUserAgent;
134
382
  /**
135
- * Converts an UTF-8 string to a Secret object.
136
- * @param {string} str UTF-8 string.
137
- * @returns {Secret} Secret object.
383
+ * Safely reads a string value, ensuring it's a non-empty string or returns null.
384
+ *
385
+ * @param value
386
+ * @returns
138
387
  */
139
- static fromUTF8(str: string): Secret;
388
+ private static readString;
140
389
  /**
141
- * Converts a base32 string to a Secret object.
142
- * @param {string} str Base32 string.
143
- * @returns {Secret} Secret object.
390
+ * Reads a specific device-related header from the request
391
+ *
392
+ * @param req
393
+ * @param headerName
394
+ * @returns
144
395
  */
145
- static fromBase32(str: string): Secret;
396
+ private static readDeviceAgent;
397
+ private static normalizeDeviceType;
146
398
  /**
147
- * Converts a hexadecimal string to a Secret object.
148
- * @param {string} str Hexadecimal string.
149
- * @returns {Secret} Secret object.
399
+ * Detects the client's IP address from the request, considering common headers set by proxies.
400
+ *
401
+ * @param req
402
+ * @returns
150
403
  */
151
- static fromHex(str: string): Secret;
404
+ private static detectIpAddress;
152
405
  /**
153
- * Creates a secret key object.
154
- * @param {Object} [config] Configuration options.
155
- * @param {ArrayBufferLike} [config.buffer] Secret key buffer.
156
- * @param {number} [config.size=20] Number of random bytes to generate, ignored if 'buffer' is provided.
406
+ * Detects the browser from the user agent string.
407
+ *
408
+ * @param userAgent
409
+ * @returns
157
410
  */
158
- constructor({
159
- buffer,
160
- size
161
- }?: {
162
- buffer?: ArrayBufferLike | undefined;
163
- size?: number | undefined;
164
- });
411
+ private static detectBrowser;
165
412
  /**
166
- * Secret key.
167
- * @type {Uint8Array}
168
- * @readonly
413
+ * Detects the operating system from the user agent string.
414
+ *
415
+ * @param userAgent
416
+ * @returns
169
417
  */
170
- readonly bytes: Uint8Array;
418
+ private static detectOs;
171
419
  /**
172
- * Secret key buffer.
173
- * @deprecated For backward compatibility, the "bytes" property should be used instead.
174
- * @type {ArrayBufferLike}
420
+ * Detects the device type from the user agent string.
421
+ *
422
+ * @param userAgent
423
+ * @returns
175
424
  */
176
- get buffer(): ArrayBufferLike;
425
+ private static detectDeviceType;
426
+ }
427
+ //#endregion
428
+ //#region src/types/TwoFactor.d.ts
429
+ type TwoFactorMethod = 'authenticator' | 'sms';
430
+ type SmsCodePurpose = 'setup' | 'login';
431
+ type TwoFactorSetup = {
432
+ secret: string;
433
+ otpauthUrl: string;
434
+ };
435
+ type TwoFactorStatus = {
436
+ enabled: boolean;
437
+ enabledAt: string | null;
438
+ method: TwoFactorMethod | null;
439
+ recoveryCodesRemaining: number;
440
+ };
441
+ type IssuedSmsCode = {
442
+ code: string;
443
+ expiresAt: Date;
444
+ purpose: SmsCodePurpose;
445
+ };
446
+ //#endregion
447
+ //#region src/TwoFactor.d.ts
448
+ declare class TwoFactor {
449
+ static smsCodeTtlMinutes: number;
450
+ private static getModel;
451
+ private static getRecord;
452
+ private static upsert;
453
+ static normalizeMethod(method?: string | null): TwoFactorMethod | null;
454
+ static maskPhone(phone?: string | null): string | null;
177
455
  /**
178
- * Latin-1 string representation of secret key.
179
- * @type {string}
456
+ * Build the account label used inside the OTP URI.
457
+ *
458
+ * @param user
459
+ * @returns
180
460
  */
181
- get latin1(): string;
461
+ static getLabel(user: User$1): string;
182
462
  /**
183
- * UTF-8 string representation of secret key.
184
- * @type {string}
463
+ * Create the per-user TOTP instance for setup and verification.
464
+ *
465
+ * @param user
466
+ * @param secret
467
+ * @returns
185
468
  */
186
- get utf8(): string;
469
+ static getTotp(user: User$1, secret: string): _$otpauth.TOTP;
187
470
  /**
188
- * Base32 string representation of secret key.
189
- * @type {string}
471
+ * Generate a new shared secret for authenticator-based 2FA.
472
+ *
473
+ * @returns The generated secret in base32 format.
190
474
  */
191
- get base32(): string;
475
+ static generateSecret(size?: number): string;
192
476
  /**
193
- * Hexadecimal string representation of secret key.
194
- * @type {string}
477
+ * Build the setup payload returned to the client.
478
+ *
479
+ * @param user The user for whom the setup is being created.
480
+ * @param secret Optional existing secret to use for the setup.
481
+ * @returns An object containing the secret and the OTPAuth URL.
195
482
  */
196
- get hex(): string;
197
- }
198
- /**
199
- * HOTP: An HMAC-based One-time Password Algorithm.
200
- * @see [RFC 4226](https://datatracker.ietf.org/doc/html/rfc4226)
201
- */
202
- /**
203
- * TOTP: Time-Based One-Time Password Algorithm.
204
- * @see [RFC 6238](https://datatracker.ietf.org/doc/html/rfc6238)
205
- */
206
- declare class TOTP {
207
- /**
208
- * Default configuration.
209
- * @type {{
210
- * issuer: string,
211
- * label: string,
212
- * issuerInLabel: boolean,
213
- * algorithm: string,
214
- * digits: number,
215
- * period: number
216
- * window: number
217
- * }}
218
- */
219
- static get defaults(): {
220
- issuer: string;
221
- label: string;
222
- issuerInLabel: boolean;
223
- algorithm: string;
224
- digits: number;
225
- period: number;
226
- window: number;
227
- };
483
+ static createSetup(user: User$1, secret?: string): TwoFactorSetup;
228
484
  /**
229
- * Calculates the counter. i.e. the number of periods since timestamp 0.
230
- * @param {Object} [config] Configuration options.
231
- * @param {number} [config.period=30] Token time-step duration.
232
- * @param {number} [config.timestamp=Date.now] Timestamp value in milliseconds.
233
- * @returns {number} Counter.
234
- */
235
- static counter({
236
- period,
237
- timestamp
238
- }?: {
239
- period?: number | undefined;
240
- timestamp?: number | undefined;
241
- }): number;
242
- /**
243
- * Calculates the remaining time in milliseconds until the next token is generated.
244
- * @param {Object} [config] Configuration options.
245
- * @param {number} [config.period=30] Token time-step duration.
246
- * @param {number} [config.timestamp=Date.now] Timestamp value in milliseconds.
247
- * @returns {number} counter.
248
- */
249
- static remaining({
250
- period,
251
- timestamp
252
- }?: {
253
- period?: number | undefined;
254
- timestamp?: number | undefined;
255
- }): number;
256
- /**
257
- * Generates a TOTP token.
258
- * @param {Object} config Configuration options.
259
- * @param {Secret} config.secret Secret key.
260
- * @param {string} [config.algorithm='SHA1'] HMAC hashing algorithm.
261
- * @param {number} [config.digits=6] Token length.
262
- * @param {number} [config.period=30] Token time-step duration.
263
- * @param {number} [config.timestamp=Date.now] Timestamp value in milliseconds.
264
- * @param {(algorithm: string, key: Uint8Array, message: Uint8Array) => Uint8Array} [config.hmac] Custom HMAC function.
265
- * @returns {string} Token.
266
- */
267
- static generate({
268
- secret,
269
- algorithm,
270
- digits,
271
- period,
272
- timestamp,
273
- hmac
274
- }: {
275
- secret: Secret;
276
- algorithm?: string | undefined;
277
- digits?: number | undefined;
278
- period?: number | undefined;
279
- timestamp?: number | undefined;
280
- hmac?: ((algorithm: string, key: Uint8Array, message: Uint8Array) => Uint8Array) | undefined;
281
- }): string;
282
- /**
283
- * Validates a TOTP token.
284
- * @param {Object} config Configuration options.
285
- * @param {string} config.token Token value.
286
- * @param {Secret} config.secret Secret key.
287
- * @param {string} [config.algorithm='SHA1'] HMAC hashing algorithm.
288
- * @param {number} [config.digits=6] Token length.
289
- * @param {number} [config.period=30] Token time-step duration.
290
- * @param {number} [config.timestamp=Date.now] Timestamp value in milliseconds.
291
- * @param {number} [config.window=1] Window of counter values to test.
292
- * @param {(algorithm: string, key: Uint8Array, message: Uint8Array) => Uint8Array} [config.hmac] Custom HMAC function.
293
- * @returns {number|null} Token delta or null if it is not found in the search window, in which case it should be considered invalid.
294
- */
295
- static validate({
296
- token,
297
- secret,
298
- algorithm,
299
- digits,
300
- period,
301
- timestamp,
302
- window,
303
- hmac
304
- }: {
305
- token: string;
306
- secret: Secret;
307
- algorithm?: string | undefined;
308
- digits?: number | undefined;
309
- period?: number | undefined;
310
- timestamp?: number | undefined;
311
- window?: number | undefined;
312
- hmac?: ((algorithm: string, key: Uint8Array, message: Uint8Array) => Uint8Array) | undefined;
313
- }): number | null;
314
- /**
315
- * Creates a TOTP object.
316
- * @param {Object} [config] Configuration options.
317
- * @param {string} [config.issuer=''] Account provider.
318
- * @param {string} [config.label='OTPAuth'] Account label.
319
- * @param {boolean} [config.issuerInLabel=true] Include issuer prefix in label.
320
- * @param {Secret|string} [config.secret=Secret] Secret key.
321
- * @param {string} [config.algorithm='SHA1'] HMAC hashing algorithm.
322
- * @param {number} [config.digits=6] Token length.
323
- * @param {number} [config.period=30] Token time-step duration.
324
- * @param {(algorithm: string, key: Uint8Array, message: Uint8Array) => Uint8Array} [config.hmac] Custom HMAC function.
325
- */
326
- constructor({
327
- issuer,
328
- label,
329
- issuerInLabel,
330
- secret,
331
- algorithm,
332
- digits,
333
- period,
334
- hmac
335
- }?: {
336
- issuer?: string | undefined;
337
- label?: string | undefined;
338
- issuerInLabel?: boolean | undefined;
339
- secret?: string | Secret | undefined;
340
- algorithm?: string | undefined;
341
- digits?: number | undefined;
342
- period?: number | undefined;
343
- hmac?: ((algorithm: string, key: Uint8Array, message: Uint8Array) => Uint8Array) | undefined;
344
- });
485
+ * Verify a 6-digit authenticator code for a user.
486
+ *
487
+ * @param user The user for whom the code is being verified.
488
+ * @param secret The secret used to generate the code.
489
+ * @param code The 6-digit code to verify.
490
+ * @returns True if the code is valid, false otherwise.
491
+ */
492
+ static verifyCode(user: User$1, secret: string, code: string): boolean;
493
+ static getMethod(userId: User$1['id']): Promise<TwoFactorMethod | null>;
494
+ static setMethod(userId: User$1['id'], method: TwoFactorMethod): Promise<void>;
345
495
  /**
346
- * Account provider.
347
- * @type {string}
496
+ * Read the setup secret stored for a user.
497
+ *
498
+ * @param userId The ID of the user.
499
+ * @returns The stored secret, or null if not found.
348
500
  */
349
- issuer: string;
501
+ static getSecret(userId: User$1['id']): Promise<string | null>;
350
502
  /**
351
- * Account label.
352
- * @type {string}
503
+ * Store the setup secret for a user.
504
+ *
505
+ * @param userId The ID of the user.
506
+ * @param secret The secret to store.
353
507
  */
354
- label: string;
508
+ static setSecret(userId: User$1['id'], secret: string): Promise<void>;
509
+ static clearSecret(userId: User$1['id']): Promise<void>;
355
510
  /**
356
- * Include issuer prefix in label.
357
- * @type {boolean}
511
+ * Read the timestamp indicating whether 2FA is enabled.
512
+ *
513
+ * @param userId The ID of the user.
514
+ * @returns The timestamp when 2FA was enabled, or null if not enabled.
358
515
  */
359
- issuerInLabel: boolean;
516
+ static getEnabledAt(userId: User$1['id']): Promise<string | null>;
360
517
  /**
361
- * Secret key.
362
- * @type {Secret}
518
+ * Persist the timestamp marking 2FA as enabled.
519
+ *
520
+ * @param userId The ID of the user.
521
+ * @param enabledAt The timestamp to store.
363
522
  */
364
- secret: Secret;
523
+ static setEnabledAt(userId: User$1['id'], enabledAt?: string | Date): Promise<void>;
365
524
  /**
366
- * HMAC hashing algorithm.
367
- * @type {string}
525
+ * Remove all persisted 2FA state for a user.
526
+ *
527
+ * @param userId The ID of the user.
368
528
  */
369
- algorithm: string;
529
+ static clear(userId: User$1['id']): Promise<void>;
370
530
  /**
371
- * Token length.
372
- * @type {number}
531
+ * Generate one-time recovery codes shown when 2FA is enabled.
532
+ *
533
+ * @returns An array of recovery codes.
373
534
  */
374
- digits: number;
535
+ static generateBackupCodes(count?: number): string[];
375
536
  /**
376
- * Token time-step duration.
377
- * @type {number}
537
+ * Hash recovery codes before persisting them.
538
+ *
539
+ * @param codes An array of recovery codes to hash.
540
+ * @returns An array of hashed recovery codes.
378
541
  */
379
- period: number;
542
+ static hashBackupCodes(codes: string[]): Promise<string[]>;
380
543
  /**
381
- * Custom HMAC function.
382
- * @type {((algorithm: string, key: Uint8Array, message: Uint8Array) => Uint8Array)|undefined}
544
+ * Read stored recovery-code hashes for a user.
545
+ *
546
+ * @param userId The ID of the user.
547
+ * @returns An array of recovery-code hashes.
383
548
  */
384
- hmac: ((algorithm: string, key: Uint8Array, message: Uint8Array) => Uint8Array) | undefined;
549
+ static readRecoveryCodeHashes(userId: User$1['id']): Promise<string[]>;
385
550
  /**
386
- * Calculates the counter. i.e. the number of periods since timestamp 0.
387
- * @param {Object} [config] Configuration options.
388
- * @param {number} [config.timestamp=Date.now] Timestamp value in milliseconds.
389
- * @returns {number} Counter.
551
+ * Persist recovery-code hashes on the user's dedicated 2FA record.
552
+ *
553
+ * @param userId
554
+ * @param hashes
390
555
  */
391
- counter({
392
- timestamp
393
- }?: {
394
- timestamp?: number | undefined;
395
- }): number;
556
+ static writeRecoveryCodeHashes(userId: User$1['id'], hashes: string[]): Promise<void>;
396
557
  /**
397
- * Calculates the remaining time in milliseconds until the next token is generated.
398
- * @param {Object} [config] Configuration options.
399
- * @param {number} [config.timestamp=Date.now] Timestamp value in milliseconds.
400
- * @returns {number} counter.
558
+ * Consume a valid recovery code and invalidate it immediately.
559
+ *
560
+ * @param userId The ID of the user.
561
+ * @param recoveryCode The recovery code to consume.
562
+ * @returns True if the recovery code was valid and consumed, false otherwise.
401
563
  */
402
- remaining({
403
- timestamp
404
- }?: {
405
- timestamp?: number | undefined;
406
- }): number;
564
+ static consumeRecoveryCode(userId: User$1['id'], recoveryCode: string): Promise<boolean>;
407
565
  /**
408
- * Generates a TOTP token.
409
- * @param {Object} [config] Configuration options.
410
- * @param {number} [config.timestamp=Date.now] Timestamp value in milliseconds.
411
- * @returns {string} Token.
566
+ * Return the public 2FA status payload for a user.
567
+ *
568
+ * @param userId The ID of the user.
569
+ * @returns An object containing the 2FA status and recovery codes remaining.
412
570
  */
413
- generate({
414
- timestamp
415
- }?: {
416
- timestamp?: number | undefined;
417
- }): string;
571
+ static readStatus(userId: User$1['id']): Promise<TwoFactorStatus>;
572
+ static createSmsCode(): string;
418
573
  /**
419
- * Validates a TOTP token.
420
- * @param {Object} config Configuration options.
421
- * @param {string} config.token Token value.
422
- * @param {number} [config.timestamp=Date.now] Timestamp value in milliseconds.
423
- * @param {number} [config.window=1] Window of counter values to test.
424
- * @returns {number|null} Token delta or null if it is not found in the search window, in which case it should be considered invalid.
574
+ * Issue a new SMS code for the given user and send it via SMS for the specified purpose.
575
+ *
576
+ * @param user
577
+ * @param purpose
425
578
  */
426
- validate({
427
- token,
428
- timestamp,
429
- window
430
- }: {
431
- token: string;
432
- timestamp?: number | undefined;
433
- window?: number | undefined;
434
- }): number | null;
579
+ static issueSmsCode(user: User$1, purpose: SmsCodePurpose): Promise<IssuedSmsCode>;
580
+ static clearSmsCode(userId: User$1['id']): Promise<void>;
435
581
  /**
436
- * Returns a Google Authenticator key URI.
437
- * @returns {string} URI.
582
+ * Verify a submitted SMS code for a user and purpose, consuming the code if valid.
583
+ *
584
+ * @param userId
585
+ * @param code
586
+ * @param purpose
587
+ * @returns
438
588
  */
439
- toString(): string;
589
+ static verifySmsCode(userId: User$1['id'], code: string, purpose: SmsCodePurpose): Promise<boolean>;
440
590
  }
441
- /**
442
- * HOTP/TOTP object/string conversion.
443
- * @see [Key URI Format](https://github.com/google/google-authenticator/wiki/Key-Uri-Format)
444
- */
445
- //#endregion
446
- //#region src/types/TwoFactor.d.ts
447
- type TwoFactorMethod = 'authenticator' | 'sms';
448
- type SmsCodePurpose = 'setup' | 'login';
449
- type TwoFactorSetup = {
450
- secret: string;
451
- otpauthUrl: string;
452
- };
453
- type TwoFactorStatus = {
454
- enabled: boolean;
455
- enabledAt: string | null;
456
- method: TwoFactorMethod | null;
457
- recoveryCodesRemaining: number;
458
- };
459
- type IssuedSmsCode = {
460
- code: string;
461
- expiresAt: Date;
462
- purpose: SmsCodePurpose;
463
- };
464
591
  //#endregion
465
- //#region src/TwoFactor.d.ts
466
- declare class TwoFactor {
467
- private static getModel;
468
- private static getRecord;
469
- private static upsert;
470
- static normalizeMethod(method?: string | null): TwoFactorMethod | null;
471
- static maskPhone(phone?: string | null): string | null;
472
- static getLabel(user: User): string;
473
- static getTotp(user: User, secret: string): TOTP;
474
- static generateSecret(size?: number): string;
475
- static createSetup(user: User, secret?: string): TwoFactorSetup;
476
- static verifyCode(user: User, secret: string, code: string): boolean;
477
- static getMethod(userId: User['id']): Promise<TwoFactorMethod | null>;
478
- static setMethod(userId: User['id'], method: TwoFactorMethod): Promise<void>;
479
- static getSecret(userId: User['id']): Promise<string | null>;
480
- static setSecret(userId: User['id'], secret: string): Promise<void>;
481
- static clearSecret(userId: User['id']): Promise<void>;
482
- static getEnabledAt(userId: User['id']): Promise<string | null>;
483
- static setEnabledAt(userId: User['id'], enabledAt?: string | Date): Promise<void>;
484
- static clear(userId: User['id']): Promise<void>;
485
- static generateBackupCodes(count?: number): string[];
486
- static hashBackupCodes(codes: string[]): Promise<string[]>;
487
- static readRecoveryCodeHashes(userId: User['id']): Promise<string[]>;
488
- static writeRecoveryCodeHashes(userId: User['id'], hashes: string[]): Promise<void>;
489
- static consumeRecoveryCode(userId: User['id'], recoveryCode: string): Promise<boolean>;
490
- static readStatus(userId: User['id']): Promise<TwoFactorStatus>;
491
- static createSmsCode(): string;
492
- static issueSmsCode(user: User, purpose: SmsCodePurpose): Promise<IssuedSmsCode>;
493
- static clearSmsCode(userId: User['id']): Promise<void>;
494
- static verifySmsCode(userId: User['id'], code: string, purpose: SmsCodePurpose): Promise<boolean>;
592
+ //#region src/Contracts/User.d.ts
593
+ declare abstract class User extends Model {
594
+ [key: string]: any;
595
+ email: string;
596
+ name: string;
597
+ password: string;
598
+ createdAt: Date;
599
+ updatedAt: Date;
600
+ protected static table?: string | undefined;
495
601
  }
496
602
  //#endregion
497
603
  //#region src/Contracts/UserTwoFactor.d.ts
498
604
  declare abstract class UserTwoFactor extends Model {
499
- id: number | string;
500
- userId: User['id'];
605
+ [key: string]: any;
606
+ userId: User$1['id'];
501
607
  method: TwoFactorMethod | null;
502
608
  secretCiphertext: string | null;
503
609
  smsCodeHash: string | null;
@@ -527,5 +633,4 @@ declare class AuthenticationException extends Exception {
527
633
  errors(): Record<string, any> | undefined;
528
634
  }
529
635
  //#endregion
530
- export { Auth, AuthAgentPayload, AuthContract, AuthenticationException, CurrentSession, IssuedSmsCode, PersonalAccessToken, SessionDevice, SessionDeviceInfo, SmsCodePurpose, TwoFactor, TwoFactorMethod, TwoFactorSetup, TwoFactorStatus, User, UserTwoFactor };
531
- //# sourceMappingURL=index.d.ts.map
636
+ export { Auth, AuthContract, AuthSession, AuthenticationException, DeviceAgentPayload, IssuedSmsCode, PersonalAccessToken, SessionDevice, SessionDeviceInfo, SmsCodePurpose, TwoFactor, TwoFactorMethod, TwoFactorSetup, TwoFactorStatus, User, UserTwoFactor, auth };