@soapjs/soap-auth 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/__tests__/soap-auth.test.d.ts +1 -0
- package/build/__tests__/soap-auth.test.js +42 -0
- package/build/errors.d.ts +14 -3
- package/build/errors.js +29 -8
- package/build/index.d.ts +1 -1
- package/build/index.js +1 -1
- package/build/services/__tests__/account-lock.service.test.d.ts +1 -0
- package/build/services/__tests__/account-lock.service.test.js +55 -0
- package/build/services/__tests__/auth-throttle.service.test.d.ts +1 -0
- package/build/services/__tests__/auth-throttle.service.test.js +48 -0
- package/build/services/__tests__/jwks.service.test.d.ts +1 -0
- package/build/services/__tests__/jwks.service.test.js +39 -0
- package/build/services/__tests__/mfa.service.test.d.ts +1 -0
- package/build/services/__tests__/mfa.service.test.js +66 -0
- package/build/services/__tests__/password.service.test.d.ts +1 -0
- package/build/services/__tests__/password.service.test.js +66 -0
- package/build/services/__tests__/pkce.service.test.d.ts +1 -0
- package/build/services/__tests__/pkce.service.test.js +77 -0
- package/build/services/__tests__/rate-limit.service.test.d.ts +1 -0
- package/build/services/__tests__/rate-limit.service.test.js +37 -0
- package/build/services/__tests__/role.service.test.d.ts +1 -0
- package/build/services/__tests__/role.service.test.js +31 -0
- package/build/services/account-lock.service.d.ts +12 -0
- package/build/services/account-lock.service.js +39 -0
- package/build/services/auth-throttle.service.d.ts +10 -0
- package/build/services/auth-throttle.service.js +43 -0
- package/build/services/index.d.ts +8 -0
- package/build/{factories → services}/index.js +8 -3
- package/build/services/jwks.service.d.ts +7 -0
- package/build/services/jwks.service.js +41 -0
- package/build/services/mfa.service.d.ts +12 -0
- package/build/services/mfa.service.js +74 -0
- package/build/services/password.service.d.ts +14 -0
- package/build/services/password.service.js +78 -0
- package/build/services/pkce.service.d.ts +14 -0
- package/build/services/pkce.service.js +81 -0
- package/build/services/rate-limit.service.d.ts +9 -0
- package/build/services/rate-limit.service.js +26 -0
- package/build/services/role.service.d.ts +9 -0
- package/build/services/role.service.js +26 -0
- package/build/session/__tests__/file.session-store.test.d.ts +1 -0
- package/build/session/__tests__/file.session-store.test.js +117 -0
- package/build/session/__tests__/memory.session-store.test.d.ts +1 -0
- package/build/session/__tests__/memory.session-store.test.js +77 -0
- package/build/session/__tests__/session-handler.test.d.ts +1 -0
- package/build/session/__tests__/session-handler.test.js +337 -0
- package/build/session/file.session-store.d.ts +1 -0
- package/build/session/file.session-store.js +7 -0
- package/build/session/memory.session-store.d.ts +4 -1
- package/build/session/memory.session-store.js +11 -5
- package/build/session/session-handler.d.ts +12 -7
- package/build/session/session-handler.js +46 -13
- package/build/session/session.errors.d.ts +6 -0
- package/build/session/session.errors.js +15 -0
- package/build/soap-auth.d.ts +9 -8
- package/build/soap-auth.js +42 -29
- package/build/strategies/__tests__/base-auth.strategy.test.d.ts +14 -0
- package/build/strategies/__tests__/base-auth.strategy.test.js +137 -0
- package/build/strategies/__tests__/credential-auth.strategy.test.d.ts +14 -0
- package/build/strategies/__tests__/credential-auth.strategy.test.js +265 -0
- package/build/strategies/__tests__/token-auth.strategy.test.d.ts +28 -0
- package/build/strategies/__tests__/token-auth.strategy.test.js +298 -0
- package/build/strategies/api-key/__tests__/api-key.strategy.test.d.ts +1 -0
- package/build/strategies/api-key/__tests__/api-key.strategy.test.js +103 -0
- package/build/strategies/api-key/api-key.strategy.d.ts +5 -2
- package/build/strategies/api-key/api-key.strategy.js +43 -35
- package/build/strategies/api-key/api-key.tools.d.ts +2 -0
- package/build/strategies/api-key/api-key.tools.js +39 -0
- package/build/strategies/api-key/api-key.types.d.ts +10 -2
- package/build/strategies/base-auth.strategy.d.ts +11 -5
- package/build/strategies/base-auth.strategy.js +45 -52
- package/build/strategies/basic/__tests__/basic.strategy.test.d.ts +1 -0
- package/build/strategies/basic/__tests__/basic.strategy.test.js +104 -0
- package/build/strategies/basic/basic.strategy.d.ts +5 -7
- package/build/strategies/basic/basic.strategy.js +6 -6
- package/build/strategies/basic/basic.tools.d.ts +2 -0
- package/build/strategies/basic/basic.tools.js +44 -0
- package/build/strategies/credential-auth.strategy.d.ts +7 -17
- package/build/strategies/credential-auth.strategy.js +116 -181
- package/build/strategies/jwt/__tests__/jwt.strategy.test.d.ts +1 -0
- package/build/strategies/jwt/__tests__/jwt.strategy.test.js +156 -0
- package/build/strategies/jwt/__tests__/jwt.tools.test.d.ts +1 -0
- package/build/strategies/jwt/__tests__/jwt.tools.test.js +98 -0
- package/build/strategies/jwt/jwt.strategy.d.ts +13 -14
- package/build/strategies/jwt/jwt.strategy.js +57 -44
- package/build/strategies/jwt/jwt.tools.d.ts +20 -7
- package/build/strategies/jwt/jwt.tools.js +180 -81
- package/build/strategies/local/__tests__/local.strategy.test.d.ts +1 -0
- package/build/strategies/local/__tests__/local.strategy.test.js +115 -0
- package/build/strategies/local/local.strategy.d.ts +4 -3
- package/build/strategies/local/local.strategy.js +7 -6
- package/build/strategies/local/local.tools.d.ts +2 -0
- package/build/strategies/local/local.tools.js +44 -0
- package/build/strategies/oauth2/hybrid.oauth2.strategy.d.ts +5 -0
- package/build/strategies/oauth2/hybrid.oauth2.strategy.js +92 -0
- package/build/strategies/oauth2/oauth2.errors.d.ts +12 -0
- package/build/strategies/oauth2/oauth2.errors.js +24 -0
- package/build/strategies/oauth2/oauth2.strategy.d.ts +25 -15
- package/build/strategies/oauth2/oauth2.strategy.js +131 -141
- package/build/strategies/oauth2/oauth2.tools.d.ts +7 -2
- package/build/strategies/oauth2/oauth2.tools.js +119 -14
- package/build/strategies/oauth2/oauth2.types.d.ts +32 -1
- package/build/strategies/token-auth.strategy.d.ts +14 -8
- package/build/strategies/token-auth.strategy.js +162 -38
- package/build/tools/index.d.ts +0 -2
- package/build/tools/index.js +0 -2
- package/build/tools/tools.d.ts +2 -1
- package/build/tools/tools.js +9 -12
- package/build/types.d.ts +88 -57
- package/package.json +1 -1
- package/build/factories/auth-strategy.factory.d.ts +0 -9
- package/build/factories/auth-strategy.factory.js +0 -16
- package/build/factories/http-auth-strategy.factory.d.ts +0 -5
- package/build/factories/http-auth-strategy.factory.js +0 -41
- package/build/factories/index.d.ts +0 -3
- package/build/factories/socket-auth-strategy.factory.d.ts +0 -5
- package/build/factories/socket-auth-strategy.factory.js +0 -27
- package/build/tools/session.tools.d.ts +0 -6
- package/build/tools/session.tools.js +0 -15
- package/build/tools/token.tools.d.ts +0 -7
- package/build/tools/token.tools.js +0 -32
|
@@ -1,8 +1,33 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.TokenAuthStrategy = void 0;
|
|
27
|
+
const Soap = __importStar(require("@soapjs/soap"));
|
|
4
28
|
const base_auth_strategy_1 = require("./base-auth.strategy");
|
|
5
29
|
const errors_1 = require("../errors");
|
|
30
|
+
const jsonwebtoken_1 = require("jsonwebtoken");
|
|
6
31
|
class TokenAuthStrategy extends base_auth_strategy_1.BaseAuthStrategy {
|
|
7
32
|
config;
|
|
8
33
|
session;
|
|
@@ -13,66 +38,165 @@ class TokenAuthStrategy extends base_auth_strategy_1.BaseAuthStrategy {
|
|
|
13
38
|
this.session = session;
|
|
14
39
|
this.logger = logger;
|
|
15
40
|
}
|
|
41
|
+
async fetchUser(payload) {
|
|
42
|
+
if (this.config?.user?.fetchUser) {
|
|
43
|
+
return this.config.user.fetchUser(payload);
|
|
44
|
+
}
|
|
45
|
+
throw new Soap.NotImplementedError("fetchUser");
|
|
46
|
+
}
|
|
16
47
|
async authenticate(context) {
|
|
17
48
|
try {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
49
|
+
await this.rateLimit?.checkRateLimit(context);
|
|
50
|
+
const accessToken = this.extractAccessToken(context);
|
|
51
|
+
const refreshToken = this.extractRefreshToken(context);
|
|
21
52
|
if (accessToken) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (!user)
|
|
26
|
-
throw new errors_1.UserNotFoundError();
|
|
27
|
-
await this.isAuthorized(user);
|
|
53
|
+
const { user, isExpired } = await this.verifyAndFetchUser(accessToken);
|
|
54
|
+
if (user) {
|
|
55
|
+
await this.role?.isAuthorized(user);
|
|
28
56
|
return { user, tokens: { accessToken } };
|
|
29
57
|
}
|
|
30
|
-
|
|
31
|
-
|
|
58
|
+
if (!isExpired) {
|
|
59
|
+
throw new errors_1.InvalidTokenError("Access");
|
|
32
60
|
}
|
|
61
|
+
this.logger?.warn("Access token expired, attempting refresh...");
|
|
33
62
|
}
|
|
34
|
-
|
|
35
|
-
if (!refreshToken)
|
|
36
|
-
throw new errors_1.MissingTokenError("Refresh");
|
|
37
|
-
const newTokens = await this.rotateTokens(context);
|
|
38
|
-
accessToken = newTokens.accessToken;
|
|
39
|
-
refreshToken = newTokens.refreshToken;
|
|
40
|
-
if (!accessToken)
|
|
63
|
+
if (!this.config.refreshToken) {
|
|
41
64
|
throw new errors_1.MissingTokenError("Access");
|
|
65
|
+
}
|
|
66
|
+
if (!refreshToken) {
|
|
67
|
+
throw new errors_1.MissingTokenError("Refresh");
|
|
68
|
+
}
|
|
69
|
+
return this.refreshTokens(context);
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
await this.onFailure("authenticate", { error });
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
async verifyAndFetchUser(accessToken) {
|
|
77
|
+
try {
|
|
42
78
|
const decoded = await this.verifyAccessToken(accessToken);
|
|
43
|
-
const user = await this.
|
|
44
|
-
if (!user)
|
|
79
|
+
const user = await this.fetchUser(decoded);
|
|
80
|
+
if (!user) {
|
|
45
81
|
throw new errors_1.UserNotFoundError();
|
|
46
|
-
|
|
47
|
-
return { user,
|
|
82
|
+
}
|
|
83
|
+
return { user, isExpired: false };
|
|
48
84
|
}
|
|
49
85
|
catch (error) {
|
|
50
|
-
this.logger?.error(
|
|
51
|
-
|
|
86
|
+
this.logger?.error(error);
|
|
87
|
+
if (error instanceof jsonwebtoken_1.TokenExpiredError) {
|
|
88
|
+
return { user: null, isExpired: true };
|
|
89
|
+
}
|
|
90
|
+
return { user: null, isExpired: false };
|
|
52
91
|
}
|
|
53
92
|
}
|
|
54
|
-
async
|
|
93
|
+
async refreshTokens(context, existingUser) {
|
|
55
94
|
try {
|
|
56
|
-
|
|
57
|
-
|
|
95
|
+
if (!this.config.refreshToken) {
|
|
96
|
+
throw new Error("Refresh tokens are not enabled.");
|
|
97
|
+
}
|
|
98
|
+
const refreshToken = this.extractRefreshToken(context);
|
|
99
|
+
if (!refreshToken) {
|
|
58
100
|
throw new errors_1.MissingTokenError("Refresh");
|
|
101
|
+
}
|
|
59
102
|
const payload = await this.verifyRefreshToken(refreshToken);
|
|
60
|
-
if (!payload)
|
|
103
|
+
if (!payload) {
|
|
61
104
|
throw new errors_1.InvalidTokenError("Refresh");
|
|
62
|
-
const newAccessToken = await this.generateAccessToken(payload);
|
|
63
|
-
let newRefreshToken = await this.generateRefreshToken(payload);
|
|
64
|
-
await this.storeAccessToken(newAccessToken, context);
|
|
65
|
-
if (newRefreshToken) {
|
|
66
|
-
await this.storeRefreshToken(newRefreshToken, context);
|
|
67
105
|
}
|
|
68
|
-
this.
|
|
69
|
-
|
|
70
|
-
|
|
106
|
+
if (this.config.refreshToken.absoluteExpiry) {
|
|
107
|
+
const { payloadField, onExpiry } = this.config.refreshToken.absoluteExpiry;
|
|
108
|
+
const field = payloadField || "absoluteExp";
|
|
109
|
+
const maxTime = payload[field];
|
|
110
|
+
if (maxTime && Date.now() / 1000 > maxTime) {
|
|
111
|
+
this.logger?.warn(`Absolute expiry exceeded for refresh token.`);
|
|
112
|
+
switch (onExpiry) {
|
|
113
|
+
case "logout": {
|
|
114
|
+
await this.session?.logoutSession(context);
|
|
115
|
+
await this.invalidateRefreshToken(refreshToken, context);
|
|
116
|
+
throw new errors_1.InvalidTokenError("Refresh");
|
|
117
|
+
}
|
|
118
|
+
case "error":
|
|
119
|
+
throw new errors_1.InvalidTokenError("Refresh");
|
|
120
|
+
case "ignore":
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
let user = existingUser ?? (await this.fetchUser(payload));
|
|
126
|
+
if (!user) {
|
|
127
|
+
throw new errors_1.UserNotFoundError();
|
|
128
|
+
}
|
|
129
|
+
await this.role?.isAuthorized(user);
|
|
130
|
+
const newTokens = await this.issueTokens(user, context, true);
|
|
131
|
+
return {
|
|
132
|
+
user,
|
|
133
|
+
tokens: newTokens,
|
|
134
|
+
};
|
|
71
135
|
}
|
|
72
136
|
catch (error) {
|
|
73
|
-
this.
|
|
74
|
-
|
|
137
|
+
await this.onFailure("refresh_tokens", {
|
|
138
|
+
error,
|
|
139
|
+
});
|
|
140
|
+
throw error;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async issueTokens(user, context, rotate) {
|
|
144
|
+
try {
|
|
145
|
+
const accessToken = await this.generateAccessToken(user, context);
|
|
146
|
+
let refreshToken;
|
|
147
|
+
if (this.config.refreshToken) {
|
|
148
|
+
refreshToken = await this.generateRefreshToken(user, context);
|
|
149
|
+
if (rotate && this.config?.refreshToken?.rotation) {
|
|
150
|
+
const oldRefreshToken = this.extractRefreshToken(context);
|
|
151
|
+
refreshToken = await this.rotateToken(oldRefreshToken, user, context);
|
|
152
|
+
}
|
|
153
|
+
else if (this.generateRefreshToken) {
|
|
154
|
+
refreshToken = await this.generateRefreshToken(user, context);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
await this.storeAccessToken(accessToken);
|
|
158
|
+
this.embedAccessToken(accessToken, context);
|
|
159
|
+
if (refreshToken) {
|
|
160
|
+
await this.storeRefreshToken(refreshToken);
|
|
161
|
+
this.embedRefreshToken(refreshToken, context);
|
|
162
|
+
}
|
|
163
|
+
this.logger?.info(`JWT issued successfully`);
|
|
164
|
+
return { accessToken, refreshToken };
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
await this.onFailure("issueTokens", {
|
|
168
|
+
context,
|
|
169
|
+
error,
|
|
170
|
+
});
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async rotateToken(refreshToken, user, context) {
|
|
175
|
+
let rotationCount = 0;
|
|
176
|
+
let newRefreshToken;
|
|
177
|
+
if (this.config.refreshToken.rotation.getRotationCount) {
|
|
178
|
+
rotationCount = await this.config.refreshToken.rotation.getRotationCount(refreshToken, user, context);
|
|
179
|
+
}
|
|
180
|
+
if (this.config.refreshToken.rotation.isLimitReached(rotationCount, this.config.refreshToken.rotation.maxRotations, user, context)) {
|
|
181
|
+
throw new errors_1.TokenRotationLimitReachedError();
|
|
182
|
+
}
|
|
183
|
+
if (this.config.refreshToken.rotation.rotateToken) {
|
|
184
|
+
const result = await this.config.refreshToken.rotation.rotateToken(refreshToken, user, context);
|
|
185
|
+
newRefreshToken = result.newToken;
|
|
186
|
+
if (typeof result.newRotationCount === "number") {
|
|
187
|
+
rotationCount = result.newRotationCount;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
rotationCount += 1;
|
|
191
|
+
}
|
|
192
|
+
if (this.config.refreshToken.rotation.afterRotation) {
|
|
193
|
+
await this.config.refreshToken.rotation.afterRotation(refreshToken, newRefreshToken, user, context, rotationCount);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
this.logger?.warn("Rotation enabled but rotateToken not provided.");
|
|
75
198
|
}
|
|
199
|
+
return newRefreshToken;
|
|
76
200
|
}
|
|
77
201
|
}
|
|
78
202
|
exports.TokenAuthStrategy = TokenAuthStrategy;
|
package/build/tools/index.d.ts
CHANGED
package/build/tools/index.js
CHANGED
|
@@ -14,6 +14,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./session.tools"), exports);
|
|
18
|
-
__exportStar(require("./token.tools"), exports);
|
|
19
17
|
__exportStar(require("./tools"), exports);
|
package/build/tools/tools.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
export declare const generateUUID: () => Promise<string>;
|
|
2
|
-
export declare const generateSecureToken: (tokenLength?: number, encoding?: string) => Promise<string>;
|
|
3
3
|
export declare function resolveConfig<T>(strategyConfig: T | undefined, globalConfig: T | undefined): T | undefined;
|
|
4
|
+
export declare const generateRandomString: (size?: number, encoding?: BufferEncoding) => string;
|
package/build/tools/tools.js
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const crypto_1 = require("crypto");
|
|
6
|
+
exports.generateRandomString = exports.resolveConfig = exports.generateUUID = void 0;
|
|
5
7
|
const uuid_1 = require("uuid");
|
|
8
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
6
9
|
const generateUUID = async () => {
|
|
7
10
|
return Promise.resolve((0, uuid_1.v4)());
|
|
8
11
|
};
|
|
9
12
|
exports.generateUUID = generateUUID;
|
|
10
|
-
const generateSecureToken = async (tokenLength = 32, encoding = "hex") => {
|
|
11
|
-
return new Promise((resolve, reject) => {
|
|
12
|
-
(0, crypto_1.randomBytes)(tokenLength, (err, buffer) => {
|
|
13
|
-
if (err)
|
|
14
|
-
return reject(err);
|
|
15
|
-
resolve(buffer.toString(encoding));
|
|
16
|
-
});
|
|
17
|
-
});
|
|
18
|
-
};
|
|
19
|
-
exports.generateSecureToken = generateSecureToken;
|
|
20
13
|
function resolveConfig(strategyConfig, globalConfig) {
|
|
21
14
|
return strategyConfig || globalConfig;
|
|
22
15
|
}
|
|
23
16
|
exports.resolveConfig = resolveConfig;
|
|
17
|
+
const generateRandomString = (size = 32, encoding = "hex") => {
|
|
18
|
+
return crypto_1.default.randomBytes(size).toString(encoding);
|
|
19
|
+
};
|
|
20
|
+
exports.generateRandomString = generateRandomString;
|
package/build/types.d.ts
CHANGED
|
@@ -4,11 +4,13 @@ import { OAuth2StrategyConfig } from "./strategies/oauth2/oauth2.types";
|
|
|
4
4
|
import { ApiKeyStrategyConfig } from "./strategies/api-key/api-key.types";
|
|
5
5
|
import { BasicStrategyConfig } from "./strategies/basic/basic.types";
|
|
6
6
|
import { JwtConfig } from "./strategies/jwt/jwt.types";
|
|
7
|
+
export type AuthCategories = "http" | "socket" | "grpc" | "webhook" | "edge" | "isa" | "event";
|
|
7
8
|
export interface SessionStore {
|
|
8
9
|
getSession<T = SessionData>(sid: string, ...args: unknown[]): Promise<T | null>;
|
|
9
10
|
setSession<T = SessionData>(sid: string, session: T, ...args: unknown[]): void | Promise<void>;
|
|
10
11
|
destroySession(sid: string, ...args: unknown[]): void | Promise<void>;
|
|
11
12
|
touchSession<T = SessionData>(sid: string, session: T, ...args: unknown[]): void | Promise<void>;
|
|
13
|
+
getSessionIds(): Promise<string[]>;
|
|
12
14
|
}
|
|
13
15
|
export type SessionData = {
|
|
14
16
|
[key: string]: any;
|
|
@@ -39,23 +41,19 @@ export interface AuthResultConfig<TContext = unknown, TUser = unknown> {
|
|
|
39
41
|
onSuccess?: (action: string, context: AuthSuccessContext<TUser, TContext>) => Promise<void> | void;
|
|
40
42
|
onFailure?: (action: string, context: AuthFailureContext<TContext>) => Promise<void> | void;
|
|
41
43
|
}
|
|
42
|
-
export interface
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
export interface AuthThrottleConfig {
|
|
45
|
+
incrementFailedAttempts?: (identifier: string, ...rest: unknown[]) => Promise<void>;
|
|
46
|
+
resetFailedAttempts?: (identifier: string, ...rest: unknown[]) => Promise<void>;
|
|
47
|
+
getFailedAttempts?: (identifier: string, ...rest: unknown[]) => Promise<number>;
|
|
48
|
+
maxFailedAttempts?: number;
|
|
46
49
|
}
|
|
47
50
|
export interface BaseAuthStrategyConfig<TContext = unknown, TUser = unknown> extends AuthResultConfig<TContext, TUser> {
|
|
48
51
|
mfa?: MfaConfig<TUser, TContext>;
|
|
49
52
|
session?: SessionConfig;
|
|
50
53
|
role?: RoleAuthorizationConfig<TUser>;
|
|
51
54
|
rateLimit?: RateLimitConfig;
|
|
52
|
-
|
|
55
|
+
throttle?: AuthThrottleConfig;
|
|
53
56
|
lock?: AccountLockConfig<TContext>;
|
|
54
|
-
failedAttempts?: FailedAttemptsConfig;
|
|
55
|
-
}
|
|
56
|
-
export interface AuditLoggingConfig<TContext = unknown> {
|
|
57
|
-
logAttempt?: (userId: string, success: boolean, context?: TContext) => Promise<void>;
|
|
58
|
-
logPasswordChange?: (userId: string, context?: TContext) => Promise<void>;
|
|
59
57
|
}
|
|
60
58
|
export interface MfaConfig<TUser = unknown, TContext = unknown> {
|
|
61
59
|
extractMfaCode?: (context?: TContext) => string;
|
|
@@ -74,19 +72,17 @@ export interface MfaConfig<TUser = unknown, TContext = unknown> {
|
|
|
74
72
|
incrementMfaAttempts?: (user: TUser) => Promise<void>;
|
|
75
73
|
}
|
|
76
74
|
export interface PasswordPolicyConfig {
|
|
77
|
-
validatePassword?: (password: string) => boolean
|
|
78
|
-
getLastPasswordChange?: (identifier: string) => Date
|
|
79
|
-
forcePasswordChangeOnFirstLogin?: boolean;
|
|
75
|
+
validatePassword?: (password: string) => Promise<boolean>;
|
|
76
|
+
getLastPasswordChange?: (identifier: string) => Promise<Date>;
|
|
80
77
|
passwordExpirationDays?: number;
|
|
81
|
-
isPasswordChangeRequired?: (identifier: string) => Promise<boolean>;
|
|
82
78
|
generateResetToken?: (identifier: string) => Promise<string>;
|
|
83
79
|
sendResetEmail?: (identifier: string, token: string) => Promise<void>;
|
|
84
80
|
validateResetToken?: (token: string) => Promise<boolean>;
|
|
85
81
|
updatePassword?: (identifier: string, newPassword: string) => Promise<void>;
|
|
86
82
|
}
|
|
87
|
-
export interface UserConfig {
|
|
88
|
-
|
|
89
|
-
validateUser?: (payload:
|
|
83
|
+
export interface UserConfig<TUser = unknown> {
|
|
84
|
+
fetchUser: (payload: unknown) => Promise<TUser | null>;
|
|
85
|
+
validateUser?: (payload: unknown) => Promise<any>;
|
|
90
86
|
}
|
|
91
87
|
export interface CredentailsConfig<TContext = any> {
|
|
92
88
|
extractCredentials: <TCredentials = {
|
|
@@ -95,44 +91,48 @@ export interface CredentailsConfig<TContext = any> {
|
|
|
95
91
|
}>(context: TContext) => TCredentials;
|
|
96
92
|
verifyCredentials: (identifier: string, password: string) => Promise<boolean>;
|
|
97
93
|
}
|
|
98
|
-
export interface FailedAttemptsConfig {
|
|
99
|
-
incrementFailedAttempts?: (identifier: string, ...rest: unknown[]) => Promise<void>;
|
|
100
|
-
resetFailedAttempts?: (identifier: string, ...rest: unknown[]) => Promise<void>;
|
|
101
|
-
getFailedAttempts?: (identifier: string, ...rest: unknown[]) => Promise<number>;
|
|
102
|
-
}
|
|
103
94
|
export interface CredentialAuthStrategyConfig<TContext = unknown, TUser = unknown> extends BaseAuthStrategyConfig<TContext, TUser> {
|
|
104
95
|
passwordPolicy?: PasswordPolicyConfig;
|
|
105
|
-
audit?: AuditLoggingConfig<TContext>;
|
|
106
96
|
credentials?: CredentailsConfig<TContext>;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
97
|
+
jwt?: TokenAuthConfig<TContext>;
|
|
98
|
+
user?: UserConfig<TUser>;
|
|
99
|
+
allowGuest?: boolean;
|
|
100
|
+
routes: {
|
|
101
|
+
login: AuthRouteConfig;
|
|
102
|
+
logout: AuthRouteConfig;
|
|
111
103
|
resetPassword?: AuthRouteConfig;
|
|
104
|
+
changePassword?: AuthRouteConfig;
|
|
105
|
+
requestPasswordReset?: AuthRouteConfig;
|
|
112
106
|
};
|
|
113
107
|
}
|
|
114
108
|
export type AuthRouteConfig = {
|
|
115
|
-
path
|
|
116
|
-
method
|
|
109
|
+
path: string;
|
|
110
|
+
method: string;
|
|
117
111
|
};
|
|
118
|
-
export interface
|
|
119
|
-
|
|
112
|
+
export interface TokenAuthConfig<TContext = unknown, TUser = unknown> {
|
|
113
|
+
accessToken?: TokenConfig<TContext>;
|
|
114
|
+
refreshToken?: RefreshTokenConfig<TContext, TUser>;
|
|
115
|
+
}
|
|
116
|
+
export interface TokenAuthStrategyConfig<TContext = unknown, TUser = unknown> extends BaseAuthStrategyConfig<TContext, TUser>, TokenAuthConfig<TContext> {
|
|
117
|
+
user?: UserConfig<TUser>;
|
|
120
118
|
routes: {
|
|
121
119
|
login?: AuthRouteConfig;
|
|
122
120
|
logout?: AuthRouteConfig;
|
|
123
121
|
refresh?: AuthRouteConfig;
|
|
124
122
|
[key: string]: AuthRouteConfig;
|
|
125
123
|
};
|
|
126
|
-
accessToken?: TokenConfig<TContext>;
|
|
127
|
-
refreshToken?: TokenConfig<TContext>;
|
|
128
124
|
}
|
|
129
125
|
export interface AccountLockConfig<TContext = unknown> {
|
|
130
126
|
logFailedAttempt?: (account: any, context?: TContext) => Promise<void>;
|
|
131
|
-
lockAccount
|
|
132
|
-
|
|
127
|
+
lockAccount: (account: any) => Promise<void>;
|
|
128
|
+
removeAccountLock: (account: any) => Promise<void>;
|
|
129
|
+
hasAccountLockExpired: (account: any) => Promise<boolean>;
|
|
130
|
+
isAccountLocked: (account: any, context?: TContext) => Promise<boolean>;
|
|
131
|
+
lockoutDuration?: number;
|
|
132
|
+
notifyOnLockout?: (account: any) => Promise<void>;
|
|
133
133
|
}
|
|
134
134
|
export interface RateLimitConfig {
|
|
135
|
-
checkRateLimit
|
|
135
|
+
checkRateLimit: (...args: unknown[]) => Promise<boolean>;
|
|
136
136
|
incrementRequestCount?: (...args: unknown[]) => Promise<void>;
|
|
137
137
|
}
|
|
138
138
|
export interface RoleAuthorizationConfig<TUser = unknown> {
|
|
@@ -143,23 +143,26 @@ export type AuthSuccessContext<TUser = unknown, TContext = unknown, TSessionData
|
|
|
143
143
|
user?: TUser;
|
|
144
144
|
context?: TContext;
|
|
145
145
|
session?: SessionInfo<TSessionData>;
|
|
146
|
-
tokens?: string
|
|
146
|
+
tokens?: Record<string, unknown>;
|
|
147
147
|
identifier?: string;
|
|
148
148
|
email?: string;
|
|
149
|
+
additional?: Record<string, unknown>;
|
|
149
150
|
};
|
|
150
151
|
export type AuthFailureContext<TContext = unknown> = {
|
|
151
152
|
error: Error;
|
|
152
153
|
context?: TContext;
|
|
153
154
|
identifier?: string;
|
|
154
155
|
email?: string;
|
|
156
|
+
additional?: Record<string, unknown>;
|
|
155
157
|
};
|
|
156
|
-
export type AuthResult<TUser, TSessionData = unknown> = {
|
|
158
|
+
export type AuthResult<TUser = unknown, TSessionData = unknown> = {
|
|
157
159
|
user: TUser;
|
|
158
160
|
session?: SessionInfo<TSessionData>;
|
|
159
161
|
tokens?: {
|
|
160
162
|
accessToken?: string;
|
|
161
163
|
refreshToken?: string | null;
|
|
162
164
|
apiKey?: string | null;
|
|
165
|
+
[key: string]: string;
|
|
163
166
|
};
|
|
164
167
|
};
|
|
165
168
|
export interface AuthStrategy<TContext = unknown, TUser = unknown> {
|
|
@@ -168,6 +171,7 @@ export interface AuthStrategy<TContext = unknown, TUser = unknown> {
|
|
|
168
171
|
authorize?(user: any, action: string, resource?: string): Promise<boolean>;
|
|
169
172
|
refresh?(refreshToken: string): Promise<string>;
|
|
170
173
|
logout?(context?: TContext): Promise<void>;
|
|
174
|
+
logout?(context?: TContext): Promise<void>;
|
|
171
175
|
}
|
|
172
176
|
export interface SoapHttpAuthConfig<TContext = unknown, TUser = unknown> {
|
|
173
177
|
local?: LocalStrategyConfig<TContext, TUser>;
|
|
@@ -175,7 +179,6 @@ export interface SoapHttpAuthConfig<TContext = unknown, TUser = unknown> {
|
|
|
175
179
|
[provider: string]: OAuth2StrategyConfig<TContext, TUser>;
|
|
176
180
|
};
|
|
177
181
|
apiKey?: ApiKeyStrategyConfig<TContext, TUser>;
|
|
178
|
-
jwt?: JwtConfig<TContext, TUser>;
|
|
179
182
|
basic?: BasicStrategyConfig<TContext, TUser>;
|
|
180
183
|
custom: {
|
|
181
184
|
[label: string]: AuthStrategy;
|
|
@@ -190,6 +193,7 @@ export interface SoapSocketAuthConfig<TContext = unknown, TUser = unknown> {
|
|
|
190
193
|
}
|
|
191
194
|
export interface SoapAuthConfig<TContext = unknown, TUser = unknown> {
|
|
192
195
|
session?: SessionConfig;
|
|
196
|
+
jwt?: TokenAuthConfig<TContext>;
|
|
193
197
|
http?: SoapHttpAuthConfig<TContext, TUser>;
|
|
194
198
|
socket?: SoapSocketAuthConfig<TContext, TUser>;
|
|
195
199
|
logger?: Soap.Logger;
|
|
@@ -235,7 +239,7 @@ export interface StorageContext {
|
|
|
235
239
|
encrypt?: (data: string) => Promise<string> | string;
|
|
236
240
|
decrypt?: (data: string) => Promise<string> | string;
|
|
237
241
|
}
|
|
238
|
-
export interface TokenIssuerConfig {
|
|
242
|
+
export interface TokenIssuerConfig<TContext = unknown> {
|
|
239
243
|
secretKey: string;
|
|
240
244
|
options: {
|
|
241
245
|
expiresIn: string | number;
|
|
@@ -244,7 +248,8 @@ export interface TokenIssuerConfig {
|
|
|
244
248
|
subject?: string;
|
|
245
249
|
[option: string]: unknown;
|
|
246
250
|
};
|
|
247
|
-
|
|
251
|
+
buildPayload?: (user: any, context?: TContext) => Record<string, any>;
|
|
252
|
+
generate?: (data: any, context?: TContext) => string;
|
|
248
253
|
}
|
|
249
254
|
export interface TokenVerifierConfig {
|
|
250
255
|
options: {
|
|
@@ -252,26 +257,52 @@ export interface TokenVerifierConfig {
|
|
|
252
257
|
};
|
|
253
258
|
verify?: (token: string) => Promise<any>;
|
|
254
259
|
}
|
|
255
|
-
export interface
|
|
256
|
-
store
|
|
257
|
-
read
|
|
258
|
-
remove
|
|
260
|
+
export interface PersistenceConfig<T = any> {
|
|
261
|
+
store: (data: any, ...args: any[]) => Promise<void>;
|
|
262
|
+
read: (...args: any[]) => Promise<T | null>;
|
|
263
|
+
remove: (...args: any[]) => Promise<void>;
|
|
264
|
+
}
|
|
265
|
+
export interface ContextOperationConfig<TContext = any, TData = any> {
|
|
266
|
+
embed?: (context: TContext, data: TData) => void;
|
|
267
|
+
extract?: (context: TContext) => TData | null;
|
|
259
268
|
}
|
|
260
|
-
export interface TokenConfig<TContext = any> {
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
rotation?: TokenRotationConfig;
|
|
264
|
-
issuer?: TokenIssuerConfig;
|
|
269
|
+
export interface TokenConfig<TContext = any, TUser = any> extends ContextOperationConfig<TContext, string> {
|
|
270
|
+
rotation?: TokenRotationConfig<TContext, TUser>;
|
|
271
|
+
issuer?: TokenIssuerConfig<TContext>;
|
|
265
272
|
verifier?: TokenVerifierConfig;
|
|
266
|
-
persistence?:
|
|
273
|
+
persistence?: PersistenceConfig;
|
|
267
274
|
additional?: Record<string, unknown>;
|
|
268
275
|
}
|
|
269
|
-
export interface
|
|
270
|
-
|
|
271
|
-
|
|
276
|
+
export interface RefreshTokenConfig<TContext = any, TUser = any> extends TokenConfig<TContext, TUser> {
|
|
277
|
+
absoluteExpiry?: AbsoluteExpiryConfig;
|
|
278
|
+
}
|
|
279
|
+
export interface AbsoluteExpiryConfig {
|
|
280
|
+
payloadField?: string;
|
|
281
|
+
onExpiry?: "error" | "logout" | "ignore";
|
|
282
|
+
}
|
|
283
|
+
export interface TokenRotationConfig<TContext, TUser> {
|
|
284
|
+
maxRotations: number;
|
|
285
|
+
getRotationCount: (token: string, user: TUser, context: TContext) => Promise<number>;
|
|
286
|
+
rotateToken: (oldToken: string, user: TUser, context: TContext) => Promise<{
|
|
287
|
+
newToken: string;
|
|
288
|
+
newRotationCount?: number;
|
|
289
|
+
}>;
|
|
290
|
+
afterRotation?: (oldToken: string, newToken: string, user: TUser, context: TContext, rotationCount?: number) => Promise<void>;
|
|
291
|
+
isLimitReached?: (rotationCount: number, maxRotations: number | undefined, user: TUser, context: TContext) => boolean;
|
|
272
292
|
}
|
|
273
293
|
export interface PKCEConfig<TContext> {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
294
|
+
challenge: {
|
|
295
|
+
expiresIn?: number;
|
|
296
|
+
generate?: (codeVerifier: string) => string;
|
|
297
|
+
embed?: (context: TContext, challenge: string) => void;
|
|
298
|
+
extract?: (context: TContext) => string | null;
|
|
299
|
+
persistence?: PersistenceConfig;
|
|
300
|
+
};
|
|
301
|
+
verifier: {
|
|
302
|
+
expiresIn?: number;
|
|
303
|
+
generate?: () => string;
|
|
304
|
+
embed?: (context: TContext, codeVerifier: string) => void;
|
|
305
|
+
extract?: (context: TContext) => string | null;
|
|
306
|
+
persistence?: PersistenceConfig;
|
|
307
|
+
};
|
|
277
308
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import * as Soap from "@soapjs/soap";
|
|
2
|
-
import { AuthStrategy, SessionConfig, SoapAuthConfig } from "../types";
|
|
3
|
-
import { SessionHandler } from "../session/session-handler";
|
|
4
|
-
export declare abstract class AuthStrategyFactory {
|
|
5
|
-
protected logger?: Soap.Logger;
|
|
6
|
-
abstract createStrategies(config: SoapAuthConfig): Map<string, AuthStrategy>;
|
|
7
|
-
constructor(logger?: Soap.Logger);
|
|
8
|
-
protected getSessionHandler(strategyConfig: SessionConfig, globalConfig: SessionConfig): SessionHandler<unknown, any>;
|
|
9
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AuthStrategyFactory = void 0;
|
|
4
|
-
const tools_1 = require("../tools/tools");
|
|
5
|
-
const session_handler_1 = require("../session/session-handler");
|
|
6
|
-
class AuthStrategyFactory {
|
|
7
|
-
logger;
|
|
8
|
-
constructor(logger) {
|
|
9
|
-
this.logger = logger;
|
|
10
|
-
}
|
|
11
|
-
getSessionHandler(strategyConfig, globalConfig) {
|
|
12
|
-
const sessionConfig = (0, tools_1.resolveConfig)(strategyConfig, globalConfig);
|
|
13
|
-
return sessionConfig ? new session_handler_1.SessionHandler(sessionConfig) : undefined;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
exports.AuthStrategyFactory = AuthStrategyFactory;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { AuthStrategy, SoapAuthConfig } from "../types";
|
|
2
|
-
import { AuthStrategyFactory } from "./auth-strategy.factory";
|
|
3
|
-
export declare class HttpAuthStrategyFactory extends AuthStrategyFactory {
|
|
4
|
-
createStrategies(config: SoapAuthConfig): Map<string, AuthStrategy>;
|
|
5
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.HttpAuthStrategyFactory = void 0;
|
|
4
|
-
const oauth2_strategy_1 = require("../strategies/oauth2/oauth2.strategy");
|
|
5
|
-
const api_key_strategy_1 = require("../strategies/api-key/api-key.strategy");
|
|
6
|
-
const jwt_strategy_1 = require("../strategies/jwt/jwt.strategy");
|
|
7
|
-
const basic_strategy_1 = require("../strategies/basic/basic.strategy");
|
|
8
|
-
const auth_strategy_factory_1 = require("./auth-strategy.factory");
|
|
9
|
-
const local_strategy_1 = require("../strategies/local/local.strategy");
|
|
10
|
-
class HttpAuthStrategyFactory extends auth_strategy_factory_1.AuthStrategyFactory {
|
|
11
|
-
createStrategies(config) {
|
|
12
|
-
const strategies = new Map();
|
|
13
|
-
if (!config.http) {
|
|
14
|
-
return strategies;
|
|
15
|
-
}
|
|
16
|
-
if (config.http.oauth2) {
|
|
17
|
-
for (const provider in config.http.oauth2) {
|
|
18
|
-
strategies.set(provider, new oauth2_strategy_1.OAuth2Strategy(config.http.oauth2[provider], this.getSessionHandler(config.http.oauth2[provider].session, config.session), config.logger));
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
if (config.http.apiKey) {
|
|
22
|
-
strategies.set("apiKey", new api_key_strategy_1.ApiKeyStrategy(config.http.apiKey, this.logger));
|
|
23
|
-
}
|
|
24
|
-
if (config.http.basic) {
|
|
25
|
-
strategies.set("basic", new basic_strategy_1.BasicStrategy(config.http.basic, this.getSessionHandler(config.http.basic.session, config.session), config.logger));
|
|
26
|
-
}
|
|
27
|
-
if (config.http.local) {
|
|
28
|
-
strategies.set("local", new local_strategy_1.LocalStrategy(config.http.local, this.getSessionHandler(config.http.local.session, config.session), config.logger));
|
|
29
|
-
}
|
|
30
|
-
if (config.http.jwt) {
|
|
31
|
-
strategies.set("jwt", new jwt_strategy_1.JwtStrategy(config.http.jwt, this.getSessionHandler(config.http.jwt.session, config.session), this.logger));
|
|
32
|
-
}
|
|
33
|
-
if (config.http.custom) {
|
|
34
|
-
Object.entries(config.http.custom).forEach(([key, strategy]) => {
|
|
35
|
-
strategies.set(key, strategy);
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
return strategies;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
exports.HttpAuthStrategyFactory = HttpAuthStrategyFactory;
|