@prsm/auth 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +226 -0
  2. package/index.d.ts +19 -0
  3. package/package.json +76 -0
  4. package/src/__tests__/auth.test.js +1171 -0
  5. package/src/__tests__/impersonation-test-setup.js +208 -0
  6. package/src/__tests__/impersonation.test.js +473 -0
  7. package/src/__tests__/oauth-test-setup.js +136 -0
  8. package/src/__tests__/oauth.test.js +400 -0
  9. package/src/__tests__/prsm.test.js +215 -0
  10. package/src/__tests__/test-setup.js +385 -0
  11. package/src/__tests__/totp.test.js +158 -0
  12. package/src/__tests__/two-factor-test-setup.js +331 -0
  13. package/src/__tests__/two-factor.test.js +396 -0
  14. package/src/activity-logger.js +228 -0
  15. package/src/auth-context.js +120 -0
  16. package/src/auth-functions.js +520 -0
  17. package/src/auth-manager.js +1371 -0
  18. package/src/errors.js +173 -0
  19. package/src/hooks.js +41 -0
  20. package/src/index.js +23 -0
  21. package/src/invalidation.js +166 -0
  22. package/src/middleware.js +33 -0
  23. package/src/providers/azure-provider.js +114 -0
  24. package/src/providers/base-provider.js +152 -0
  25. package/src/providers/github-provider.js +86 -0
  26. package/src/providers/google-provider.js +76 -0
  27. package/src/providers/index.js +4 -0
  28. package/src/queries.js +543 -0
  29. package/src/schema.js +261 -0
  30. package/src/totp.js +221 -0
  31. package/src/two-factor/index.js +3 -0
  32. package/src/two-factor/otp-provider.js +128 -0
  33. package/src/two-factor/totp-provider.js +98 -0
  34. package/src/two-factor/two-factor-manager.js +676 -0
  35. package/src/types.js +399 -0
  36. package/src/user-roles.js +128 -0
  37. package/src/util.js +32 -0
  38. package/types/activity-logger.d.ts +73 -0
  39. package/types/auth-context.d.ts +88 -0
  40. package/types/auth-functions.d.ts +151 -0
  41. package/types/auth-manager.d.ts +365 -0
  42. package/types/errors.d.ts +108 -0
  43. package/types/hooks.d.ts +30 -0
  44. package/types/index.d.ts +13 -0
  45. package/types/invalidation.d.ts +40 -0
  46. package/types/middleware.d.ts +11 -0
  47. package/types/providers/azure-provider.d.ts +35 -0
  48. package/types/providers/base-provider.d.ts +52 -0
  49. package/types/providers/github-provider.d.ts +29 -0
  50. package/types/providers/google-provider.d.ts +29 -0
  51. package/types/providers/index.d.ts +4 -0
  52. package/types/queries.d.ts +287 -0
  53. package/types/schema.d.ts +37 -0
  54. package/types/totp.d.ts +72 -0
  55. package/types/two-factor/index.d.ts +3 -0
  56. package/types/two-factor/otp-provider.d.ts +57 -0
  57. package/types/two-factor/totp-provider.d.ts +58 -0
  58. package/types/two-factor/two-factor-manager.d.ts +191 -0
  59. package/types/types.d.ts +688 -0
  60. package/types/user-roles.d.ts +47 -0
  61. package/types/util.d.ts +3 -0
@@ -0,0 +1,72 @@
1
+ export class InvalidOtpLengthError extends Error {
2
+ }
3
+ export class InvalidSecretError extends Error {
4
+ }
5
+ export class InvalidHashFunctionError extends Error {
6
+ }
7
+ export class InvalidSecretStrengthError extends Error {
8
+ }
9
+ export class InvalidIntervalError extends Error {
10
+ }
11
+ export default Otp;
12
+ declare class Otp {
13
+ static OTP_LENGTH_MIN: number;
14
+ static OTP_LENGTH_MAX: number;
15
+ static OTP_LENGTH_DEFAULT: number;
16
+ static INTERVAL_LENGTH_DEFAULT: number;
17
+ static EPOCH_DEFAULT: number;
18
+ static HASH_FUNCTION_SHA_1: number;
19
+ static HASH_FUNCTION_SHA_256: number;
20
+ static HASH_FUNCTION_SHA_512: number;
21
+ static HASH_FUNCTION_DEFAULT: number;
22
+ static SHARED_SECRET_STRENGTH_LOW: number;
23
+ static SHARED_SECRET_STRENGTH_MODERATE: number;
24
+ static SHARED_SECRET_STRENGTH_HIGH: number;
25
+ /**
26
+ * Generate a random Base32 shared secret (without padding).
27
+ * @param {number} [strength] one of the SHARED_SECRET_STRENGTH_* constants, defaults to high (160 bits)
28
+ * @returns {string}
29
+ * @throws {InvalidSecretStrengthError}
30
+ */
31
+ static createSecret(strength?: number): string;
32
+ /**
33
+ * Build an otpauth:// URI for QR-code provisioning in authenticator apps.
34
+ * @param {string} issuer
35
+ * @param {string} accountName
36
+ * @param {string} secret
37
+ * @returns {string}
38
+ */
39
+ static createTotpKeyUriForQrCode(issuer: string, accountName: string, secret: string): string;
40
+ /**
41
+ * Generate a TOTP value.
42
+ * @param {string} secret base32 shared secret, at least 16 chars after sanitization
43
+ * @param {number} [t] unix time in seconds, defaults to now
44
+ * @param {number} [otpLength] number of digits (6-8), defaults to 6
45
+ * @param {number} [t_x] time step in seconds, defaults to 30
46
+ * @param {number} [t_0] epoch start in seconds, defaults to 0
47
+ * @param {number} [hashFunction] one of the HASH_FUNCTION_* constants, defaults to SHA-1
48
+ * @returns {string}
49
+ * @throws {InvalidOtpLengthError|InvalidIntervalError|InvalidSecretError|InvalidHashFunctionError}
50
+ */
51
+ static generateTotp(secret: string, t?: number, otpLength?: number, t_x?: number, t_0?: number, hashFunction?: number): string;
52
+ /**
53
+ * Verify a user-supplied TOTP across a drift window using a constant-time compare.
54
+ * @param {string} secret
55
+ * @param {string} otpValue
56
+ * @param {number} [lookBehindSteps] defaults to 2
57
+ * @param {number} [lookAheadSteps] defaults to lookBehindSteps (symmetric)
58
+ * @param {number} [t]
59
+ * @param {number} [otpLength]
60
+ * @param {number} [t_x]
61
+ * @param {number} [t_0]
62
+ * @param {number} [hashFunction]
63
+ * @returns {boolean}
64
+ */
65
+ static verifyTotp(secret: string, otpValue: string, lookBehindSteps?: number, lookAheadSteps?: number, t?: number, otpLength?: number, t_x?: number, t_0?: number, hashFunction?: number): boolean;
66
+ /**
67
+ * @param {number} strength
68
+ * @returns {number}
69
+ * @throws {InvalidSecretStrengthError}
70
+ */
71
+ static determineBitsForSharedSecretStrength(strength: number): number;
72
+ }
@@ -0,0 +1,3 @@
1
+ export { TwoFactorManager } from "./two-factor-manager.js";
2
+ export { TotpProvider } from "./totp-provider.js";
3
+ export { OtpProvider } from "./otp-provider.js";
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @typedef {import("../types.js").AuthConfig} AuthConfig
3
+ * @typedef {import("../types.js").TwoFactorToken} TwoFactorToken
4
+ */
5
+ export class OtpProvider {
6
+ /**
7
+ * @param {AuthConfig} config
8
+ */
9
+ constructor(config: AuthConfig);
10
+ config: import("../types.js").AuthConfig;
11
+ queries: AuthQueries;
12
+ /**
13
+ * Generate a numeric one-time password.
14
+ * @returns {string}
15
+ */
16
+ generateOTP(): string;
17
+ /**
18
+ * Generate a random opaque selector for an OTP token.
19
+ * @returns {string}
20
+ */
21
+ generateSelector(): string;
22
+ /**
23
+ * Create, hash, and store a new OTP for an account and mechanism.
24
+ * @param {number} accountId
25
+ * @param {number} mechanism EMAIL or SMS
26
+ * @returns {Promise<{ otp: string, selector: string }>}
27
+ */
28
+ createAndStoreOTP(accountId: number, mechanism: number): Promise<{
29
+ otp: string;
30
+ selector: string;
31
+ }>;
32
+ /**
33
+ * Verify an OTP by selector, consuming the token on success.
34
+ * @param {string} selector
35
+ * @param {string} inputCode
36
+ * @returns {Promise<{ isValid: boolean, token?: TwoFactorToken }>}
37
+ */
38
+ verifyOTP(selector: string, inputCode: string): Promise<{
39
+ isValid: boolean;
40
+ token?: TwoFactorToken;
41
+ }>;
42
+ /**
43
+ * Mask a phone number for display.
44
+ * @param {string} phone
45
+ * @returns {string}
46
+ */
47
+ maskPhone(phone: string): string;
48
+ /**
49
+ * Mask an email address for display.
50
+ * @param {string} email
51
+ * @returns {string}
52
+ */
53
+ maskEmail(email: string): string;
54
+ }
55
+ export type AuthConfig = import("../types.js").AuthConfig;
56
+ export type TwoFactorToken = import("../types.js").TwoFactorToken;
57
+ import { AuthQueries } from "../queries.js";
@@ -0,0 +1,58 @@
1
+ /**
2
+ * @typedef {import("../types.js").AuthConfig} AuthConfig
3
+ */
4
+ export class TotpProvider {
5
+ /**
6
+ * @param {AuthConfig} config
7
+ */
8
+ constructor(config: AuthConfig);
9
+ config: import("../types.js").AuthConfig;
10
+ /**
11
+ * Generate a new base32 TOTP shared secret.
12
+ * @returns {string}
13
+ */
14
+ generateSecret(): string;
15
+ /**
16
+ * Build an otpauth:// URI for QR-code provisioning.
17
+ * @param {string} email
18
+ * @param {string} secret
19
+ * @returns {string}
20
+ */
21
+ generateQRCode(email: string, secret: string): string;
22
+ /**
23
+ * Verify a TOTP code against a secret using the configured drift window.
24
+ * @param {string} secret
25
+ * @param {string} code
26
+ * @returns {boolean}
27
+ */
28
+ verify(secret: string, code: string): boolean;
29
+ /**
30
+ * Generate random alphanumeric backup codes.
31
+ * @param {number} [count]
32
+ * @returns {string[]}
33
+ */
34
+ generateBackupCodes(count?: number): string[];
35
+ /**
36
+ * Hash a set of backup codes for storage.
37
+ * @param {string[]} codes
38
+ * @returns {Promise<string[]>}
39
+ */
40
+ hashBackupCodes(codes: string[]): Promise<string[]>;
41
+ /**
42
+ * Verify an input backup code against hashed codes.
43
+ * @param {string[]} hashedCodes
44
+ * @param {string} inputCode
45
+ * @returns {Promise<{ isValid: boolean, index: number }>}
46
+ */
47
+ verifyBackupCode(hashedCodes: string[], inputCode: string): Promise<{
48
+ isValid: boolean;
49
+ index: number;
50
+ }>;
51
+ /**
52
+ * Mask an email address for display.
53
+ * @param {string} email
54
+ * @returns {string}
55
+ */
56
+ maskEmail(email: string): string;
57
+ }
58
+ export type AuthConfig = import("../types.js").AuthConfig;
@@ -0,0 +1,191 @@
1
+ /**
2
+ * @typedef {import("express").Request} Request
3
+ * @typedef {import("express").Response} Response
4
+ * @typedef {import("../types.js").AuthConfig} AuthConfig
5
+ * @typedef {import("../types.js").TwoFactorSetupResult} TwoFactorSetupResult
6
+ * @typedef {import("../types.js").TwoFactorChallenge} TwoFactorChallenge
7
+ */
8
+ export class TwoFactorManager {
9
+ /**
10
+ * @param {Request} req
11
+ * @param {Response} res
12
+ * @param {AuthConfig} config
13
+ */
14
+ constructor(req: Request, res: Response, config: AuthConfig);
15
+ req: import("express").Request<import("express-serve-static-core").ParamsDictionary, any, any, import("qs").ParsedQs, Record<string, any>>;
16
+ res: import("express").Response<any, Record<string, any>>;
17
+ config: import("../types.js").AuthConfig;
18
+ queries: AuthQueries;
19
+ activityLogger: ActivityLogger;
20
+ totpProvider: TotpProvider;
21
+ otpProvider: OtpProvider;
22
+ setup: {
23
+ /**
24
+ * Begin TOTP setup, optionally deferring verification.
25
+ * @param {boolean} [requireVerification]
26
+ * @returns {Promise<TwoFactorSetupResult>}
27
+ * @throws {UserNotLoggedInError|TwoFactorAlreadyEnabledError}
28
+ */
29
+ totp: (requireVerification?: boolean) => Promise<TwoFactorSetupResult>;
30
+ /**
31
+ * Begin email 2FA setup, optionally deferring verification.
32
+ * @param {string} [email]
33
+ * @param {boolean} [requireVerification]
34
+ * @returns {Promise<void>}
35
+ * @throws {UserNotLoggedInError|TwoFactorAlreadyEnabledError}
36
+ */
37
+ email: (email?: string, requireVerification?: boolean) => Promise<void>;
38
+ /**
39
+ * Begin SMS 2FA setup, optionally deferring verification.
40
+ * @param {string} phone
41
+ * @param {boolean} [requireVerification]
42
+ * @returns {Promise<void>}
43
+ * @throws {UserNotLoggedInError|TwoFactorAlreadyEnabledError}
44
+ */
45
+ sms: (phone: string, requireVerification?: boolean) => Promise<void>;
46
+ };
47
+ complete: {
48
+ /**
49
+ * Complete TOTP setup by verifying a code, returning backup codes.
50
+ * @param {string} code
51
+ * @returns {Promise<string[]>}
52
+ * @throws {UserNotLoggedInError|TwoFactorNotSetupError|TwoFactorAlreadyEnabledError|InvalidTwoFactorCodeError}
53
+ */
54
+ totp: (code: string) => Promise<string[]>;
55
+ /**
56
+ * Complete email 2FA setup with a verification code.
57
+ * @param {string} code
58
+ * @returns {Promise<void>}
59
+ */
60
+ email: (code: string) => Promise<void>;
61
+ /**
62
+ * Complete SMS 2FA setup with a verification code.
63
+ * @param {string} code
64
+ * @returns {Promise<void>}
65
+ */
66
+ sms: (code: string) => Promise<void>;
67
+ };
68
+ verify: {
69
+ /**
70
+ * Verify a TOTP code during the login flow.
71
+ * @param {string} code
72
+ * @returns {Promise<void>}
73
+ * @throws {UserNotLoggedInError|TwoFactorNotSetupError|InvalidTwoFactorCodeError}
74
+ */
75
+ totp: (code: string) => Promise<void>;
76
+ /**
77
+ * Verify an email OTP during the login flow.
78
+ * @param {string} code
79
+ * @returns {Promise<void>}
80
+ */
81
+ email: (code: string) => Promise<void>;
82
+ /**
83
+ * Verify an SMS OTP during the login flow.
84
+ * @param {string} code
85
+ * @returns {Promise<void>}
86
+ */
87
+ sms: (code: string) => Promise<void>;
88
+ /**
89
+ * Verify a backup code during the login flow, consuming it on success.
90
+ * @param {string} code
91
+ * @returns {Promise<void>}
92
+ * @throws {UserNotLoggedInError|TwoFactorNotSetupError|InvalidBackupCodeError}
93
+ */
94
+ backupCode: (code: string) => Promise<void>;
95
+ /**
96
+ * Verify an OTP against any available email/SMS mechanism during login.
97
+ * @param {string} code
98
+ * @returns {Promise<void>}
99
+ * @throws {UserNotLoggedInError|TwoFactorNotSetupError|InvalidTwoFactorCodeError}
100
+ */
101
+ otp: (code: string) => Promise<void>;
102
+ };
103
+ /**
104
+ * @returns {number | null}
105
+ */
106
+ getAccountId(): number | null;
107
+ /**
108
+ * @returns {string | null}
109
+ */
110
+ getEmail(): string | null;
111
+ /**
112
+ * Whether the current account has any verified 2FA method.
113
+ * @returns {Promise<boolean>}
114
+ */
115
+ isEnabled(): Promise<boolean>;
116
+ /**
117
+ * Whether the current account has TOTP enabled.
118
+ * @returns {Promise<boolean>}
119
+ */
120
+ totpEnabled(): Promise<boolean>;
121
+ /**
122
+ * Whether the current account has email 2FA enabled.
123
+ * @returns {Promise<boolean>}
124
+ */
125
+ emailEnabled(): Promise<boolean>;
126
+ /**
127
+ * Whether the current account has SMS 2FA enabled.
128
+ * @returns {Promise<boolean>}
129
+ */
130
+ smsEnabled(): Promise<boolean>;
131
+ /**
132
+ * List the verified 2FA mechanisms for the current account.
133
+ * @returns {Promise<number[]>}
134
+ */
135
+ getEnabledMethods(): Promise<number[]>;
136
+ /**
137
+ * Mark an OTP-based (email/SMS) method as verified to complete its setup.
138
+ * @param {number} mechanism EMAIL or SMS
139
+ * @param {string} code
140
+ * @returns {Promise<void>}
141
+ * @throws {UserNotLoggedInError|TwoFactorNotSetupError|TwoFactorAlreadyEnabledError}
142
+ */
143
+ completeOtpSetup(mechanism: number, code: string): Promise<void>;
144
+ /**
145
+ * Verify an email/SMS OTP using the selector stored during login.
146
+ * @param {number} mechanism EMAIL or SMS
147
+ * @param {string} code
148
+ * @returns {Promise<void>}
149
+ * @throws {UserNotLoggedInError|TwoFactorNotSetupError|InvalidTwoFactorCodeError}
150
+ */
151
+ verifyOtp(mechanism: number, code: string): Promise<void>;
152
+ /**
153
+ * Disable a 2FA mechanism for the current account.
154
+ * @param {number} mechanism
155
+ * @returns {Promise<void>}
156
+ * @throws {UserNotLoggedInError|TwoFactorNotSetupError}
157
+ */
158
+ disable(mechanism: number): Promise<void>;
159
+ /**
160
+ * Regenerate and store new backup codes for the TOTP method.
161
+ * @returns {Promise<string[]>}
162
+ * @throws {UserNotLoggedInError|TwoFactorNotSetupError}
163
+ */
164
+ generateNewBackupCodes(): Promise<string[]>;
165
+ /**
166
+ * Get the stored contact (email/phone) for an OTP mechanism.
167
+ * @param {number} mechanism EMAIL or SMS
168
+ * @returns {Promise<string | null>}
169
+ */
170
+ getContact(mechanism: number): Promise<string | null>;
171
+ /**
172
+ * Build the otpauth:// URI for the current account's TOTP secret.
173
+ * @returns {Promise<string | null>}
174
+ */
175
+ getTotpUri(): Promise<string | null>;
176
+ /**
177
+ * Build a 2FA challenge for an account, issuing OTPs for email/SMS methods.
178
+ * @param {number} accountId
179
+ * @returns {Promise<TwoFactorChallenge>}
180
+ */
181
+ createChallenge(accountId: number): Promise<TwoFactorChallenge>;
182
+ }
183
+ export type Request = import("express").Request;
184
+ export type Response = import("express").Response;
185
+ export type AuthConfig = import("../types.js").AuthConfig;
186
+ export type TwoFactorSetupResult = import("../types.js").TwoFactorSetupResult;
187
+ export type TwoFactorChallenge = import("../types.js").TwoFactorChallenge;
188
+ import { AuthQueries } from "../queries.js";
189
+ import { ActivityLogger } from "../activity-logger.js";
190
+ import { TotpProvider } from "./totp-provider.js";
191
+ import { OtpProvider } from "./otp-provider.js";