@eaccess/auth 0.1.20 → 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.
- package/README.md +90 -41
- package/dist/index.cjs +108 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -5
- package/dist/index.d.ts +14 -5
- package/dist/index.js +106 -52
- package/dist/index.js.map +1 -1
- package/package.json +17 -9
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
2
|
import { Pool } from 'pg';
|
|
3
|
+
import { IncomingMessage } from 'http';
|
|
3
4
|
|
|
4
5
|
interface OAuthProviderConfig {
|
|
5
6
|
clientId: string;
|
|
@@ -35,6 +36,7 @@ interface AuthConfig {
|
|
|
35
36
|
*/
|
|
36
37
|
createUser?: (userData: OAuthUserData) => string | number | Promise<string | number>;
|
|
37
38
|
tablePrefix?: string;
|
|
39
|
+
roles?: Record<string, number>;
|
|
38
40
|
minPasswordLength?: number;
|
|
39
41
|
maxPasswordLength?: number;
|
|
40
42
|
rememberDuration?: string;
|
|
@@ -119,6 +121,10 @@ interface AuthRemember {
|
|
|
119
121
|
token: string;
|
|
120
122
|
expires: Date;
|
|
121
123
|
}
|
|
124
|
+
interface AuthenticateRequestResult {
|
|
125
|
+
account: AuthAccount | null;
|
|
126
|
+
source: "session" | "remember" | null;
|
|
127
|
+
}
|
|
122
128
|
interface AuthReset {
|
|
123
129
|
id: number;
|
|
124
130
|
account_id: number;
|
|
@@ -599,6 +605,7 @@ interface AuthContext {
|
|
|
599
605
|
}
|
|
600
606
|
declare function createAuthContext(config: AuthConfig): AuthContext;
|
|
601
607
|
|
|
608
|
+
declare function authenticateRequest(config: AuthConfig, req: IncomingMessage, sessionMiddleware?: (req: any, res: any, next: () => void) => void): Promise<AuthenticateRequestResult>;
|
|
602
609
|
declare function createUser(config: AuthConfig, credentials: {
|
|
603
610
|
email: string;
|
|
604
611
|
password: string;
|
|
@@ -654,6 +661,7 @@ declare function forceLogoutForUserBy(config: AuthConfig, identifier: {
|
|
|
654
661
|
}>;
|
|
655
662
|
|
|
656
663
|
declare const authFunctions_addRoleForUserBy: typeof addRoleForUserBy;
|
|
664
|
+
declare const authFunctions_authenticateRequest: typeof authenticateRequest;
|
|
657
665
|
declare const authFunctions_changePasswordForUserBy: typeof changePasswordForUserBy;
|
|
658
666
|
declare const authFunctions_confirmResetPassword: typeof confirmResetPassword;
|
|
659
667
|
declare const authFunctions_createUser: typeof createUser;
|
|
@@ -667,9 +675,10 @@ declare const authFunctions_resetPassword: typeof resetPassword;
|
|
|
667
675
|
declare const authFunctions_setStatusForUserBy: typeof setStatusForUserBy;
|
|
668
676
|
declare const authFunctions_userExistsByEmail: typeof userExistsByEmail;
|
|
669
677
|
declare namespace authFunctions {
|
|
670
|
-
export { authFunctions_addRoleForUserBy as addRoleForUserBy, authFunctions_changePasswordForUserBy as changePasswordForUserBy, authFunctions_confirmResetPassword as confirmResetPassword, authFunctions_createUser as createUser, authFunctions_deleteUserBy as deleteUserBy, authFunctions_forceLogoutForUserBy as forceLogoutForUserBy, authFunctions_hasRoleForUserBy as hasRoleForUserBy, authFunctions_initiatePasswordResetForUserBy as initiatePasswordResetForUserBy, authFunctions_register as register, authFunctions_removeRoleForUserBy as removeRoleForUserBy, authFunctions_resetPassword as resetPassword, authFunctions_setStatusForUserBy as setStatusForUserBy, authFunctions_userExistsByEmail as userExistsByEmail };
|
|
678
|
+
export { authFunctions_addRoleForUserBy as addRoleForUserBy, authFunctions_authenticateRequest as authenticateRequest, authFunctions_changePasswordForUserBy as changePasswordForUserBy, authFunctions_confirmResetPassword as confirmResetPassword, authFunctions_createUser as createUser, authFunctions_deleteUserBy as deleteUserBy, authFunctions_forceLogoutForUserBy as forceLogoutForUserBy, authFunctions_hasRoleForUserBy as hasRoleForUserBy, authFunctions_initiatePasswordResetForUserBy as initiatePasswordResetForUserBy, authFunctions_register as register, authFunctions_removeRoleForUserBy as removeRoleForUserBy, authFunctions_resetPassword as resetPassword, authFunctions_setStatusForUserBy as setStatusForUserBy, authFunctions_userExistsByEmail as userExistsByEmail };
|
|
671
679
|
}
|
|
672
680
|
|
|
681
|
+
declare function defineRoles<const T extends readonly string[]>(...names: T): Readonly<Record<T[number], number>>;
|
|
673
682
|
type UserIdentifier = {
|
|
674
683
|
accountId?: number;
|
|
675
684
|
email?: string;
|
|
@@ -866,11 +875,11 @@ declare class TotpProvider {
|
|
|
866
875
|
generateQRCode(email: string, secret: string): string;
|
|
867
876
|
verify(secret: string, code: string): boolean;
|
|
868
877
|
generateBackupCodes(count?: number): string[];
|
|
869
|
-
hashBackupCodes(codes: string[]): string[]
|
|
870
|
-
verifyBackupCode(hashedCodes: string[], inputCode: string): {
|
|
878
|
+
hashBackupCodes(codes: string[]): Promise<string[]>;
|
|
879
|
+
verifyBackupCode(hashedCodes: string[], inputCode: string): Promise<{
|
|
871
880
|
isValid: boolean;
|
|
872
881
|
index: number;
|
|
873
|
-
}
|
|
882
|
+
}>;
|
|
874
883
|
maskEmail(email: string): string;
|
|
875
884
|
}
|
|
876
885
|
|
|
@@ -1193,4 +1202,4 @@ declare class AzureProvider extends BaseOAuthProvider {
|
|
|
1193
1202
|
protected exchangeCodeForToken(code: string, tokenUrl: string): Promise<string>;
|
|
1194
1203
|
}
|
|
1195
1204
|
|
|
1196
|
-
export { ActivityLogger, type AuthAccount, type AuthActivity, AuthActivityAction, type AuthActivityActionType, type AuthConfig, type AuthConfirmation, type AuthContext, AuthError, type AuthManager$1 as AuthManager, type AuthProvider, type AuthRemember, type AuthReset, AuthRole, type AuthSession, AuthStatus, AzureProvider, type AzureProviderConfig, BaseOAuthProvider, ConfirmationExpiredError, ConfirmationNotFoundError, EmailNotVerifiedError, EmailTakenError, GitHubProvider, type GitHubProviderConfig, GoogleProvider, type GoogleProviderConfig, InvalidBackupCodeError, InvalidEmailError, InvalidPasswordError, InvalidTokenError, InvalidTwoFactorCodeError, type OAuthCallbackResult, type OAuthProvider, type OAuthProviderConfig, type OAuthUserData, OtpProvider, ResetDisabledError, ResetExpiredError, ResetNotFoundError, SecondFactorRequiredError, type TokenCallback, TooManyResetsError, TotpProvider, TwoFactorAlreadyEnabledError, type TwoFactorChallenge, TwoFactorExpiredError, TwoFactorManager, TwoFactorMechanism, type TwoFactorMethod, TwoFactorNotSetupError, TwoFactorSetupIncompleteError, type TwoFactorSetupResult, type TwoFactorToken, type UserIdentifier, UserInactiveError, UserNotFoundError, UserNotLoggedInError, addRoleForUserBy, addRoleToUser, authFunctions, changePasswordForUserBy, cleanupExpiredTokens, confirmResetPassword, createAuthContext, createAuthMiddleware, createAuthTables, createUser, deleteUserBy, dropAuthTables, forceLogoutForUserBy, getAuthTableStats, getUserRoles, hasRoleForUserBy, initiatePasswordResetForUserBy, isValidEmail, register, removeRoleForUserBy, removeRoleFromUser, resetPassword, setStatusForUserBy, setUserRoles, userExistsByEmail, validateEmail };
|
|
1205
|
+
export { ActivityLogger, type AuthAccount, type AuthActivity, AuthActivityAction, type AuthActivityActionType, type AuthConfig, type AuthConfirmation, type AuthContext, AuthError, type AuthManager$1 as AuthManager, type AuthProvider, type AuthRemember, type AuthReset, AuthRole, type AuthSession, AuthStatus, type AuthenticateRequestResult, AzureProvider, type AzureProviderConfig, BaseOAuthProvider, ConfirmationExpiredError, ConfirmationNotFoundError, EmailNotVerifiedError, EmailTakenError, GitHubProvider, type GitHubProviderConfig, GoogleProvider, type GoogleProviderConfig, InvalidBackupCodeError, InvalidEmailError, InvalidPasswordError, InvalidTokenError, InvalidTwoFactorCodeError, type OAuthCallbackResult, type OAuthProvider, type OAuthProviderConfig, type OAuthUserData, OtpProvider, ResetDisabledError, ResetExpiredError, ResetNotFoundError, SecondFactorRequiredError, type TokenCallback, TooManyResetsError, TotpProvider, TwoFactorAlreadyEnabledError, type TwoFactorChallenge, TwoFactorExpiredError, TwoFactorManager, TwoFactorMechanism, type TwoFactorMethod, TwoFactorNotSetupError, TwoFactorSetupIncompleteError, type TwoFactorSetupResult, type TwoFactorToken, type UserIdentifier, UserInactiveError, UserNotFoundError, UserNotLoggedInError, addRoleForUserBy, addRoleToUser, authFunctions, authenticateRequest, changePasswordForUserBy, cleanupExpiredTokens, confirmResetPassword, createAuthContext, createAuthMiddleware, createAuthTables, createUser, defineRoles, deleteUserBy, dropAuthTables, forceLogoutForUserBy, getAuthTableStats, getUserRoles, hasRoleForUserBy, initiatePasswordResetForUserBy, isValidEmail, register, removeRoleForUserBy, removeRoleFromUser, resetPassword, setStatusForUserBy, setUserRoles, userExistsByEmail, validateEmail };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
2
|
import { Pool } from 'pg';
|
|
3
|
+
import { IncomingMessage } from 'http';
|
|
3
4
|
|
|
4
5
|
interface OAuthProviderConfig {
|
|
5
6
|
clientId: string;
|
|
@@ -35,6 +36,7 @@ interface AuthConfig {
|
|
|
35
36
|
*/
|
|
36
37
|
createUser?: (userData: OAuthUserData) => string | number | Promise<string | number>;
|
|
37
38
|
tablePrefix?: string;
|
|
39
|
+
roles?: Record<string, number>;
|
|
38
40
|
minPasswordLength?: number;
|
|
39
41
|
maxPasswordLength?: number;
|
|
40
42
|
rememberDuration?: string;
|
|
@@ -119,6 +121,10 @@ interface AuthRemember {
|
|
|
119
121
|
token: string;
|
|
120
122
|
expires: Date;
|
|
121
123
|
}
|
|
124
|
+
interface AuthenticateRequestResult {
|
|
125
|
+
account: AuthAccount | null;
|
|
126
|
+
source: "session" | "remember" | null;
|
|
127
|
+
}
|
|
122
128
|
interface AuthReset {
|
|
123
129
|
id: number;
|
|
124
130
|
account_id: number;
|
|
@@ -599,6 +605,7 @@ interface AuthContext {
|
|
|
599
605
|
}
|
|
600
606
|
declare function createAuthContext(config: AuthConfig): AuthContext;
|
|
601
607
|
|
|
608
|
+
declare function authenticateRequest(config: AuthConfig, req: IncomingMessage, sessionMiddleware?: (req: any, res: any, next: () => void) => void): Promise<AuthenticateRequestResult>;
|
|
602
609
|
declare function createUser(config: AuthConfig, credentials: {
|
|
603
610
|
email: string;
|
|
604
611
|
password: string;
|
|
@@ -654,6 +661,7 @@ declare function forceLogoutForUserBy(config: AuthConfig, identifier: {
|
|
|
654
661
|
}>;
|
|
655
662
|
|
|
656
663
|
declare const authFunctions_addRoleForUserBy: typeof addRoleForUserBy;
|
|
664
|
+
declare const authFunctions_authenticateRequest: typeof authenticateRequest;
|
|
657
665
|
declare const authFunctions_changePasswordForUserBy: typeof changePasswordForUserBy;
|
|
658
666
|
declare const authFunctions_confirmResetPassword: typeof confirmResetPassword;
|
|
659
667
|
declare const authFunctions_createUser: typeof createUser;
|
|
@@ -667,9 +675,10 @@ declare const authFunctions_resetPassword: typeof resetPassword;
|
|
|
667
675
|
declare const authFunctions_setStatusForUserBy: typeof setStatusForUserBy;
|
|
668
676
|
declare const authFunctions_userExistsByEmail: typeof userExistsByEmail;
|
|
669
677
|
declare namespace authFunctions {
|
|
670
|
-
export { authFunctions_addRoleForUserBy as addRoleForUserBy, authFunctions_changePasswordForUserBy as changePasswordForUserBy, authFunctions_confirmResetPassword as confirmResetPassword, authFunctions_createUser as createUser, authFunctions_deleteUserBy as deleteUserBy, authFunctions_forceLogoutForUserBy as forceLogoutForUserBy, authFunctions_hasRoleForUserBy as hasRoleForUserBy, authFunctions_initiatePasswordResetForUserBy as initiatePasswordResetForUserBy, authFunctions_register as register, authFunctions_removeRoleForUserBy as removeRoleForUserBy, authFunctions_resetPassword as resetPassword, authFunctions_setStatusForUserBy as setStatusForUserBy, authFunctions_userExistsByEmail as userExistsByEmail };
|
|
678
|
+
export { authFunctions_addRoleForUserBy as addRoleForUserBy, authFunctions_authenticateRequest as authenticateRequest, authFunctions_changePasswordForUserBy as changePasswordForUserBy, authFunctions_confirmResetPassword as confirmResetPassword, authFunctions_createUser as createUser, authFunctions_deleteUserBy as deleteUserBy, authFunctions_forceLogoutForUserBy as forceLogoutForUserBy, authFunctions_hasRoleForUserBy as hasRoleForUserBy, authFunctions_initiatePasswordResetForUserBy as initiatePasswordResetForUserBy, authFunctions_register as register, authFunctions_removeRoleForUserBy as removeRoleForUserBy, authFunctions_resetPassword as resetPassword, authFunctions_setStatusForUserBy as setStatusForUserBy, authFunctions_userExistsByEmail as userExistsByEmail };
|
|
671
679
|
}
|
|
672
680
|
|
|
681
|
+
declare function defineRoles<const T extends readonly string[]>(...names: T): Readonly<Record<T[number], number>>;
|
|
673
682
|
type UserIdentifier = {
|
|
674
683
|
accountId?: number;
|
|
675
684
|
email?: string;
|
|
@@ -866,11 +875,11 @@ declare class TotpProvider {
|
|
|
866
875
|
generateQRCode(email: string, secret: string): string;
|
|
867
876
|
verify(secret: string, code: string): boolean;
|
|
868
877
|
generateBackupCodes(count?: number): string[];
|
|
869
|
-
hashBackupCodes(codes: string[]): string[]
|
|
870
|
-
verifyBackupCode(hashedCodes: string[], inputCode: string): {
|
|
878
|
+
hashBackupCodes(codes: string[]): Promise<string[]>;
|
|
879
|
+
verifyBackupCode(hashedCodes: string[], inputCode: string): Promise<{
|
|
871
880
|
isValid: boolean;
|
|
872
881
|
index: number;
|
|
873
|
-
}
|
|
882
|
+
}>;
|
|
874
883
|
maskEmail(email: string): string;
|
|
875
884
|
}
|
|
876
885
|
|
|
@@ -1193,4 +1202,4 @@ declare class AzureProvider extends BaseOAuthProvider {
|
|
|
1193
1202
|
protected exchangeCodeForToken(code: string, tokenUrl: string): Promise<string>;
|
|
1194
1203
|
}
|
|
1195
1204
|
|
|
1196
|
-
export { ActivityLogger, type AuthAccount, type AuthActivity, AuthActivityAction, type AuthActivityActionType, type AuthConfig, type AuthConfirmation, type AuthContext, AuthError, type AuthManager$1 as AuthManager, type AuthProvider, type AuthRemember, type AuthReset, AuthRole, type AuthSession, AuthStatus, AzureProvider, type AzureProviderConfig, BaseOAuthProvider, ConfirmationExpiredError, ConfirmationNotFoundError, EmailNotVerifiedError, EmailTakenError, GitHubProvider, type GitHubProviderConfig, GoogleProvider, type GoogleProviderConfig, InvalidBackupCodeError, InvalidEmailError, InvalidPasswordError, InvalidTokenError, InvalidTwoFactorCodeError, type OAuthCallbackResult, type OAuthProvider, type OAuthProviderConfig, type OAuthUserData, OtpProvider, ResetDisabledError, ResetExpiredError, ResetNotFoundError, SecondFactorRequiredError, type TokenCallback, TooManyResetsError, TotpProvider, TwoFactorAlreadyEnabledError, type TwoFactorChallenge, TwoFactorExpiredError, TwoFactorManager, TwoFactorMechanism, type TwoFactorMethod, TwoFactorNotSetupError, TwoFactorSetupIncompleteError, type TwoFactorSetupResult, type TwoFactorToken, type UserIdentifier, UserInactiveError, UserNotFoundError, UserNotLoggedInError, addRoleForUserBy, addRoleToUser, authFunctions, changePasswordForUserBy, cleanupExpiredTokens, confirmResetPassword, createAuthContext, createAuthMiddleware, createAuthTables, createUser, deleteUserBy, dropAuthTables, forceLogoutForUserBy, getAuthTableStats, getUserRoles, hasRoleForUserBy, initiatePasswordResetForUserBy, isValidEmail, register, removeRoleForUserBy, removeRoleFromUser, resetPassword, setStatusForUserBy, setUserRoles, userExistsByEmail, validateEmail };
|
|
1205
|
+
export { ActivityLogger, type AuthAccount, type AuthActivity, AuthActivityAction, type AuthActivityActionType, type AuthConfig, type AuthConfirmation, type AuthContext, AuthError, type AuthManager$1 as AuthManager, type AuthProvider, type AuthRemember, type AuthReset, AuthRole, type AuthSession, AuthStatus, type AuthenticateRequestResult, AzureProvider, type AzureProviderConfig, BaseOAuthProvider, ConfirmationExpiredError, ConfirmationNotFoundError, EmailNotVerifiedError, EmailTakenError, GitHubProvider, type GitHubProviderConfig, GoogleProvider, type GoogleProviderConfig, InvalidBackupCodeError, InvalidEmailError, InvalidPasswordError, InvalidTokenError, InvalidTwoFactorCodeError, type OAuthCallbackResult, type OAuthProvider, type OAuthProviderConfig, type OAuthUserData, OtpProvider, ResetDisabledError, ResetExpiredError, ResetNotFoundError, SecondFactorRequiredError, type TokenCallback, TooManyResetsError, TotpProvider, TwoFactorAlreadyEnabledError, type TwoFactorChallenge, TwoFactorExpiredError, TwoFactorManager, TwoFactorMechanism, type TwoFactorMethod, TwoFactorNotSetupError, TwoFactorSetupIncompleteError, type TwoFactorSetupResult, type TwoFactorToken, type UserIdentifier, UserInactiveError, UserNotFoundError, UserNotLoggedInError, addRoleForUserBy, addRoleToUser, authFunctions, authenticateRequest, changePasswordForUserBy, cleanupExpiredTokens, confirmResetPassword, createAuthContext, createAuthMiddleware, createAuthTables, createUser, defineRoles, deleteUserBy, dropAuthTables, forceLogoutForUserBy, getAuthTableStats, getUserRoles, hasRoleForUserBy, initiatePasswordResetForUserBy, isValidEmail, register, removeRoleForUserBy, removeRoleFromUser, resetPassword, setStatusForUserBy, setUserRoles, userExistsByEmail, validateEmail };
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var __export = (target, all) => {
|
|
|
5
5
|
};
|
|
6
6
|
|
|
7
7
|
// src/auth-manager.ts
|
|
8
|
-
import
|
|
8
|
+
import hash4 from "@prsm/hash";
|
|
9
9
|
import ms3 from "@prsm/ms";
|
|
10
10
|
|
|
11
11
|
// src/types.ts
|
|
@@ -721,7 +721,7 @@ var GitHubProvider = class extends BaseOAuthProvider {
|
|
|
721
721
|
client_id: this.config.clientId,
|
|
722
722
|
redirect_uri: this.config.redirectUri,
|
|
723
723
|
scope: scopes?.join(" ") || "user:email",
|
|
724
|
-
state: state ||
|
|
724
|
+
state: state || crypto.randomUUID(),
|
|
725
725
|
response_type: "code"
|
|
726
726
|
});
|
|
727
727
|
return `https://github.com/login/oauth/authorize?${params}`;
|
|
@@ -770,7 +770,7 @@ var GoogleProvider = class extends BaseOAuthProvider {
|
|
|
770
770
|
client_id: this.config.clientId,
|
|
771
771
|
redirect_uri: this.config.redirectUri,
|
|
772
772
|
scope: scopes?.join(" ") || "openid profile email",
|
|
773
|
-
state: state ||
|
|
773
|
+
state: state || crypto.randomUUID(),
|
|
774
774
|
response_type: "code",
|
|
775
775
|
access_type: "offline",
|
|
776
776
|
prompt: "consent"
|
|
@@ -812,7 +812,7 @@ var AzureProvider = class extends BaseOAuthProvider {
|
|
|
812
812
|
client_id: azureConfig.clientId,
|
|
813
813
|
redirect_uri: azureConfig.redirectUri,
|
|
814
814
|
scope: scopes?.join(" ") || "openid profile email User.Read",
|
|
815
|
-
state: state ||
|
|
815
|
+
state: state || crypto.randomUUID(),
|
|
816
816
|
response_type: "code",
|
|
817
817
|
response_mode: "query"
|
|
818
818
|
});
|
|
@@ -871,7 +871,7 @@ var AzureProvider = class extends BaseOAuthProvider {
|
|
|
871
871
|
|
|
872
872
|
// src/two-factor/totp-provider.ts
|
|
873
873
|
import Otp from "@eaccess/totp";
|
|
874
|
-
import
|
|
874
|
+
import hash from "@prsm/hash";
|
|
875
875
|
var TotpProvider = class {
|
|
876
876
|
constructor(config) {
|
|
877
877
|
this.config = config;
|
|
@@ -888,23 +888,20 @@ var TotpProvider = class {
|
|
|
888
888
|
return Otp.verifyTotp(secret, code, window);
|
|
889
889
|
}
|
|
890
890
|
generateBackupCodes(count = 10) {
|
|
891
|
+
const chars = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
891
892
|
const codes = [];
|
|
892
893
|
for (let i = 0; i < count; i++) {
|
|
893
|
-
const
|
|
894
|
-
|
|
895
|
-
for (let j = 0; j < 8; j++) {
|
|
896
|
-
code += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
897
|
-
}
|
|
898
|
-
codes.push(code);
|
|
894
|
+
const bytes = crypto.getRandomValues(new Uint8Array(8));
|
|
895
|
+
codes.push(Array.from(bytes, (b) => chars[b % chars.length]).join(""));
|
|
899
896
|
}
|
|
900
897
|
return codes;
|
|
901
898
|
}
|
|
902
|
-
hashBackupCodes(codes) {
|
|
903
|
-
return codes.map((code) => hash.encode(code));
|
|
899
|
+
async hashBackupCodes(codes) {
|
|
900
|
+
return await Promise.all(codes.map((code) => hash.encode(code)));
|
|
904
901
|
}
|
|
905
|
-
verifyBackupCode(hashedCodes, inputCode) {
|
|
902
|
+
async verifyBackupCode(hashedCodes, inputCode) {
|
|
906
903
|
for (let i = 0; i < hashedCodes.length; i++) {
|
|
907
|
-
if (hash.verify(hashedCodes[i], inputCode.toUpperCase())) {
|
|
904
|
+
if (await hash.verify(hashedCodes[i], inputCode.toUpperCase())) {
|
|
908
905
|
return { isValid: true, index: i };
|
|
909
906
|
}
|
|
910
907
|
}
|
|
@@ -921,7 +918,7 @@ var TotpProvider = class {
|
|
|
921
918
|
|
|
922
919
|
// src/two-factor/otp-provider.ts
|
|
923
920
|
import ms from "@prsm/ms";
|
|
924
|
-
import
|
|
921
|
+
import hash2 from "@prsm/hash";
|
|
925
922
|
var OtpProvider = class {
|
|
926
923
|
constructor(config) {
|
|
927
924
|
this.config = config;
|
|
@@ -929,24 +926,16 @@ var OtpProvider = class {
|
|
|
929
926
|
}
|
|
930
927
|
generateOTP() {
|
|
931
928
|
const length = this.config.twoFactor?.codeLength || 6;
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
otp += Math.floor(Math.random() * 10).toString();
|
|
935
|
-
}
|
|
936
|
-
return otp;
|
|
929
|
+
const bytes = crypto.getRandomValues(new Uint8Array(length));
|
|
930
|
+
return Array.from(bytes, (b) => (b % 10).toString()).join("");
|
|
937
931
|
}
|
|
938
932
|
generateSelector() {
|
|
939
|
-
|
|
940
|
-
let selector = "";
|
|
941
|
-
for (let i = 0; i < 32; i++) {
|
|
942
|
-
selector += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
943
|
-
}
|
|
944
|
-
return selector;
|
|
933
|
+
return crypto.randomUUID().replace(/-/g, "");
|
|
945
934
|
}
|
|
946
935
|
async createAndStoreOTP(accountId, mechanism) {
|
|
947
936
|
const otp = this.generateOTP();
|
|
948
937
|
const selector = this.generateSelector();
|
|
949
|
-
const tokenHash = hash2.encode(otp);
|
|
938
|
+
const tokenHash = await hash2.encode(otp);
|
|
950
939
|
const expiryDuration = this.config.twoFactor?.tokenExpiry || "5m";
|
|
951
940
|
const expiresAt = new Date(Date.now() + ms(expiryDuration));
|
|
952
941
|
await this.queries.deleteTwoFactorTokensByAccountAndMechanism(accountId, mechanism);
|
|
@@ -968,7 +957,7 @@ var OtpProvider = class {
|
|
|
968
957
|
await this.queries.deleteTwoFactorToken(token.id);
|
|
969
958
|
return { isValid: false };
|
|
970
959
|
}
|
|
971
|
-
const isValid = hash2.verify(token.token_hash, inputCode);
|
|
960
|
+
const isValid = await hash2.verify(token.token_hash, inputCode);
|
|
972
961
|
if (isValid) {
|
|
973
962
|
await this.queries.deleteTwoFactorToken(token.id);
|
|
974
963
|
return { isValid: true, token };
|
|
@@ -1015,7 +1004,7 @@ var TwoFactorManager = class {
|
|
|
1015
1004
|
const backupCodesCount = this.config.twoFactor?.backupCodesCount || 10;
|
|
1016
1005
|
backupCodes = this.totpProvider.generateBackupCodes(backupCodesCount);
|
|
1017
1006
|
}
|
|
1018
|
-
const hashedBackupCodes = backupCodes ? this.totpProvider.hashBackupCodes(backupCodes) : void 0;
|
|
1007
|
+
const hashedBackupCodes = backupCodes ? await this.totpProvider.hashBackupCodes(backupCodes) : void 0;
|
|
1019
1008
|
const verified = !requireVerification;
|
|
1020
1009
|
if (existingMethod) {
|
|
1021
1010
|
await this.queries.updateTwoFactorMethod(existingMethod.id, {
|
|
@@ -1113,7 +1102,7 @@ var TwoFactorManager = class {
|
|
|
1113
1102
|
}
|
|
1114
1103
|
const backupCodesCount = this.config.twoFactor?.backupCodesCount || 10;
|
|
1115
1104
|
const backupCodes = this.totpProvider.generateBackupCodes(backupCodesCount);
|
|
1116
|
-
const hashedBackupCodes = this.totpProvider.hashBackupCodes(backupCodes);
|
|
1105
|
+
const hashedBackupCodes = await this.totpProvider.hashBackupCodes(backupCodes);
|
|
1117
1106
|
await this.queries.updateTwoFactorMethod(method.id, {
|
|
1118
1107
|
verified: true,
|
|
1119
1108
|
backup_codes: hashedBackupCodes,
|
|
@@ -1165,7 +1154,7 @@ var TwoFactorManager = class {
|
|
|
1165
1154
|
if (!method || !method.verified || !method.backup_codes) {
|
|
1166
1155
|
throw new TwoFactorNotSetupError();
|
|
1167
1156
|
}
|
|
1168
|
-
const { isValid, index } = this.totpProvider.verifyBackupCode(method.backup_codes, code);
|
|
1157
|
+
const { isValid, index } = await this.totpProvider.verifyBackupCode(method.backup_codes, code);
|
|
1169
1158
|
if (!isValid) {
|
|
1170
1159
|
await this.activityLogger.logActivity(twoFactorState.accountId, AuthActivityAction.TwoFactorFailed, this.req, false, { mechanism: "backup_code", reason: "invalid_code" });
|
|
1171
1160
|
throw new InvalidBackupCodeError();
|
|
@@ -1314,7 +1303,7 @@ var TwoFactorManager = class {
|
|
|
1314
1303
|
}
|
|
1315
1304
|
const backupCodesCount = this.config.twoFactor?.backupCodesCount || 10;
|
|
1316
1305
|
const backupCodes = this.totpProvider.generateBackupCodes(backupCodesCount);
|
|
1317
|
-
const hashedBackupCodes = this.totpProvider.hashBackupCodes(backupCodes);
|
|
1306
|
+
const hashedBackupCodes = await this.totpProvider.hashBackupCodes(backupCodes);
|
|
1318
1307
|
await this.queries.updateTwoFactorMethod(method.id, {
|
|
1319
1308
|
backup_codes: hashedBackupCodes
|
|
1320
1309
|
});
|
|
@@ -1382,6 +1371,7 @@ var TwoFactorManager = class {
|
|
|
1382
1371
|
var auth_functions_exports = {};
|
|
1383
1372
|
__export(auth_functions_exports, {
|
|
1384
1373
|
addRoleForUserBy: () => addRoleForUserBy,
|
|
1374
|
+
authenticateRequest: () => authenticateRequest,
|
|
1385
1375
|
changePasswordForUserBy: () => changePasswordForUserBy,
|
|
1386
1376
|
confirmResetPassword: () => confirmResetPassword,
|
|
1387
1377
|
createUser: () => createUser,
|
|
@@ -1395,8 +1385,50 @@ __export(auth_functions_exports, {
|
|
|
1395
1385
|
setStatusForUserBy: () => setStatusForUserBy,
|
|
1396
1386
|
userExistsByEmail: () => userExistsByEmail
|
|
1397
1387
|
});
|
|
1398
|
-
import
|
|
1388
|
+
import hash3 from "@prsm/hash";
|
|
1399
1389
|
import ms2 from "@prsm/ms";
|
|
1390
|
+
function parseCookies(cookieHeader) {
|
|
1391
|
+
const cookies = {};
|
|
1392
|
+
if (!cookieHeader) return cookies;
|
|
1393
|
+
for (const pair of cookieHeader.split(";")) {
|
|
1394
|
+
const idx = pair.indexOf("=");
|
|
1395
|
+
if (idx === -1) continue;
|
|
1396
|
+
const key = pair.slice(0, idx).trim();
|
|
1397
|
+
const value = pair.slice(idx + 1).trim();
|
|
1398
|
+
if (key) cookies[key] = decodeURIComponent(value);
|
|
1399
|
+
}
|
|
1400
|
+
return cookies;
|
|
1401
|
+
}
|
|
1402
|
+
async function authenticateRequest(config, req, sessionMiddleware) {
|
|
1403
|
+
const queries = new AuthQueries(config);
|
|
1404
|
+
if (sessionMiddleware) {
|
|
1405
|
+
await new Promise((resolve) => {
|
|
1406
|
+
sessionMiddleware(req, {}, resolve);
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1409
|
+
const session = req.session;
|
|
1410
|
+
if (session?.auth?.loggedIn && session.auth.accountId) {
|
|
1411
|
+
const account2 = await queries.findAccountById(session.auth.accountId);
|
|
1412
|
+
if (account2 && account2.status === AuthStatus.Normal) {
|
|
1413
|
+
return { account: account2, source: "session" };
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
const cookies = parseCookies(req.headers.cookie || "");
|
|
1417
|
+
const cookieName = config.rememberCookieName || "remember_token";
|
|
1418
|
+
const token = cookies[cookieName];
|
|
1419
|
+
if (!token) {
|
|
1420
|
+
return { account: null, source: null };
|
|
1421
|
+
}
|
|
1422
|
+
const remember = await queries.findRememberToken(token);
|
|
1423
|
+
if (!remember || /* @__PURE__ */ new Date() > remember.expires) {
|
|
1424
|
+
return { account: null, source: null };
|
|
1425
|
+
}
|
|
1426
|
+
const account = await queries.findAccountById(remember.account_id);
|
|
1427
|
+
if (!account || account.status !== AuthStatus.Normal) {
|
|
1428
|
+
return { account: null, source: null };
|
|
1429
|
+
}
|
|
1430
|
+
return { account, source: "remember" };
|
|
1431
|
+
}
|
|
1400
1432
|
function validatePassword(password, config) {
|
|
1401
1433
|
const minLength = config.minPasswordLength || 8;
|
|
1402
1434
|
const maxLength = config.maxPasswordLength || 64;
|
|
@@ -1424,7 +1456,7 @@ async function findAccountByIdentifier(queries, identifier) {
|
|
|
1424
1456
|
return null;
|
|
1425
1457
|
}
|
|
1426
1458
|
async function createConfirmationToken(queries, account, email, callback) {
|
|
1427
|
-
const token = hash3.encode(email);
|
|
1459
|
+
const token = await hash3.encode(email);
|
|
1428
1460
|
const expires = new Date(Date.now() + 1e3 * 60 * 60 * 24 * 7);
|
|
1429
1461
|
await queries.createConfirmation({
|
|
1430
1462
|
accountId: account.id,
|
|
@@ -1445,7 +1477,7 @@ async function createUser(config, credentials, userId, callback) {
|
|
|
1445
1477
|
throw new EmailTakenError();
|
|
1446
1478
|
}
|
|
1447
1479
|
const finalUserId = userId || generateAutoUserId();
|
|
1448
|
-
const hashedPassword = hash3.encode(credentials.password);
|
|
1480
|
+
const hashedPassword = await hash3.encode(credentials.password);
|
|
1449
1481
|
const verified = typeof callback !== "function";
|
|
1450
1482
|
const account = await queries.createAccount({
|
|
1451
1483
|
userId: finalUserId,
|
|
@@ -1469,7 +1501,7 @@ async function register(config, email, password, userId, callback) {
|
|
|
1469
1501
|
throw new EmailTakenError();
|
|
1470
1502
|
}
|
|
1471
1503
|
const finalUserId = userId || generateAutoUserId();
|
|
1472
|
-
const hashedPassword = hash3.encode(password);
|
|
1504
|
+
const hashedPassword = await hash3.encode(password);
|
|
1473
1505
|
const verified = typeof callback !== "function";
|
|
1474
1506
|
const account = await queries.createAccount({
|
|
1475
1507
|
userId: finalUserId,
|
|
@@ -1526,7 +1558,7 @@ async function changePasswordForUserBy(config, identifier, password) {
|
|
|
1526
1558
|
throw new UserNotFoundError();
|
|
1527
1559
|
}
|
|
1528
1560
|
await queries.updateAccount(account.id, {
|
|
1529
|
-
password: hash3.encode(password)
|
|
1561
|
+
password: await hash3.encode(password)
|
|
1530
1562
|
});
|
|
1531
1563
|
}
|
|
1532
1564
|
async function setStatusForUserBy(config, identifier, status) {
|
|
@@ -1547,7 +1579,7 @@ async function initiatePasswordResetForUserBy(config, identifier, expiresAfter =
|
|
|
1547
1579
|
throw new EmailNotVerifiedError();
|
|
1548
1580
|
}
|
|
1549
1581
|
const expiry = !expiresAfter ? ms2("6h") : ms2(expiresAfter);
|
|
1550
|
-
const token = hash3.encode(account.email);
|
|
1582
|
+
const token = await hash3.encode(account.email);
|
|
1551
1583
|
const expires = new Date(Date.now() + expiry);
|
|
1552
1584
|
await queries.createResetToken({
|
|
1553
1585
|
accountId: account.id,
|
|
@@ -1574,7 +1606,7 @@ async function resetPassword(config, email, expiresAfter = null, maxOpenRequests
|
|
|
1574
1606
|
if (openRequests >= maxRequests) {
|
|
1575
1607
|
throw new TooManyResetsError();
|
|
1576
1608
|
}
|
|
1577
|
-
const token = hash3.encode(email);
|
|
1609
|
+
const token = await hash3.encode(email);
|
|
1578
1610
|
const expires = new Date(Date.now() + expiry);
|
|
1579
1611
|
await queries.createResetToken({
|
|
1580
1612
|
accountId: account.id,
|
|
@@ -1602,11 +1634,11 @@ async function confirmResetPassword(config, token, password) {
|
|
|
1602
1634
|
throw new ResetDisabledError();
|
|
1603
1635
|
}
|
|
1604
1636
|
validatePassword(password, config);
|
|
1605
|
-
if (!hash3.verify(token, account.email)) {
|
|
1637
|
+
if (!await hash3.verify(token, account.email)) {
|
|
1606
1638
|
throw new InvalidTokenError();
|
|
1607
1639
|
}
|
|
1608
1640
|
await queries.updateAccount(account.id, {
|
|
1609
|
-
password: hash3.encode(password)
|
|
1641
|
+
password: await hash3.encode(password)
|
|
1610
1642
|
});
|
|
1611
1643
|
await queries.deleteResetToken(token);
|
|
1612
1644
|
return { accountId: account.id, email: account.email };
|
|
@@ -1676,7 +1708,7 @@ var AuthManager = class {
|
|
|
1676
1708
|
}
|
|
1677
1709
|
}
|
|
1678
1710
|
getRoleMap() {
|
|
1679
|
-
return createMapFromEnum(AuthRole);
|
|
1711
|
+
return createMapFromEnum(this.config.roles || AuthRole);
|
|
1680
1712
|
}
|
|
1681
1713
|
getStatusMap() {
|
|
1682
1714
|
return createMapFromEnum(AuthStatus);
|
|
@@ -1827,7 +1859,7 @@ var AuthManager = class {
|
|
|
1827
1859
|
});
|
|
1828
1860
|
}
|
|
1829
1861
|
async createRememberDirective(account) {
|
|
1830
|
-
const token = hash4.encode(account.email);
|
|
1862
|
+
const token = await hash4.encode(account.email);
|
|
1831
1863
|
const duration = this.config.rememberDuration || "30d";
|
|
1832
1864
|
const expires = new Date(Date.now() + ms3(duration));
|
|
1833
1865
|
await this.queries.createRememberToken({
|
|
@@ -1865,7 +1897,7 @@ var AuthManager = class {
|
|
|
1865
1897
|
await this.activityLogger.logActivity(null, AuthActivityAction.FailedLogin, this.req, false, { email, reason: "account_not_found" });
|
|
1866
1898
|
throw new UserNotFoundError();
|
|
1867
1899
|
}
|
|
1868
|
-
if (!account.password || !hash4.verify(account.password, password)) {
|
|
1900
|
+
if (!account.password || !await hash4.verify(account.password, password)) {
|
|
1869
1901
|
await this.activityLogger.logActivity(account.id, AuthActivityAction.FailedLogin, this.req, false, { email, reason: "invalid_password" });
|
|
1870
1902
|
throw new InvalidPasswordError();
|
|
1871
1903
|
}
|
|
@@ -1978,7 +2010,7 @@ var AuthManager = class {
|
|
|
1978
2010
|
throw new EmailTakenError();
|
|
1979
2011
|
}
|
|
1980
2012
|
const finalUserId = userId || this.generateAutoUserId();
|
|
1981
|
-
const hashedPassword = hash4.encode(password);
|
|
2013
|
+
const hashedPassword = await hash4.encode(password);
|
|
1982
2014
|
const verified = typeof callback !== "function";
|
|
1983
2015
|
const account = await this.queries.createAccount({
|
|
1984
2016
|
userId: finalUserId,
|
|
@@ -1995,7 +2027,7 @@ var AuthManager = class {
|
|
|
1995
2027
|
return account;
|
|
1996
2028
|
}
|
|
1997
2029
|
async createConfirmationToken(account, email, callback) {
|
|
1998
|
-
const token = hash4.encode(email);
|
|
2030
|
+
const token = await hash4.encode(email);
|
|
1999
2031
|
const expires = new Date(Date.now() + 1e3 * 60 * 60 * 24 * 7);
|
|
2000
2032
|
await this.queries.createConfirmation({
|
|
2001
2033
|
accountId: account.id,
|
|
@@ -2137,7 +2169,7 @@ var AuthManager = class {
|
|
|
2137
2169
|
if (new Date(confirmation.expires) < /* @__PURE__ */ new Date()) {
|
|
2138
2170
|
throw new ConfirmationExpiredError();
|
|
2139
2171
|
}
|
|
2140
|
-
if (!hash4.verify(token, confirmation.email)) {
|
|
2172
|
+
if (!await hash4.verify(token, confirmation.email)) {
|
|
2141
2173
|
throw new InvalidTokenError();
|
|
2142
2174
|
}
|
|
2143
2175
|
await this.queries.updateAccount(confirmation.account_id, {
|
|
@@ -2235,7 +2267,7 @@ var AuthManager = class {
|
|
|
2235
2267
|
if (openRequests >= maxRequests) {
|
|
2236
2268
|
throw new TooManyResetsError();
|
|
2237
2269
|
}
|
|
2238
|
-
const token = hash4.encode(email);
|
|
2270
|
+
const token = await hash4.encode(email);
|
|
2239
2271
|
const expires = new Date(Date.now() + expiry);
|
|
2240
2272
|
await this.queries.createResetToken({
|
|
2241
2273
|
accountId: account.id,
|
|
@@ -2277,11 +2309,11 @@ var AuthManager = class {
|
|
|
2277
2309
|
throw new ResetDisabledError();
|
|
2278
2310
|
}
|
|
2279
2311
|
this.validatePassword(password);
|
|
2280
|
-
if (!hash4.verify(token, account.email)) {
|
|
2312
|
+
if (!await hash4.verify(token, account.email)) {
|
|
2281
2313
|
throw new InvalidTokenError();
|
|
2282
2314
|
}
|
|
2283
2315
|
await this.queries.updateAccount(account.id, {
|
|
2284
|
-
password: hash4.encode(password)
|
|
2316
|
+
password: await hash4.encode(password)
|
|
2285
2317
|
});
|
|
2286
2318
|
if (logout) {
|
|
2287
2319
|
await this.forceLogoutForAccountById(account.id);
|
|
@@ -2309,7 +2341,7 @@ var AuthManager = class {
|
|
|
2309
2341
|
if (!account.password) {
|
|
2310
2342
|
return false;
|
|
2311
2343
|
}
|
|
2312
|
-
return hash4.verify(account.password, password);
|
|
2344
|
+
return await hash4.verify(account.password, password);
|
|
2313
2345
|
}
|
|
2314
2346
|
async forceLogoutForAccountById(accountId) {
|
|
2315
2347
|
await this.queries.deleteRememberTokensForAccount(accountId);
|
|
@@ -2641,6 +2673,26 @@ function createAuthContext(config) {
|
|
|
2641
2673
|
}
|
|
2642
2674
|
|
|
2643
2675
|
// src/user-roles.ts
|
|
2676
|
+
var MAX_ROLES = 31;
|
|
2677
|
+
function defineRoles(...names) {
|
|
2678
|
+
if (names.length > MAX_ROLES) {
|
|
2679
|
+
throw new Error(`Cannot define more than ${MAX_ROLES} roles (postgres INTEGER is 32-bit signed)`);
|
|
2680
|
+
}
|
|
2681
|
+
if (names.length === 0) {
|
|
2682
|
+
throw new Error("At least one role name is required");
|
|
2683
|
+
}
|
|
2684
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2685
|
+
const roles = {};
|
|
2686
|
+
for (let i = 0; i < names.length; i++) {
|
|
2687
|
+
const name = names[i];
|
|
2688
|
+
if (seen.has(name)) {
|
|
2689
|
+
throw new Error(`Duplicate role name: ${name}`);
|
|
2690
|
+
}
|
|
2691
|
+
seen.add(name);
|
|
2692
|
+
roles[name] = 1 << i;
|
|
2693
|
+
}
|
|
2694
|
+
return Object.freeze(roles);
|
|
2695
|
+
}
|
|
2644
2696
|
async function findAccountByIdentifier2(queries, identifier) {
|
|
2645
2697
|
let account = null;
|
|
2646
2698
|
if (identifier.accountId !== void 0) {
|
|
@@ -2715,6 +2767,7 @@ export {
|
|
|
2715
2767
|
addRoleForUserBy,
|
|
2716
2768
|
addRoleToUser,
|
|
2717
2769
|
auth_functions_exports as authFunctions,
|
|
2770
|
+
authenticateRequest,
|
|
2718
2771
|
changePasswordForUserBy,
|
|
2719
2772
|
cleanupExpiredTokens,
|
|
2720
2773
|
confirmResetPassword,
|
|
@@ -2722,6 +2775,7 @@ export {
|
|
|
2722
2775
|
createAuthMiddleware,
|
|
2723
2776
|
createAuthTables,
|
|
2724
2777
|
createUser,
|
|
2778
|
+
defineRoles,
|
|
2725
2779
|
deleteUserBy,
|
|
2726
2780
|
dropAuthTables,
|
|
2727
2781
|
forceLogoutForUserBy,
|