@soapjs/soap-auth 0.3.3 → 0.4.4
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/.claude/settings.local.json +20 -0
- package/build/errors.d.ts +1 -1
- package/build/errors.js +2 -2
- package/build/index.d.ts +1 -0
- package/build/index.js +1 -0
- package/build/services/auth-throttle.service.d.ts +2 -2
- package/build/services/auth-throttle.service.js +2 -2
- package/build/services/index.d.ts +1 -0
- package/build/services/index.js +1 -0
- package/build/services/password.service.d.ts +7 -5
- package/build/services/password.service.js +76 -18
- package/build/services/totp.service.d.ts +16 -0
- package/build/services/totp.service.js +96 -0
- package/build/session/session-handler.d.ts +1 -0
- package/build/session/session-handler.js +39 -6
- package/build/soap-auth.d.ts +13 -6
- package/build/soap-auth.js +132 -5
- package/build/strategies/api-key/api-key.strategy.d.ts +4 -4
- package/build/strategies/api-key/api-key.strategy.js +3 -2
- package/build/strategies/base-auth.strategy.d.ts +5 -4
- package/build/strategies/basic/basic.strategy.d.ts +2 -1
- package/build/strategies/basic/basic.strategy.js +1 -0
- package/build/strategies/credential-auth.strategy.d.ts +7 -7
- package/build/strategies/credential-auth.strategy.js +9 -14
- package/build/strategies/index.d.ts +1 -0
- package/build/strategies/index.js +1 -0
- package/build/strategies/jwt/jwt.strategy.d.ts +3 -1
- package/build/strategies/jwt/jwt.strategy.js +41 -9
- package/build/strategies/jwt/jwt.tools.js +16 -14
- package/build/strategies/local/local.strategy.d.ts +6 -3
- package/build/strategies/local/local.strategy.js +83 -2
- package/build/strategies/oauth2/hybrid.oauth2.strategy.d.ts +3 -3
- package/build/strategies/oauth2/hybrid.oauth2.strategy.js +1 -6
- package/build/strategies/oauth2/oauth2.errors.d.ts +1 -0
- package/build/strategies/oauth2/oauth2.errors.js +4 -0
- package/build/strategies/oauth2/oauth2.strategy.d.ts +6 -4
- package/build/strategies/oauth2/oauth2.strategy.js +114 -46
- package/build/strategies/oauth2/oauth2.tools.js +2 -2
- package/build/strategies/oauth2/oauth2.types.d.ts +2 -2
- package/build/strategies/oauth2/providers/facebook.strategy.d.ts +11 -0
- package/build/strategies/oauth2/providers/facebook.strategy.js +58 -0
- package/build/strategies/oauth2/providers/github.strategy.d.ts +11 -0
- package/build/strategies/oauth2/providers/github.strategy.js +56 -0
- package/build/strategies/oauth2/providers/google.strategy.d.ts +11 -0
- package/build/strategies/oauth2/providers/google.strategy.js +52 -0
- package/build/strategies/oauth2/providers/http-oauth2.strategy.d.ts +16 -0
- package/build/strategies/oauth2/providers/http-oauth2.strategy.js +49 -0
- package/build/strategies/oauth2/providers/index.d.ts +5 -0
- package/build/strategies/oauth2/providers/index.js +21 -0
- package/build/strategies/oauth2/providers/provider.types.d.ts +7 -0
- package/build/strategies/oauth2/providers/provider.types.js +2 -0
- package/build/strategies/token-auth.strategy.d.ts +4 -4
- package/build/strategies/token-auth.strategy.js +2 -3
- package/build/tools/tools.js +1 -2
- package/build/types.d.ts +31 -32
- package/build/utils/validation.d.ts +23 -0
- package/build/utils/validation.js +139 -0
- package/package.json +8 -7
- package/build/__tests__/soap-auth.test.d.ts +0 -1
- package/build/__tests__/soap-auth.test.js +0 -42
- package/build/services/__tests__/account-lock.service.test.d.ts +0 -1
- package/build/services/__tests__/account-lock.service.test.js +0 -55
- package/build/services/__tests__/auth-throttle.service.test.d.ts +0 -1
- package/build/services/__tests__/auth-throttle.service.test.js +0 -48
- package/build/services/__tests__/jwks.service.test.d.ts +0 -1
- package/build/services/__tests__/jwks.service.test.js +0 -39
- package/build/services/__tests__/mfa.service.test.d.ts +0 -1
- package/build/services/__tests__/mfa.service.test.js +0 -66
- package/build/services/__tests__/password.service.test.d.ts +0 -1
- package/build/services/__tests__/password.service.test.js +0 -66
- package/build/services/__tests__/pkce.service.test.d.ts +0 -1
- package/build/services/__tests__/pkce.service.test.js +0 -77
- package/build/services/__tests__/rate-limit.service.test.d.ts +0 -1
- package/build/services/__tests__/rate-limit.service.test.js +0 -37
- package/build/services/__tests__/role.service.test.d.ts +0 -1
- package/build/services/__tests__/role.service.test.js +0 -31
- package/build/session/__tests__/file.session-store.test.d.ts +0 -1
- package/build/session/__tests__/file.session-store.test.js +0 -117
- package/build/session/__tests__/memory.session-store.test.d.ts +0 -1
- package/build/session/__tests__/memory.session-store.test.js +0 -77
- package/build/session/__tests__/session-handler.test.d.ts +0 -1
- package/build/session/__tests__/session-handler.test.js +0 -337
- package/build/strategies/__tests__/base-auth.strategy.test.d.ts +0 -14
- package/build/strategies/__tests__/base-auth.strategy.test.js +0 -137
- package/build/strategies/__tests__/credential-auth.strategy.test.d.ts +0 -14
- package/build/strategies/__tests__/credential-auth.strategy.test.js +0 -265
- package/build/strategies/__tests__/token-auth.strategy.test.d.ts +0 -28
- package/build/strategies/__tests__/token-auth.strategy.test.js +0 -298
- package/build/strategies/api-key/__tests__/api-key.strategy.test.d.ts +0 -1
- package/build/strategies/api-key/__tests__/api-key.strategy.test.js +0 -103
- package/build/strategies/basic/__tests__/basic.strategy.test.d.ts +0 -1
- package/build/strategies/basic/__tests__/basic.strategy.test.js +0 -104
- package/build/strategies/jwt/__tests__/jwt.strategy.test.d.ts +0 -1
- package/build/strategies/jwt/__tests__/jwt.strategy.test.js +0 -156
- package/build/strategies/jwt/__tests__/jwt.tools.test.d.ts +0 -1
- package/build/strategies/jwt/__tests__/jwt.tools.test.js +0 -98
- package/build/strategies/local/__tests__/local.strategy.test.d.ts +0 -1
- package/build/strategies/local/__tests__/local.strategy.test.js +0 -115
package/build/soap-auth.js
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SoapAuth = void 0;
|
|
4
|
+
const validation_1 = require("./utils/validation");
|
|
5
|
+
const session_handler_1 = require("./session/session-handler");
|
|
6
|
+
const jwt_strategy_1 = require("./strategies/jwt/jwt.strategy");
|
|
7
|
+
const local_strategy_1 = require("./strategies/local/local.strategy");
|
|
8
|
+
const basic_strategy_1 = require("./strategies/basic/basic.strategy");
|
|
9
|
+
const api_key_strategy_1 = require("./strategies/api-key/api-key.strategy");
|
|
4
10
|
class SoapAuth {
|
|
5
|
-
requiredStrategyMethods = ["authenticate"
|
|
11
|
+
requiredStrategyMethods = ["authenticate"];
|
|
6
12
|
strategies = new Map();
|
|
7
13
|
logger;
|
|
8
14
|
constructor(config) {
|
|
15
|
+
this.validateConfig(config);
|
|
9
16
|
this.strategies.set("http", new Map());
|
|
10
17
|
this.strategies.set("socket", new Map());
|
|
11
18
|
this.strategies.set("event", new Map());
|
|
@@ -15,12 +22,83 @@ class SoapAuth {
|
|
|
15
22
|
this.strategies.set("edge", new Map());
|
|
16
23
|
this.logger = config.logger;
|
|
17
24
|
}
|
|
25
|
+
validateConfig(config) {
|
|
26
|
+
try {
|
|
27
|
+
validation_1.ValidationUtils.required(config, "config");
|
|
28
|
+
if (config.logger) {
|
|
29
|
+
validation_1.ValidationUtils.object(config.logger, "config.logger");
|
|
30
|
+
}
|
|
31
|
+
if (config.session) {
|
|
32
|
+
this.validateSessionConfig(config.session);
|
|
33
|
+
}
|
|
34
|
+
if (config.jwt) {
|
|
35
|
+
this.validateJwtConfig(config.jwt);
|
|
36
|
+
}
|
|
37
|
+
if (config.http) {
|
|
38
|
+
this.validateHttpStrategies(config.http);
|
|
39
|
+
}
|
|
40
|
+
if (config.socket) {
|
|
41
|
+
this.validateSocketStrategies(config.socket);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
if (error instanceof validation_1.ValidationError) {
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
throw new validation_1.ValidationError(`Invalid configuration: ${error.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
validateSessionConfig(session) {
|
|
52
|
+
validation_1.ValidationUtils.required(session.secret, "session.secret");
|
|
53
|
+
validation_1.ValidationUtils.nonEmptyString(session.secret, "session.secret");
|
|
54
|
+
if (session.sessionKey) {
|
|
55
|
+
validation_1.ValidationUtils.nonEmptyString(session.sessionKey, "session.sessionKey");
|
|
56
|
+
}
|
|
57
|
+
if (session.sessionHeader) {
|
|
58
|
+
validation_1.ValidationUtils.nonEmptyString(session.sessionHeader, "session.sessionHeader");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
validateJwtConfig(jwt) {
|
|
62
|
+
if (jwt.accessToken) {
|
|
63
|
+
validation_1.ValidationUtils.required(jwt.accessToken.issuer, "jwt.accessToken.issuer");
|
|
64
|
+
validation_1.ValidationUtils.required(jwt.accessToken.issuer.secretKey, "jwt.accessToken.issuer.secretKey");
|
|
65
|
+
validation_1.ValidationUtils.nonEmptyString(jwt.accessToken.issuer.secretKey, "jwt.accessToken.issuer.secretKey");
|
|
66
|
+
}
|
|
67
|
+
if (jwt.refreshToken) {
|
|
68
|
+
validation_1.ValidationUtils.required(jwt.refreshToken.issuer, "jwt.refreshToken.issuer");
|
|
69
|
+
validation_1.ValidationUtils.required(jwt.refreshToken.issuer.secretKey, "jwt.refreshToken.issuer.secretKey");
|
|
70
|
+
validation_1.ValidationUtils.nonEmptyString(jwt.refreshToken.issuer.secretKey, "jwt.refreshToken.issuer.secretKey");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
validateHttpStrategies(http) {
|
|
74
|
+
validation_1.ValidationUtils.object(http, "http");
|
|
75
|
+
if (http.custom) {
|
|
76
|
+
validation_1.ValidationUtils.object(http.custom, "http.custom");
|
|
77
|
+
for (const [name, strategy] of Object.entries(http.custom)) {
|
|
78
|
+
validation_1.ValidationUtils.required(strategy, `http.custom.${name}`);
|
|
79
|
+
validation_1.ValidationUtils.object(strategy, `http.custom.${name}`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
validateSocketStrategies(socket) {
|
|
84
|
+
validation_1.ValidationUtils.object(socket, "socket");
|
|
85
|
+
if (socket.custom) {
|
|
86
|
+
validation_1.ValidationUtils.object(socket.custom, "socket.custom");
|
|
87
|
+
for (const [name, strategy] of Object.entries(socket.custom)) {
|
|
88
|
+
validation_1.ValidationUtils.required(strategy, `socket.custom.${name}`);
|
|
89
|
+
validation_1.ValidationUtils.object(strategy, `socket.custom.${name}`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
18
93
|
isAuthStrategy(strategy) {
|
|
19
94
|
return (typeof strategy === "object" &&
|
|
20
95
|
strategy !== null &&
|
|
21
96
|
this.requiredStrategyMethods.every((method) => typeof strategy[method] === "function"));
|
|
22
97
|
}
|
|
23
98
|
addStrategy(strategyInstance, name, type) {
|
|
99
|
+
validation_1.ValidationUtils.required(strategyInstance, "strategyInstance");
|
|
100
|
+
validation_1.ValidationUtils.nonEmptyString(name, "name");
|
|
101
|
+
validation_1.ValidationUtils.oneOf(type, "type", ["http", "socket", "event", "isa", "webhook", "grpc", "edge"]);
|
|
24
102
|
if (!this.strategies.has(type)) {
|
|
25
103
|
throw new Error(`Invalid strategy type "${type}".`);
|
|
26
104
|
}
|
|
@@ -33,21 +111,28 @@ class SoapAuth {
|
|
|
33
111
|
}
|
|
34
112
|
}
|
|
35
113
|
removeStrategy(name, type) {
|
|
114
|
+
validation_1.ValidationUtils.required(name, "name");
|
|
115
|
+
validation_1.ValidationUtils.oneOf(type, "type", ["http", "socket", "event", "isa", "webhook", "grpc", "edge"]);
|
|
36
116
|
if (!this.strategies.has(type)) {
|
|
37
117
|
throw new Error(`Invalid strategy type "${type}".`);
|
|
38
118
|
}
|
|
39
119
|
const names = Array.isArray(name) ? name : [name];
|
|
40
120
|
names.forEach((n) => {
|
|
121
|
+
validation_1.ValidationUtils.nonEmptyString(n, "strategy name");
|
|
41
122
|
this.strategies.get(type).delete(n);
|
|
42
123
|
});
|
|
43
124
|
}
|
|
44
125
|
hasStrategy(name, type) {
|
|
126
|
+
validation_1.ValidationUtils.nonEmptyString(name, "name");
|
|
127
|
+
validation_1.ValidationUtils.oneOf(type, "type", ["http", "socket", "event", "isa", "webhook", "grpc", "edge"]);
|
|
45
128
|
if (!this.strategies.has(type)) {
|
|
46
129
|
throw new Error(`Invalid strategy type "${type}".`);
|
|
47
130
|
}
|
|
48
131
|
return this.strategies.get(type).has(name);
|
|
49
132
|
}
|
|
50
133
|
getStrategy(name, type) {
|
|
134
|
+
validation_1.ValidationUtils.nonEmptyString(name, "name");
|
|
135
|
+
validation_1.ValidationUtils.oneOf(type, "type", ["http", "socket", "event", "isa", "webhook", "grpc", "edge"]);
|
|
51
136
|
if (!this.strategies.has(type)) {
|
|
52
137
|
throw new Error(`Invalid strategy type "${type}".`);
|
|
53
138
|
}
|
|
@@ -101,7 +186,7 @@ class SoapAuth {
|
|
|
101
186
|
if (sequential) {
|
|
102
187
|
for (const strategy of strategies) {
|
|
103
188
|
try {
|
|
104
|
-
await strategy.init();
|
|
189
|
+
await strategy.init?.();
|
|
105
190
|
}
|
|
106
191
|
catch (error) {
|
|
107
192
|
this.logger?.error(`Failed to initialize strategy: ${error.message}`);
|
|
@@ -109,10 +194,52 @@ class SoapAuth {
|
|
|
109
194
|
}
|
|
110
195
|
}
|
|
111
196
|
else {
|
|
112
|
-
await Promise.all(strategies.map((strategy) => strategy
|
|
113
|
-
|
|
114
|
-
|
|
197
|
+
await Promise.all(strategies.map((strategy) => Promise.resolve(strategy.init?.()).catch((error) => this.logger?.error(`Failed to initialize strategy: ${error.message}`))));
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
static async create(config) {
|
|
201
|
+
const auth = new SoapAuth(config);
|
|
202
|
+
const logger = config.logger;
|
|
203
|
+
const sessionHandler = config.session
|
|
204
|
+
? new session_handler_1.SessionHandler(config.session, logger)
|
|
205
|
+
: undefined;
|
|
206
|
+
if (config.http) {
|
|
207
|
+
const sharedJwt = config.http.jwt
|
|
208
|
+
? new jwt_strategy_1.JwtStrategy(config.http.jwt, logger)
|
|
209
|
+
: undefined;
|
|
210
|
+
if (config.http.local) {
|
|
211
|
+
auth.addStrategy(new local_strategy_1.LocalStrategy(config.http.local, sessionHandler, sharedJwt, logger), "local", "http");
|
|
212
|
+
}
|
|
213
|
+
if (config.http.basic) {
|
|
214
|
+
auth.addStrategy(new basic_strategy_1.BasicStrategy(config.http.basic, sessionHandler, sharedJwt, logger), "basic", "http");
|
|
215
|
+
}
|
|
216
|
+
if (config.http.apiKey) {
|
|
217
|
+
auth.addStrategy(new api_key_strategy_1.ApiKeyStrategy(config.http.apiKey, logger), "api-key", "http");
|
|
218
|
+
}
|
|
219
|
+
if (sharedJwt) {
|
|
220
|
+
auth.addStrategy(sharedJwt, "jwt", "http");
|
|
221
|
+
}
|
|
222
|
+
if (config.http.custom) {
|
|
223
|
+
for (const [name, strategy] of Object.entries(config.http.custom)) {
|
|
224
|
+
auth.addStrategy(strategy, name, "http");
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
if (config.socket) {
|
|
229
|
+
if (config.socket.jwt) {
|
|
230
|
+
auth.addStrategy(new jwt_strategy_1.JwtStrategy(config.socket.jwt, logger), "jwt", "socket");
|
|
231
|
+
}
|
|
232
|
+
if (config.socket.apiKey) {
|
|
233
|
+
auth.addStrategy(new api_key_strategy_1.ApiKeyStrategy(config.socket.apiKey, logger), "api-key", "socket");
|
|
234
|
+
}
|
|
235
|
+
if (config.socket.custom) {
|
|
236
|
+
for (const [name, strategy] of Object.entries(config.socket.custom)) {
|
|
237
|
+
auth.addStrategy(strategy, name, "socket");
|
|
238
|
+
}
|
|
239
|
+
}
|
|
115
240
|
}
|
|
241
|
+
await auth.init();
|
|
242
|
+
return auth;
|
|
116
243
|
}
|
|
117
244
|
}
|
|
118
245
|
exports.SoapAuth = SoapAuth;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import * as Soap from "@soapjs/soap";
|
|
2
|
-
import { AuthResult, AuthStrategy } from "../../types";
|
|
3
2
|
import { ApiKeyStrategyConfig } from "./api-key.types";
|
|
4
3
|
import { BaseAuthStrategy } from "../base-auth.strategy";
|
|
5
|
-
export declare class ApiKeyStrategy<TContext =
|
|
4
|
+
export declare class ApiKeyStrategy<TContext = Soap.HttpContext, TUser extends Soap.AuthUser = Soap.AuthUser> extends BaseAuthStrategy<TContext, TUser> {
|
|
6
5
|
protected config: ApiKeyStrategyConfig<TContext, TUser>;
|
|
6
|
+
readonly name = "api-key";
|
|
7
7
|
protected apiKeyValidity: {
|
|
8
8
|
sessionDuration: number;
|
|
9
9
|
longTermDuration: number;
|
|
10
10
|
};
|
|
11
|
-
constructor(config: ApiKeyStrategyConfig<TContext, TUser>, logger
|
|
11
|
+
constructor(config: ApiKeyStrategyConfig<TContext, TUser>, logger?: Soap.Logger);
|
|
12
12
|
protected fetchUser(apiKey: string, context: TContext): Promise<TUser | null>;
|
|
13
13
|
init(): Promise<void>;
|
|
14
|
-
authenticate(context?: TContext): Promise<AuthResult<TUser
|
|
14
|
+
authenticate(context?: TContext): Promise<Soap.AuthResult<TUser> | null>;
|
|
15
15
|
authorize(user: TUser, action: string, resource?: string): Promise<boolean>;
|
|
16
16
|
revoke(apiKey: string): Promise<void>;
|
|
17
17
|
private trackApiKeyUsage;
|
|
@@ -7,6 +7,7 @@ const base_auth_strategy_1 = require("../base-auth.strategy");
|
|
|
7
7
|
const api_key_tools_1 = require("./api-key.tools");
|
|
8
8
|
class ApiKeyStrategy extends base_auth_strategy_1.BaseAuthStrategy {
|
|
9
9
|
config;
|
|
10
|
+
name = "api-key";
|
|
10
11
|
apiKeyValidity;
|
|
11
12
|
constructor(config, logger) {
|
|
12
13
|
super((0, api_key_tools_1.prepareApiKeyConfig)(config), null, logger);
|
|
@@ -28,7 +29,7 @@ class ApiKeyStrategy extends base_auth_strategy_1.BaseAuthStrategy {
|
|
|
28
29
|
return user;
|
|
29
30
|
}
|
|
30
31
|
catch (error) {
|
|
31
|
-
this.logger
|
|
32
|
+
this.logger?.warn(`Attempt ${attempt + 1} failed: ${error}`);
|
|
32
33
|
if (attempt < maxRetries) {
|
|
33
34
|
await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
34
35
|
}
|
|
@@ -99,7 +100,7 @@ class ApiKeyStrategy extends base_auth_strategy_1.BaseAuthStrategy {
|
|
|
99
100
|
await this.config.trackApiKeyUsage?.(apiKey);
|
|
100
101
|
}
|
|
101
102
|
catch (error) {
|
|
102
|
-
this.logger
|
|
103
|
+
this.logger?.warn("Failed to track API key usage:", error);
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import * as Soap from "@soapjs/soap";
|
|
2
|
-
import { AuthFailureContext,
|
|
2
|
+
import { AuthFailureContext, AuthSuccessContext, BaseAuthStrategyConfig } from "../types";
|
|
3
3
|
import { SessionHandler } from "../session/session-handler";
|
|
4
4
|
import { AccountLockService } from "../services/account-lock.service";
|
|
5
5
|
import { MfaService } from "../services/mfa.service";
|
|
6
6
|
import { RateLimitService } from "../services/rate-limit.service";
|
|
7
7
|
import { RoleService } from "../services/role.service";
|
|
8
8
|
import { AuthThrottleService } from "../services/auth-throttle.service";
|
|
9
|
-
export declare abstract class BaseAuthStrategy<TContext =
|
|
9
|
+
export declare abstract class BaseAuthStrategy<TContext = Soap.HttpContext, TUser extends Soap.AuthUser = Soap.AuthUser> {
|
|
10
10
|
protected config: BaseAuthStrategyConfig<TContext, TUser>;
|
|
11
11
|
protected session?: SessionHandler;
|
|
12
12
|
protected logger?: Soap.Logger;
|
|
@@ -15,10 +15,11 @@ export declare abstract class BaseAuthStrategy<TContext = unknown, TUser = unkno
|
|
|
15
15
|
protected rateLimit: RateLimitService;
|
|
16
16
|
protected role: RoleService<TUser>;
|
|
17
17
|
protected throttle: AuthThrottleService;
|
|
18
|
-
abstract
|
|
18
|
+
abstract readonly name: string;
|
|
19
|
+
abstract authenticate(ctx: TContext): Promise<Soap.AuthResult<TUser> | null>;
|
|
19
20
|
constructor(config: BaseAuthStrategyConfig<TContext, TUser>, session?: SessionHandler, logger?: Soap.Logger);
|
|
20
21
|
init(): Promise<void>;
|
|
21
22
|
protected onSuccess(action: string, context: AuthSuccessContext<TUser, TContext>): Promise<void>;
|
|
22
23
|
protected onFailure(action: string, context: AuthFailureContext<TContext>): Promise<void>;
|
|
23
|
-
protected authenticateWithSession(context: TContext): Promise<AuthResult<TUser>>;
|
|
24
|
+
protected authenticateWithSession(context: TContext): Promise<Soap.AuthResult<TUser>>;
|
|
24
25
|
}
|
|
@@ -3,11 +3,12 @@ import { CredentialAuthStrategy } from "../credential-auth.strategy";
|
|
|
3
3
|
import { BasicStrategyConfig } from "./basic.types";
|
|
4
4
|
import { SessionHandler } from "../../session/session-handler";
|
|
5
5
|
import { JwtStrategy } from "../jwt/jwt.strategy";
|
|
6
|
-
export declare class BasicStrategy<TContext =
|
|
6
|
+
export declare class BasicStrategy<TContext = Soap.HttpContext, TUser extends Soap.AuthUser = Soap.AuthUser> extends CredentialAuthStrategy<TContext, TUser> {
|
|
7
7
|
protected config: BasicStrategyConfig<TContext, TUser>;
|
|
8
8
|
protected session?: SessionHandler;
|
|
9
9
|
protected jwt?: JwtStrategy<TContext, TUser>;
|
|
10
10
|
protected logger?: Soap.Logger;
|
|
11
|
+
readonly name = "basic";
|
|
11
12
|
constructor(config: BasicStrategyConfig<TContext, TUser>, session?: SessionHandler, jwt?: JwtStrategy<TContext, TUser>, logger?: Soap.Logger);
|
|
12
13
|
protected extractCredentials(context?: TContext): {
|
|
13
14
|
identifier: string;
|
|
@@ -9,6 +9,7 @@ class BasicStrategy extends credential_auth_strategy_1.CredentialAuthStrategy {
|
|
|
9
9
|
session;
|
|
10
10
|
jwt;
|
|
11
11
|
logger;
|
|
12
|
+
name = "basic";
|
|
12
13
|
constructor(config, session, jwt, logger) {
|
|
13
14
|
super((0, basic_tools_1.prepareBasicConfig)(config), session, jwt, logger);
|
|
14
15
|
this.config = config;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as Soap from "@soapjs/soap";
|
|
2
|
-
import {
|
|
2
|
+
import { CredentialAuthStrategyConfig, NewPasswordOptions } from "../types";
|
|
3
3
|
import { BaseAuthStrategy } from "./base-auth.strategy";
|
|
4
4
|
import { SessionHandler } from "../session/session-handler";
|
|
5
5
|
import { JwtStrategy } from "./jwt/jwt.strategy";
|
|
6
6
|
import { PasswordService } from "../services/password.service";
|
|
7
|
-
export declare abstract class CredentialAuthStrategy<TContext =
|
|
7
|
+
export declare abstract class CredentialAuthStrategy<TContext = Soap.HttpContext, TUser extends Soap.AuthUser = Soap.AuthUser> extends BaseAuthStrategy<TContext, TUser> {
|
|
8
8
|
protected config: CredentialAuthStrategyConfig<TContext, TUser>;
|
|
9
9
|
protected session?: SessionHandler;
|
|
10
10
|
protected jwt?: JwtStrategy<TContext, TUser>;
|
|
@@ -14,10 +14,10 @@ export declare abstract class CredentialAuthStrategy<TContext = unknown, TUser =
|
|
|
14
14
|
protected abstract extractCredentials(context: TContext): any;
|
|
15
15
|
constructor(config: CredentialAuthStrategyConfig<TContext, TUser>, session?: SessionHandler, jwt?: JwtStrategy<TContext, TUser>, logger?: Soap.Logger);
|
|
16
16
|
protected fetchUser(payload: unknown): Promise<TUser | null>;
|
|
17
|
-
authenticate(context: TContext): Promise<AuthResult<TUser
|
|
18
|
-
login(context: TContext): Promise<AuthResult<TUser>>;
|
|
17
|
+
authenticate(context: TContext): Promise<Soap.AuthResult<TUser> | null>;
|
|
18
|
+
login(context: TContext): Promise<Soap.AuthResult<TUser>>;
|
|
19
19
|
logout(context: TContext): Promise<void>;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
requestPasswordResetLink(identifier: string, email?: string): Promise<void>;
|
|
21
|
+
resetPasswordWithToken(identifier: string, token: string, newPassword: string, passwordOptions?: NewPasswordOptions): Promise<void>;
|
|
22
|
+
replacePassword(identifier: string, oldPassword: string, newPassword: string, options?: NewPasswordOptions): Promise<void>;
|
|
23
23
|
}
|
|
@@ -126,7 +126,7 @@ class CredentialAuthStrategy extends base_auth_strategy_1.BaseAuthStrategy {
|
|
|
126
126
|
throw error;
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
|
-
async
|
|
129
|
+
async requestPasswordResetLink(identifier, email) {
|
|
130
130
|
try {
|
|
131
131
|
const token = await this.password.generateResetToken(identifier);
|
|
132
132
|
if (email) {
|
|
@@ -136,7 +136,7 @@ class CredentialAuthStrategy extends base_auth_strategy_1.BaseAuthStrategy {
|
|
|
136
136
|
identifier,
|
|
137
137
|
tokens: { reset: token },
|
|
138
138
|
});
|
|
139
|
-
this.logger
|
|
139
|
+
this.logger?.info(`Password reset requested for identifier: ${identifier}`);
|
|
140
140
|
}
|
|
141
141
|
catch (error) {
|
|
142
142
|
await this.onFailure("request_password_reset", {
|
|
@@ -147,17 +147,12 @@ class CredentialAuthStrategy extends base_auth_strategy_1.BaseAuthStrategy {
|
|
|
147
147
|
throw error;
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
-
async
|
|
150
|
+
async resetPasswordWithToken(identifier, token, newPassword, passwordOptions) {
|
|
151
151
|
try {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
if ((await this.password.validateResetToken(token)) === false) {
|
|
156
|
-
throw new errors_1.ExpiredResetTokenError();
|
|
157
|
-
}
|
|
158
|
-
await this.password.updatePassword(identifier, newPassword);
|
|
152
|
+
await this.password?.validateResetToken(token);
|
|
153
|
+
await this.password.updatePassword(identifier, newPassword, passwordOptions);
|
|
159
154
|
await this.onSuccess("password_reset", { identifier });
|
|
160
|
-
this.logger
|
|
155
|
+
this.logger?.info(`Password successfully reset for identifier: ${identifier}`);
|
|
161
156
|
}
|
|
162
157
|
catch (error) {
|
|
163
158
|
await this.onFailure("password_reset", {
|
|
@@ -168,14 +163,14 @@ class CredentialAuthStrategy extends base_auth_strategy_1.BaseAuthStrategy {
|
|
|
168
163
|
throw error;
|
|
169
164
|
}
|
|
170
165
|
}
|
|
171
|
-
async
|
|
166
|
+
async replacePassword(identifier, oldPassword, newPassword, options) {
|
|
172
167
|
try {
|
|
173
168
|
if (!(await this.verifyCredentials(identifier, oldPassword))) {
|
|
174
169
|
throw new errors_1.InvalidCredentialsError();
|
|
175
170
|
}
|
|
176
|
-
await this.password.updatePassword(identifier, newPassword);
|
|
171
|
+
await this.password.updatePassword(identifier, newPassword, options);
|
|
177
172
|
await this.onSuccess("change_password", { identifier });
|
|
178
|
-
this.logger
|
|
173
|
+
this.logger?.info(`Password changed successfully for identifier: ${identifier}`);
|
|
179
174
|
}
|
|
180
175
|
catch (error) {
|
|
181
176
|
await this.onFailure("change_password", {
|
|
@@ -29,4 +29,5 @@ __exportStar(require("./local/local.types"), exports);
|
|
|
29
29
|
__exportStar(require("./oauth2/oauth2.strategy"), exports);
|
|
30
30
|
__exportStar(require("./oauth2/oauth2.tools"), exports);
|
|
31
31
|
__exportStar(require("./oauth2/oauth2.types"), exports);
|
|
32
|
+
__exportStar(require("./oauth2/providers"), exports);
|
|
32
33
|
__exportStar(require("./token-auth.strategy"), exports);
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import * as Soap from "@soapjs/soap";
|
|
2
2
|
import { TokenAuthStrategy } from "../token-auth.strategy";
|
|
3
3
|
import { TokenAuthStrategyConfig, TokenConfig } from "../../types";
|
|
4
|
-
export declare class JwtStrategy<TContext =
|
|
4
|
+
export declare class JwtStrategy<TContext = Soap.HttpContext, TUser extends Soap.AuthUser = Soap.AuthUser> extends TokenAuthStrategy<TContext, TUser> {
|
|
5
5
|
protected config: TokenAuthStrategyConfig<TContext, TUser>;
|
|
6
6
|
protected logger?: Soap.Logger;
|
|
7
|
+
readonly name = "jwt";
|
|
7
8
|
protected accessTokenConfig: TokenConfig<TContext>;
|
|
8
9
|
protected refreshTokenConfig: TokenConfig<TContext>;
|
|
9
10
|
constructor(config: TokenAuthStrategyConfig<TContext, TUser>, logger?: Soap.Logger);
|
|
11
|
+
private static validateConfig;
|
|
10
12
|
protected verifyAccessToken(token: string): Promise<any>;
|
|
11
13
|
protected verifyRefreshToken(token: string): Promise<any>;
|
|
12
14
|
protected generateAccessToken(user: TUser, context: TContext): Promise<string>;
|
|
@@ -8,12 +8,15 @@ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
|
8
8
|
const token_auth_strategy_1 = require("../token-auth.strategy");
|
|
9
9
|
const errors_1 = require("../../errors");
|
|
10
10
|
const jwt_tools_1 = require("./jwt.tools");
|
|
11
|
+
const validation_1 = require("../../utils/validation");
|
|
11
12
|
class JwtStrategy extends token_auth_strategy_1.TokenAuthStrategy {
|
|
12
13
|
config;
|
|
13
14
|
logger;
|
|
15
|
+
name = "jwt";
|
|
14
16
|
accessTokenConfig;
|
|
15
17
|
refreshTokenConfig;
|
|
16
18
|
constructor(config, logger) {
|
|
19
|
+
JwtStrategy.validateConfig(config);
|
|
17
20
|
if (!config.accessToken.issuer.secretKey) {
|
|
18
21
|
throw new errors_1.UndefinedTokenSecretError("Access");
|
|
19
22
|
}
|
|
@@ -24,13 +27,39 @@ class JwtStrategy extends token_auth_strategy_1.TokenAuthStrategy {
|
|
|
24
27
|
this.config = config;
|
|
25
28
|
this.logger = logger;
|
|
26
29
|
this.accessTokenConfig = jwt_tools_1.JwtTools.prepareAccessTokenConfig(config.accessToken);
|
|
27
|
-
|
|
30
|
+
if (config.refreshToken) {
|
|
31
|
+
this.refreshTokenConfig = jwt_tools_1.JwtTools.prepareRefreshTokenConfig(config.refreshToken);
|
|
32
|
+
}
|
|
28
33
|
this.logger?.info("JWTStrategy initialized with provided configurations.");
|
|
29
34
|
}
|
|
35
|
+
static validateConfig(config) {
|
|
36
|
+
try {
|
|
37
|
+
validation_1.ValidationUtils.required(config, "config");
|
|
38
|
+
validation_1.ValidationUtils.required(config.accessToken, "config.accessToken");
|
|
39
|
+
validation_1.ValidationUtils.required(config.accessToken.issuer, "config.accessToken.issuer");
|
|
40
|
+
validation_1.ValidationUtils.required(config.accessToken.issuer.secretKey, "config.accessToken.issuer.secretKey");
|
|
41
|
+
validation_1.ValidationUtils.nonEmptyString(config.accessToken.issuer.secretKey, "config.accessToken.issuer.secretKey");
|
|
42
|
+
if (config.refreshToken) {
|
|
43
|
+
validation_1.ValidationUtils.required(config.refreshToken.issuer, "config.refreshToken.issuer");
|
|
44
|
+
validation_1.ValidationUtils.required(config.refreshToken.issuer.secretKey, "config.refreshToken.issuer.secretKey");
|
|
45
|
+
validation_1.ValidationUtils.nonEmptyString(config.refreshToken.issuer.secretKey, "config.refreshToken.issuer.secretKey");
|
|
46
|
+
}
|
|
47
|
+
if (config.user) {
|
|
48
|
+
validation_1.ValidationUtils.required(config.user.fetchUser, "config.user.fetchUser");
|
|
49
|
+
validation_1.ValidationUtils.function(config.user.fetchUser, "config.user.fetchUser");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
if (error instanceof validation_1.ValidationError) {
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
throw new validation_1.ValidationError(`Invalid JWT configuration: ${error.message}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
30
59
|
verifyAccessToken(token) {
|
|
31
60
|
try {
|
|
32
|
-
|
|
33
|
-
|
|
61
|
+
validation_1.ValidationUtils.required(token, "token");
|
|
62
|
+
validation_1.ValidationUtils.jwtToken(token, "token");
|
|
34
63
|
if (!this.accessTokenConfig.issuer.secretKey)
|
|
35
64
|
throw new errors_1.UndefinedTokenSecretError("Access");
|
|
36
65
|
return new Promise((resolve, reject) => {
|
|
@@ -49,8 +78,8 @@ class JwtStrategy extends token_auth_strategy_1.TokenAuthStrategy {
|
|
|
49
78
|
}
|
|
50
79
|
verifyRefreshToken(token) {
|
|
51
80
|
try {
|
|
52
|
-
|
|
53
|
-
|
|
81
|
+
validation_1.ValidationUtils.required(token, "token");
|
|
82
|
+
validation_1.ValidationUtils.jwtToken(token, "token");
|
|
54
83
|
if (!this.refreshTokenConfig.issuer.secretKey)
|
|
55
84
|
throw new errors_1.UndefinedTokenSecretError("Refresh");
|
|
56
85
|
return new Promise((resolve, reject) => {
|
|
@@ -64,7 +93,7 @@ class JwtStrategy extends token_auth_strategy_1.TokenAuthStrategy {
|
|
|
64
93
|
}
|
|
65
94
|
catch (error) {
|
|
66
95
|
this.logger?.error("JWT verification failed:", error);
|
|
67
|
-
error;
|
|
96
|
+
throw error;
|
|
68
97
|
}
|
|
69
98
|
}
|
|
70
99
|
async generateAccessToken(user, context) {
|
|
@@ -76,12 +105,12 @@ class JwtStrategy extends token_auth_strategy_1.TokenAuthStrategy {
|
|
|
76
105
|
return Promise.resolve(jwt_tools_1.JwtTools.generateRefreshToken(payload, this.refreshTokenConfig));
|
|
77
106
|
}
|
|
78
107
|
async storeAccessToken(token) {
|
|
79
|
-
if (this.accessTokenConfig.persistence
|
|
108
|
+
if (this.accessTokenConfig.persistence?.store) {
|
|
80
109
|
await this.accessTokenConfig.persistence.store(token, null, this.accessTokenConfig.issuer.options.expiresIn);
|
|
81
110
|
}
|
|
82
111
|
}
|
|
83
112
|
async storeRefreshToken(token) {
|
|
84
|
-
if (this.refreshTokenConfig
|
|
113
|
+
if (this.refreshTokenConfig?.persistence?.store) {
|
|
85
114
|
await this.refreshTokenConfig.persistence.store(token, null, this.refreshTokenConfig.issuer.options.expiresIn);
|
|
86
115
|
}
|
|
87
116
|
}
|
|
@@ -112,6 +141,9 @@ class JwtStrategy extends token_auth_strategy_1.TokenAuthStrategy {
|
|
|
112
141
|
}
|
|
113
142
|
}
|
|
114
143
|
extractRefreshToken(context) {
|
|
144
|
+
if (!this.refreshTokenConfig) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
115
147
|
if (this.refreshTokenConfig.extract) {
|
|
116
148
|
return this.refreshTokenConfig.extract(context);
|
|
117
149
|
}
|
|
@@ -132,7 +164,7 @@ class JwtStrategy extends token_auth_strategy_1.TokenAuthStrategy {
|
|
|
132
164
|
async invalidateRefreshToken(token, context) {
|
|
133
165
|
const refreshToken = token || (await this.extractRefreshToken(context));
|
|
134
166
|
if (refreshToken) {
|
|
135
|
-
await this.refreshTokenConfig
|
|
167
|
+
await this.refreshTokenConfig?.persistence?.remove?.(refreshToken);
|
|
136
168
|
if (context) {
|
|
137
169
|
jwt_tools_1.JwtTools.clearDefaultJwtCookie(context);
|
|
138
170
|
jwt_tools_1.JwtTools.clearDefaultJwtHeader(context);
|
|
@@ -88,6 +88,7 @@ class JwtTools {
|
|
|
88
88
|
return context.req.cookies?.refreshToken;
|
|
89
89
|
}
|
|
90
90
|
static prepareAccessTokenConfig = (config) => {
|
|
91
|
+
const verifierOptions = config.verifier?.options ?? {};
|
|
91
92
|
return Soap.removeUndefinedProperties({
|
|
92
93
|
...config,
|
|
93
94
|
issuer: {
|
|
@@ -101,14 +102,15 @@ class JwtTools {
|
|
|
101
102
|
verifier: {
|
|
102
103
|
...config.verifier,
|
|
103
104
|
options: {
|
|
104
|
-
...
|
|
105
|
-
algorithms:
|
|
106
|
-
expiresIn:
|
|
105
|
+
...verifierOptions,
|
|
106
|
+
algorithms: verifierOptions.algorithms || ["HS256"],
|
|
107
|
+
expiresIn: verifierOptions.expiresIn || "1h",
|
|
107
108
|
},
|
|
108
109
|
},
|
|
109
110
|
});
|
|
110
111
|
};
|
|
111
112
|
static prepareRefreshTokenConfig = (config) => {
|
|
113
|
+
const verifierOptions = config.verifier?.options ?? {};
|
|
112
114
|
return Soap.removeUndefinedProperties({
|
|
113
115
|
...config,
|
|
114
116
|
issuer: {
|
|
@@ -122,9 +124,9 @@ class JwtTools {
|
|
|
122
124
|
verifier: {
|
|
123
125
|
...config.verifier,
|
|
124
126
|
options: {
|
|
125
|
-
...
|
|
126
|
-
algorithms:
|
|
127
|
-
expiresIn:
|
|
127
|
+
...verifierOptions,
|
|
128
|
+
algorithms: verifierOptions.algorithms || ["HS256"],
|
|
129
|
+
expiresIn: verifierOptions.expiresIn || "7d",
|
|
128
130
|
},
|
|
129
131
|
},
|
|
130
132
|
});
|
|
@@ -189,6 +191,14 @@ exports.JwtTools = JwtTools;
|
|
|
189
191
|
const prepareJwtConfig = (config) => {
|
|
190
192
|
return Soap.removeUndefinedProperties({
|
|
191
193
|
...config,
|
|
194
|
+
user: {
|
|
195
|
+
...config.user,
|
|
196
|
+
validateUser: config.user?.validateUser ?? (() => Promise.resolve(true)),
|
|
197
|
+
},
|
|
198
|
+
accessToken: JwtTools.prepareAccessTokenConfig(config.accessToken),
|
|
199
|
+
refreshToken: config.refreshToken
|
|
200
|
+
? JwtTools.prepareRefreshTokenConfig(config.refreshToken)
|
|
201
|
+
: undefined,
|
|
192
202
|
routes: {
|
|
193
203
|
login: config.routes?.login ?? {
|
|
194
204
|
path: "/auth/jwt/login",
|
|
@@ -203,14 +213,6 @@ const prepareJwtConfig = (config) => {
|
|
|
203
213
|
method: "POST",
|
|
204
214
|
},
|
|
205
215
|
...config.routes,
|
|
206
|
-
user: {
|
|
207
|
-
...config.user,
|
|
208
|
-
validateUser: config.user?.validateUser ?? (() => Promise.resolve(true)),
|
|
209
|
-
},
|
|
210
|
-
accessToken: JwtTools.prepareAccessTokenConfig(config.accessToken),
|
|
211
|
-
refreshToken: config.refreshToken
|
|
212
|
-
? JwtTools.prepareRefreshTokenConfig(config.refreshToken)
|
|
213
|
-
: undefined,
|
|
214
216
|
},
|
|
215
217
|
});
|
|
216
218
|
};
|
|
@@ -3,18 +3,21 @@ import { CredentialAuthStrategy } from "../credential-auth.strategy";
|
|
|
3
3
|
import { LocalStrategyConfig } from "./local.types";
|
|
4
4
|
import { SessionHandler } from "../../session/session-handler";
|
|
5
5
|
import { JwtStrategy } from "../jwt/jwt.strategy";
|
|
6
|
-
export declare class LocalStrategy<TContext =
|
|
6
|
+
export declare class LocalStrategy<TContext = Soap.HttpContext, TUser extends Soap.AuthUser = Soap.AuthUser> extends CredentialAuthStrategy<TContext, TUser> {
|
|
7
7
|
protected session?: SessionHandler;
|
|
8
8
|
protected jwt?: JwtStrategy<TContext, TUser>;
|
|
9
9
|
protected logger?: Soap.Logger;
|
|
10
|
+
readonly name = "local";
|
|
10
11
|
constructor(config: LocalStrategyConfig<TContext, TUser>, session?: SessionHandler, jwt?: JwtStrategy<TContext, TUser>, logger?: Soap.Logger);
|
|
12
|
+
private static validateConfig;
|
|
11
13
|
protected extractCredentials(context?: TContext): Promise<{
|
|
12
14
|
identifier: string;
|
|
13
15
|
password: string;
|
|
14
16
|
}>;
|
|
15
17
|
protected verifyCredentials(identifier: string, password: string): Promise<boolean>;
|
|
16
|
-
protected fetchUser(
|
|
18
|
+
protected fetchUser(identifierOrCredentials: string | {
|
|
17
19
|
identifier: string;
|
|
18
|
-
password
|
|
20
|
+
password?: string;
|
|
19
21
|
}): Promise<TUser | null>;
|
|
22
|
+
changePassword(context: TContext): Promise<void>;
|
|
20
23
|
}
|