@soapjs/soap-auth 0.1.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +120 -169
  2. package/build/factories/http-auth-strategy.factory.js +1 -1
  3. package/build/factories/index.d.ts +3 -0
  4. package/build/factories/index.js +19 -0
  5. package/build/index.d.ts +4 -25
  6. package/build/index.js +4 -25
  7. package/build/session/index.d.ts +3 -0
  8. package/build/session/index.js +19 -0
  9. package/build/soap-auth.d.ts +9 -9
  10. package/build/soap-auth.js +64 -34
  11. package/build/strategies/api-key/api-key.strategy.d.ts +4 -3
  12. package/build/strategies/api-key/api-key.strategy.js +9 -6
  13. package/build/strategies/api-key/api-key.types.d.ts +2 -4
  14. package/build/strategies/base-auth.strategy.d.ts +4 -3
  15. package/build/strategies/base-auth.strategy.js +18 -2
  16. package/build/strategies/basic/basic.strategy.d.ts +5 -11
  17. package/build/strategies/basic/basic.strategy.js +14 -19
  18. package/build/strategies/basic/basic.types.d.ts +2 -2
  19. package/build/strategies/{credential-based-auth.strategy.d.ts → credential-auth.strategy.d.ts} +15 -12
  20. package/build/strategies/{credential-based-auth.strategy.js → credential-auth.strategy.js} +95 -46
  21. package/build/strategies/index.d.ts +16 -0
  22. package/build/strategies/index.js +32 -0
  23. package/build/strategies/jwt/jwt.strategy.d.ts +17 -2
  24. package/build/strategies/jwt/jwt.strategy.js +118 -57
  25. package/build/strategies/jwt/jwt.tools.d.ts +7 -3
  26. package/build/strategies/jwt/jwt.tools.js +80 -41
  27. package/build/strategies/jwt/jwt.types.d.ts +3 -27
  28. package/build/strategies/local/local.strategy.d.ts +3 -9
  29. package/build/strategies/local/local.strategy.js +7 -58
  30. package/build/strategies/local/local.types.d.ts +2 -2
  31. package/build/strategies/oauth2/oauth2.strategy.d.ts +21 -7
  32. package/build/strategies/oauth2/oauth2.strategy.js +158 -49
  33. package/build/strategies/oauth2/oauth2.types.d.ts +8 -16
  34. package/build/strategies/token-auth.strategy.d.ts +25 -0
  35. package/build/strategies/token-auth.strategy.js +78 -0
  36. package/build/tools/index.d.ts +3 -0
  37. package/build/tools/index.js +19 -0
  38. package/build/types.d.ts +87 -57
  39. package/package.json +2 -1
  40. package/build/strategies/token-based-auth.strategy.d.ts +0 -25
  41. package/build/strategies/token-based-auth.strategy.js +0 -130
@@ -6,85 +6,163 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.OAuth2Strategy = void 0;
7
7
  const axios_1 = __importDefault(require("axios"));
8
8
  const errors_1 = require("../../errors");
9
- const token_based_auth_strategy_1 = require("../token-based-auth.strategy");
10
9
  const oauth2_tools_1 = require("./oauth2.tools");
11
- class OAuth2Strategy extends token_based_auth_strategy_1.TokenBasedAuthStrategy {
10
+ const base_auth_strategy_1 = require("../base-auth.strategy");
11
+ class OAuth2Strategy extends base_auth_strategy_1.BaseAuthStrategy {
12
12
  config;
13
- accessTokenConfig;
14
- refreshTokenConfig;
15
13
  session;
16
14
  logger;
17
- constructor(config, accessTokenConfig, refreshTokenConfig, session, logger) {
18
- super(config, accessTokenConfig, refreshTokenConfig, session, logger);
15
+ constructor(config, session, logger) {
16
+ super(config, session, logger);
19
17
  this.config = config;
20
- this.accessTokenConfig = accessTokenConfig;
21
- this.refreshTokenConfig = refreshTokenConfig;
22
18
  this.session = session;
23
19
  this.logger = logger;
24
20
  this.config.scope = this.config.scope ?? "email";
25
21
  }
22
+ async logout(context) {
23
+ try {
24
+ await this.storeAccessToken("", context);
25
+ await this.storeRefreshToken("", context);
26
+ if (this.config.endpoints.logoutUrl) {
27
+ this.logger?.info("Redirecting to OAuth2 logout endpoint.");
28
+ this.redirectUser(context, this.config.endpoints.logoutUrl);
29
+ }
30
+ }
31
+ catch (error) {
32
+ this.logger?.error("Logout failed:", error);
33
+ throw new Error("Logout failed.");
34
+ }
35
+ }
36
+ async getCredentialsForPasswordGrant(context) {
37
+ if (this.config.credentials?.extractCredentials) {
38
+ return this.config.credentials.extractCredentials(context);
39
+ }
40
+ else if (typeof context === "object" && "body" in context) {
41
+ const body = context.body;
42
+ if (body.username && body.password) {
43
+ return {
44
+ identifier: body.username,
45
+ password: body.password,
46
+ };
47
+ }
48
+ }
49
+ throw new Error("Missing credentials for password grant.");
50
+ }
51
+ retrieveAccessToken(context) {
52
+ if (this.config.accessToken?.retrieve) {
53
+ return this.config.accessToken.retrieve(context);
54
+ }
55
+ if (typeof context === "object" && "headers" in context) {
56
+ const authHeader = context.headers?.authorization;
57
+ if (authHeader?.startsWith("Bearer ")) {
58
+ return authHeader.split(" ")[1];
59
+ }
60
+ }
61
+ if (typeof context === "object" && "cookies" in context) {
62
+ return context.cookies?.access_token;
63
+ }
64
+ return undefined;
65
+ }
66
+ retrieveRefreshToken(context) {
67
+ if (this.config.refreshToken?.retrieve) {
68
+ return this.config.refreshToken.retrieve(context);
69
+ }
70
+ if (typeof context === "object" && "cookies" in context) {
71
+ return context.cookies?.refresh_token;
72
+ }
73
+ return undefined;
74
+ }
75
+ storeAccessToken(token, context) {
76
+ if (this.config.accessToken?.persistence?.store) {
77
+ return this.config.accessToken.persistence.store(token, context, this.config.accessToken.issuer.options.expiresIn);
78
+ }
79
+ if (typeof context === "object" && "cookies" in context) {
80
+ context.cookies.set("access_token", token, { httpOnly: true });
81
+ }
82
+ }
83
+ storeRefreshToken(token, context) {
84
+ if (this.config.refreshToken?.persistence?.store) {
85
+ return this.config.refreshToken.persistence.store(token, context, this.config.refreshToken.issuer.options.expiresIn);
86
+ }
87
+ if (typeof context === "object" && "cookies" in context) {
88
+ context.cookies.set("refresh_token", token, { httpOnly: true });
89
+ }
90
+ }
91
+ embedAccessToken(token, context) {
92
+ if (this.config.accessToken?.embed) {
93
+ this.config.accessToken.embed(context, token);
94
+ }
95
+ else if (typeof context === "object" && "response" in context) {
96
+ context.response.setHeader("Authorization", `Bearer ${token}`);
97
+ }
98
+ }
99
+ embedRefreshToken(token, context) {
100
+ if (this.config.refreshToken?.embed) {
101
+ return this.config.refreshToken.embed(context, token);
102
+ }
103
+ else if (typeof context === "object" && "cookies" in context) {
104
+ context.cookies.set("refresh_token", token, { httpOnly: true });
105
+ }
106
+ }
107
+ async isTokenExpired(token) {
108
+ try {
109
+ const parts = token.split(".");
110
+ if (parts.length !== 3) {
111
+ this.logger?.warn("Non-JWT token provided, cannot determine expiration.");
112
+ return false;
113
+ }
114
+ const decoded = JSON.parse(Buffer.from(parts[1], "base64").toString());
115
+ if (!decoded.exp)
116
+ return false;
117
+ const currentTime = Math.floor(Date.now() / 1000);
118
+ return decoded.exp < currentTime;
119
+ }
120
+ catch (error) {
121
+ this.logger?.warn("Failed to decode token:", error);
122
+ return false;
123
+ }
124
+ }
26
125
  async authenticate(context) {
27
126
  try {
28
127
  let user;
29
128
  let refreshToken;
30
- let accessToken = await this.accessTokenConfig.retrieve?.(context);
129
+ let accessToken = await this.retrieveAccessToken(context);
31
130
  if (!accessToken) {
32
131
  this.logger?.info("No access token found, checking for refresh token.");
33
- refreshToken = await this.refreshTokenConfig?.retrieve?.(context);
132
+ refreshToken = await this.retrieveRefreshToken(context);
34
133
  if (refreshToken) {
35
134
  this.logger?.info("Found refresh token, attempting to refresh access token.");
36
135
  const newTokens = await this.refreshAccessToken(context);
37
136
  accessToken = newTokens.accessToken;
38
- this.accessTokenConfig.embed?.(context, accessToken);
137
+ this.embedAccessToken(accessToken, context);
39
138
  if (newTokens.refreshToken) {
40
139
  refreshToken = newTokens.refreshToken;
41
- this.refreshTokenConfig?.embed?.(context, newTokens.refreshToken);
140
+ this.embedRefreshToken(newTokens.refreshToken, context);
42
141
  }
43
142
  }
44
143
  else {
45
144
  this.logger?.info("No refresh token found, attempting authentication using grant type.");
46
- switch (this.config.grantType) {
47
- case "authorization_code":
48
- const authorizationCode = this.extractAuthorizationCode(context);
49
- this.verifyAuthorizationCode(context, authorizationCode);
50
- const tokenResult = await this.exchangeCodeForToken(context, authorizationCode);
51
- accessToken = tokenResult.accessToken;
52
- refreshToken = tokenResult.refreshToken;
53
- break;
54
- case "client_credentials":
55
- this.logger?.info("Using client credentials grant.");
56
- const clientCredResult = await this.exchangeClientCredentials();
57
- accessToken = clientCredResult.accessToken;
58
- break;
59
- case "password":
60
- this.logger?.info("Using password grant.");
61
- if (!this.config.credentials) {
62
- throw new Error("Missing credentials for password grant.");
63
- }
64
- const passwordResult = await this.exchangePasswordGrant();
65
- accessToken = passwordResult.accessToken;
66
- break;
67
- default:
68
- throw new Error(`Unsupported grant type: ${this.config.grantType}`);
69
- }
70
- this.accessTokenConfig.embed?.(context, accessToken);
145
+ const tokens = await this.processOAuthFlow(context);
146
+ accessToken = tokens.accessToken;
147
+ refreshToken = tokens.refreshToken;
148
+ this.embedAccessToken(accessToken, context);
71
149
  if (refreshToken) {
72
- this.refreshTokenConfig?.embed?.(context, refreshToken);
150
+ this.embedRefreshToken(refreshToken, context);
73
151
  }
74
152
  }
75
153
  }
76
154
  else if (accessToken && (await this.isTokenExpired(accessToken))) {
77
155
  this.logger?.info("Access token expired, attempting refresh.");
78
- refreshToken = await this.refreshTokenConfig?.retrieve?.(context);
156
+ refreshToken = await this.retrieveRefreshToken(context);
79
157
  if (!refreshToken) {
80
158
  throw new errors_1.MissingTokenError("Refresh");
81
159
  }
82
160
  const newTokens = await this.refreshAccessToken(context);
83
161
  accessToken = newTokens.accessToken;
84
- this.accessTokenConfig.embed?.(context, accessToken);
162
+ this.embedAccessToken(accessToken, context);
85
163
  if (newTokens.refreshToken && newTokens.refreshToken !== refreshToken) {
86
164
  refreshToken = newTokens.refreshToken;
87
- this.refreshTokenConfig?.embed?.(context, newTokens.refreshToken);
165
+ this.embedRefreshToken(newTokens.refreshToken, context);
88
166
  }
89
167
  }
90
168
  if (!accessToken) {
@@ -92,6 +170,7 @@ class OAuth2Strategy extends token_based_auth_strategy_1.TokenBasedAuthStrategy
92
170
  }
93
171
  user = await this.retrieveUser(accessToken);
94
172
  if (!user) {
173
+ this.logger?.error("User retrieval failed: No user found for access token.");
95
174
  throw new errors_1.UserNotFoundError();
96
175
  }
97
176
  await this.isAuthorized(user);
@@ -102,6 +181,29 @@ class OAuth2Strategy extends token_based_auth_strategy_1.TokenBasedAuthStrategy
102
181
  throw new errors_1.AuthError(error, "OAuth2 authentication failed.");
103
182
  }
104
183
  }
184
+ async processOAuthFlow(context) {
185
+ if (this.config.grantType === "authorization_code") {
186
+ const authorizationCode = this.extractAuthorizationCode(context);
187
+ this.verifyAuthorizationCode(context, authorizationCode);
188
+ const tokenResult = await this.exchangeCodeForToken(context, authorizationCode);
189
+ return tokenResult;
190
+ }
191
+ if (this.config.grantType === "client_credentials") {
192
+ this.logger?.info("Using client credentials grant.");
193
+ const clientCredResult = await this.exchangeClientCredentials();
194
+ return { accessToken: clientCredResult.accessToken };
195
+ }
196
+ if (this.config.grantType === "password") {
197
+ this.logger?.info("Using password grant.");
198
+ const credentials = await this.getCredentialsForPasswordGrant(context);
199
+ if (!credentials) {
200
+ throw new Error("Missing credentials for password grant.");
201
+ }
202
+ const passwordResult = await this.exchangePasswordGrant(credentials.identifier, credentials.password);
203
+ return { accessToken: passwordResult.accessToken };
204
+ }
205
+ throw new Error(`Unsupported grant type: ${this.config.grantType}`);
206
+ }
105
207
  verifyAuthorizationCode(context, code) {
106
208
  if (!code) {
107
209
  this.logger?.warn("Authorization code missing, redirecting user.");
@@ -185,7 +287,7 @@ class OAuth2Strategy extends token_based_auth_strategy_1.TokenBasedAuthStrategy
185
287
  const response = await axios_1.default.get(this.config.endpoints.userInfoUrl, {
186
288
  headers: { Authorization: `Bearer ${accessToken}` },
187
289
  });
188
- return (await this.config.validateUser?.(response.data)) || null;
290
+ return (await this.config.user.validateUser(response.data)) || null;
189
291
  }
190
292
  catch (error) {
191
293
  this.logger?.error("Failed to fetch user information:", error);
@@ -200,22 +302,22 @@ class OAuth2Strategy extends token_based_auth_strategy_1.TokenBasedAuthStrategy
200
302
  });
201
303
  return { accessToken: response.data.access_token };
202
304
  }
203
- async exchangePasswordGrant() {
204
- if (!this.config.credentials) {
305
+ async exchangePasswordGrant(username, password) {
306
+ if (!username || !password) {
205
307
  throw new Error("Missing credentials for password grant.");
206
308
  }
207
309
  const response = await axios_1.default.post(this.config.endpoints.tokenUrl, {
208
310
  grant_type: "password",
209
311
  client_id: this.config.clientId,
210
312
  client_secret: this.config.clientSecret,
211
- username: this.config.credentials.username,
212
- password: this.config.credentials.password,
313
+ username,
314
+ password,
213
315
  });
214
316
  return { accessToken: response.data.access_token };
215
317
  }
216
318
  async refreshAccessToken(context) {
217
319
  try {
218
- const refreshToken = await this.refreshTokenConfig?.retrieve?.(context);
320
+ const refreshToken = await this.retrieveRefreshToken(context);
219
321
  if (!refreshToken) {
220
322
  throw new errors_1.MissingTokenError("Refresh");
221
323
  }
@@ -225,13 +327,20 @@ class OAuth2Strategy extends token_based_auth_strategy_1.TokenBasedAuthStrategy
225
327
  client_secret: this.config.clientSecret,
226
328
  refresh_token: refreshToken,
227
329
  });
330
+ if (response.status !== 200 || !response.data.access_token) {
331
+ throw new Error("Failed to refresh token");
332
+ }
228
333
  const refreshedTokens = {
229
334
  accessToken: response.data.access_token,
230
335
  refreshToken: response.data.refresh_token,
231
336
  };
232
- await this.accessTokenConfig.embed?.(context, refreshedTokens.accessToken);
337
+ await this.storeAccessToken(refreshedTokens.accessToken, context);
338
+ if (refreshedTokens.refreshToken) {
339
+ await this.storeRefreshToken(refreshedTokens.refreshToken, context);
340
+ }
341
+ await this.embedAccessToken(refreshedTokens.accessToken, context);
233
342
  if (refreshedTokens.refreshToken) {
234
- await this.refreshTokenConfig?.embed?.(context, refreshedTokens.refreshToken);
343
+ await this.embedRefreshToken(refreshedTokens.refreshToken, context);
235
344
  }
236
345
  return refreshedTokens;
237
346
  }
@@ -1,29 +1,21 @@
1
- import { TokenBasedAuthStrategyConfig, TokenConfig } from "../../types";
1
+ import { CredentailsConfig, PKCEConfig, TokenAuthStrategyConfig } from "../../types";
2
2
  export interface OAuth2Endpoints {
3
3
  authorizationUrl: string;
4
4
  tokenUrl: string;
5
5
  userInfoUrl?: string;
6
6
  introspectionUrl?: string;
7
7
  revocationUrl?: string;
8
+ logoutUrl?: string;
8
9
  }
9
- export interface OAuth2StrategyConfig<TContext = unknown, TUser = unknown> extends TokenBasedAuthStrategyConfig<TContext, TUser> {
10
+ export interface OAuth2StrategyConfig<TContext = unknown, TUser = unknown> extends TokenAuthStrategyConfig<TContext, TUser> {
10
11
  clientId: string;
11
12
  clientSecret: string;
12
13
  redirectUri: string;
13
- scope?: string;
14
- grantType: "authorization_code" | "client_credentials" | "password" | "refresh_token";
14
+ scope?: string | string[];
15
+ audience?: string;
16
+ responseType?: "code" | "token" | "id_token" | string;
17
+ grantType: "authorization_code" | "client_credentials" | "password" | "refresh_token" | string;
15
18
  endpoints: OAuth2Endpoints;
16
- validateUser?: (tokenPayload: any) => Promise<TUser | null>;
17
- credentials?: {
18
- username: string;
19
- password: string;
20
- };
19
+ credentials?: CredentailsConfig<TContext>;
21
20
  pkce?: PKCEConfig<TContext>;
22
- accessToken?: TokenConfig;
23
- refreshToken?: TokenConfig;
24
- }
25
- export interface PKCEConfig<TContext> {
26
- generateCodeVerifier?: () => string;
27
- storeCodeVerifier?: (context: TContext, codeVerifier: string) => void;
28
- retrieveCodeVerifier?: (context: TContext) => string | null;
29
21
  }
@@ -0,0 +1,25 @@
1
+ import * as Soap from "@soapjs/soap";
2
+ import { AuthResult, TokenAuthStrategyConfig } from "../types";
3
+ import { BaseAuthStrategy } from "./base-auth.strategy";
4
+ import { SessionHandler } from "../session/session-handler";
5
+ export declare abstract class TokenAuthStrategy<TContext = unknown, TUser = unknown> extends BaseAuthStrategy<TContext, TUser> {
6
+ protected config: TokenAuthStrategyConfig<TContext, TUser>;
7
+ protected session?: SessionHandler;
8
+ protected logger?: Soap.Logger;
9
+ constructor(config: TokenAuthStrategyConfig<TContext, TUser>, session?: SessionHandler, logger?: Soap.Logger);
10
+ protected abstract retrieveAccessToken(context: TContext): Promise<string | undefined>;
11
+ protected abstract retrieveRefreshToken(context: TContext): Promise<string | undefined>;
12
+ protected abstract verifyAccessToken(token: string): Promise<any>;
13
+ protected abstract verifyRefreshToken(token: string): Promise<any>;
14
+ protected abstract generateAccessToken(payload: any): Promise<string>;
15
+ protected abstract generateRefreshToken(payload: any): Promise<string>;
16
+ protected abstract storeAccessToken(token: string, context: TContext): Promise<void>;
17
+ protected abstract storeRefreshToken(token: string, context: TContext): Promise<void>;
18
+ protected abstract embedAccessToken(token: string, context: TContext): void;
19
+ protected abstract embedRefreshToken(token: string, context: TContext): void;
20
+ authenticate(context: TContext): Promise<AuthResult<TUser>>;
21
+ rotateTokens(context: TContext): Promise<{
22
+ accessToken: string;
23
+ refreshToken?: string;
24
+ }>;
25
+ }
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenAuthStrategy = void 0;
4
+ const base_auth_strategy_1 = require("./base-auth.strategy");
5
+ const errors_1 = require("../errors");
6
+ class TokenAuthStrategy extends base_auth_strategy_1.BaseAuthStrategy {
7
+ config;
8
+ session;
9
+ logger;
10
+ constructor(config, session, logger) {
11
+ super(config, session, logger);
12
+ this.config = config;
13
+ this.session = session;
14
+ this.logger = logger;
15
+ }
16
+ async authenticate(context) {
17
+ try {
18
+ let accessToken = await this.retrieveAccessToken(context);
19
+ let refreshToken;
20
+ await this.checkRateLimit(context);
21
+ if (accessToken) {
22
+ try {
23
+ const decoded = await this.verifyAccessToken(accessToken);
24
+ const user = await this.config.user.getUserData(decoded);
25
+ if (!user)
26
+ throw new errors_1.UserNotFoundError();
27
+ await this.isAuthorized(user);
28
+ return { user, tokens: { accessToken } };
29
+ }
30
+ catch (error) {
31
+ this.logger?.warn("Access token is invalid or expired, trying refresh token...");
32
+ }
33
+ }
34
+ refreshToken = await this.retrieveRefreshToken(context);
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)
41
+ throw new errors_1.MissingTokenError("Access");
42
+ const decoded = await this.verifyAccessToken(accessToken);
43
+ const user = await this.config.user.getUserData(decoded);
44
+ if (!user)
45
+ throw new errors_1.UserNotFoundError();
46
+ await this.isAuthorized(user);
47
+ return { user, tokens: { accessToken, refreshToken } };
48
+ }
49
+ catch (error) {
50
+ this.logger?.error("Authentication failed:", error);
51
+ throw new errors_1.AuthError(error, "Authentication failed.");
52
+ }
53
+ }
54
+ async rotateTokens(context) {
55
+ try {
56
+ const refreshToken = await this.retrieveRefreshToken(context);
57
+ if (!refreshToken)
58
+ throw new errors_1.MissingTokenError("Refresh");
59
+ const payload = await this.verifyRefreshToken(refreshToken);
60
+ if (!payload)
61
+ 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
+ }
68
+ this.embedAccessToken(newAccessToken, context);
69
+ this.embedRefreshToken(newRefreshToken, context);
70
+ return { accessToken: newAccessToken, refreshToken: newRefreshToken };
71
+ }
72
+ catch (error) {
73
+ this.logger?.error("Token rotation failed:", error);
74
+ throw new errors_1.InvalidTokenError("Refresh");
75
+ }
76
+ }
77
+ }
78
+ exports.TokenAuthStrategy = TokenAuthStrategy;
@@ -0,0 +1,3 @@
1
+ export * from "./session.tools";
2
+ export * from "./token.tools";
3
+ export * from "./tools";
@@ -0,0 +1,19 @@
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./session.tools"), exports);
18
+ __exportStar(require("./token.tools"), exports);
19
+ __exportStar(require("./tools"), exports);
package/build/types.d.ts CHANGED
@@ -36,21 +36,22 @@ export type Credentials = {
36
36
  [key: string]: unknown;
37
37
  };
38
38
  export interface AuthResultConfig<TContext = unknown, TUser = unknown> {
39
- onSuccess?: (context: AuthSuccessContext<TUser, TContext>) => Promise<void> | void;
40
- onFailure?: (context: AuthFailureContext<TContext>) => Promise<void> | void;
39
+ onSuccess?: (action: string, context: AuthSuccessContext<TUser, TContext>) => Promise<void> | void;
40
+ onFailure?: (action: string, context: AuthFailureContext<TContext>) => Promise<void> | void;
41
41
  }
42
42
  export interface SecurityConfig {
43
43
  maxFailedLoginAttempts?: number;
44
44
  lockoutDuration?: number;
45
45
  notifyOnLockout?: (account: any) => Promise<void>;
46
46
  }
47
- export interface BaseAuthStrategyConfig<TContext = unknown, TUser = unknown> {
47
+ export interface BaseAuthStrategyConfig<TContext = unknown, TUser = unknown> extends AuthResultConfig<TContext, TUser> {
48
48
  mfa?: MfaConfig<TUser, TContext>;
49
49
  session?: SessionConfig;
50
50
  role?: RoleAuthorizationConfig<TUser>;
51
51
  rateLimit?: RateLimitConfig;
52
52
  security?: SecurityConfig;
53
53
  lock?: AccountLockConfig<TContext>;
54
+ failedAttempts?: FailedAttemptsConfig;
54
55
  }
55
56
  export interface AuditLoggingConfig<TContext = unknown> {
56
57
  logAttempt?: (userId: string, success: boolean, context?: TContext) => Promise<void>;
@@ -77,54 +78,58 @@ export interface PasswordPolicyConfig {
77
78
  getLastPasswordChange?: (identifier: string) => Date;
78
79
  forcePasswordChangeOnFirstLogin?: boolean;
79
80
  passwordExpirationDays?: number;
81
+ isPasswordChangeRequired?: (identifier: string) => Promise<boolean>;
82
+ generateResetToken?: (identifier: string) => Promise<string>;
83
+ sendResetEmail?: (identifier: string, token: string) => Promise<void>;
84
+ validateResetToken?: (token: string) => Promise<boolean>;
85
+ updatePassword?: (identifier: string, newPassword: string) => Promise<void>;
80
86
  }
81
- export interface CredentialBasedAuthStrategyConfig<TContext = unknown, TUser = unknown> extends BaseAuthStrategyConfig<TContext, TUser> {
87
+ export interface UserConfig {
88
+ getUserData: (payload: any) => Promise<any>;
89
+ validateUser?: (payload: any) => Promise<any>;
90
+ }
91
+ export interface CredentailsConfig<TContext = any> {
92
+ extractCredentials: <TCredentials = {
93
+ identifier: string;
94
+ password: string;
95
+ }>(context: TContext) => TCredentials;
96
+ verifyCredentials: (identifier: string, password: string) => Promise<boolean>;
97
+ }
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
+ export interface CredentialAuthStrategyConfig<TContext = unknown, TUser = unknown> extends BaseAuthStrategyConfig<TContext, TUser> {
82
104
  passwordPolicy?: PasswordPolicyConfig;
83
105
  audit?: AuditLoggingConfig<TContext>;
84
- logout: {} & AuthResultConfig<TContext, TUser>;
85
- login: {
86
- extractCredentials: (context: TContext) => Promise<{
87
- identifier: string;
88
- password: string;
89
- }>;
90
- retrieveUserData: (identifier: string) => Promise<TUser | null>;
91
- verifyUserCredentials: (identifier: string, password: string) => Promise<boolean>;
92
- incrementFailedAttempts?: (identifier: string) => Promise<void>;
93
- resetFailedAttempts?: (identifier: string) => Promise<void>;
94
- getFailedAttempts?: (identifier: string) => Promise<number>;
95
- } & AuthResultConfig<TContext, TUser>;
96
- passwordReset?: {
97
- generateResetToken?: (identifier: string) => Promise<string>;
98
- sendResetEmail?: (identifier: string, token: string) => Promise<void>;
99
- validateResetToken?: (token: string) => Promise<boolean>;
100
- updatePassword?: (identifier: string, newPassword: string) => Promise<void>;
101
- } & AuthResultConfig<TContext, TUser>;
102
- }
103
- export interface TokenBasedAuthStrategyConfig<TContext = unknown, TUser = unknown> extends BaseAuthStrategyConfig<TContext, TUser> {
104
- rotation?: TokenRotationConfig<TUser>;
105
- login: {
106
- retrieveUserData: (identifier: string) => Promise<TUser | null>;
107
- } & AuthResultConfig<TContext, TUser>;
108
- logout: {} & AuthResultConfig<TContext, TUser>;
109
- }
110
- export interface TokenRotationConfig<TUser = unknown> {
111
- maxRotations?: number;
112
- storeUsedTokens?: boolean;
113
- getRefreshToken?: (user: TUser) => Promise<string>;
114
- rotateToken?: (refreshToken: string) => Promise<{
115
- accessToken: string;
116
- refreshToken: string;
117
- }>;
118
- onTokenRotated?: (user: TUser, newTokens: {
119
- accessToken: string;
120
- refreshToken: string;
121
- }) => Promise<void>;
122
- onTokenRotationFailure?: (user: TUser, error: Error) => Promise<void>;
106
+ credentials?: CredentailsConfig<TContext>;
107
+ user?: UserConfig;
108
+ routes?: {
109
+ login?: AuthRouteConfig;
110
+ logout?: AuthRouteConfig;
111
+ resetPassword?: AuthRouteConfig;
112
+ };
113
+ }
114
+ export type AuthRouteConfig = {
115
+ path?: string;
116
+ method?: string;
117
+ };
118
+ export interface TokenAuthStrategyConfig<TContext = unknown, TUser = unknown> extends BaseAuthStrategyConfig<TContext, TUser> {
119
+ user?: UserConfig;
120
+ routes: {
121
+ login?: AuthRouteConfig;
122
+ logout?: AuthRouteConfig;
123
+ refresh?: AuthRouteConfig;
124
+ [key: string]: AuthRouteConfig;
125
+ };
126
+ accessToken?: TokenConfig<TContext>;
127
+ refreshToken?: TokenConfig<TContext>;
123
128
  }
124
129
  export interface AccountLockConfig<TContext = unknown> {
125
130
  logFailedAttempt?: (account: any, context?: TContext) => Promise<void>;
126
- lockAccount?: (account: any, ...args: unknown[]) => Promise<void>;
127
- isAccountLocked?: (account: any, ...args: unknown[]) => Promise<boolean>;
131
+ lockAccount?: (account: any) => Promise<void>;
132
+ isAccountLocked?: (account: any, context?: TContext) => Promise<boolean>;
128
133
  }
129
134
  export interface RateLimitConfig {
130
135
  checkRateLimit?: (...args: unknown[]) => Promise<boolean>;
@@ -159,7 +164,7 @@ export type AuthResult<TUser, TSessionData = unknown> = {
159
164
  };
160
165
  export interface AuthStrategy<TContext = unknown, TUser = unknown> {
161
166
  init?(...args: unknown[]): Promise<void>;
162
- authenticate(context?: TContext, ...args: unknown[]): Promise<AuthResult<TUser>>;
167
+ authenticate(context?: TContext, ...args: unknown[]): Promise<AuthResult<TUser> | null>;
163
168
  authorize?(user: any, action: string, resource?: string): Promise<boolean>;
164
169
  refresh?(refreshToken: string): Promise<string>;
165
170
  logout?(context?: TContext): Promise<void>;
@@ -230,18 +235,43 @@ export interface StorageContext {
230
235
  encrypt?: (data: string) => Promise<string> | string;
231
236
  decrypt?: (data: string) => Promise<string> | string;
232
237
  }
233
- export interface TokenConfig {
238
+ export interface TokenIssuerConfig {
234
239
  secretKey: string;
235
- expiresIn: string | number;
236
- audience?: string | string[];
237
- issuer?: string | string[];
238
- subject?: string;
239
- tokenType?: string;
240
+ options: {
241
+ expiresIn: string | number;
242
+ audience?: string | string[];
243
+ issuer?: string | string[];
244
+ subject?: string;
245
+ [option: string]: unknown;
246
+ };
240
247
  generate?: (payload: any) => string;
248
+ }
249
+ export interface TokenVerifierConfig {
250
+ options: {
251
+ [option: string]: unknown;
252
+ };
241
253
  verify?: (token: string) => Promise<any>;
242
- store?: (token: string, data: any, expiresIn: number) => Promise<void>;
243
- retrieve?: (context: any) => Promise<string | null>;
244
- remove?: (context: any) => Promise<void>;
245
- embed?: (context: any, token: string) => void;
246
- rotate?: (oldToken: string) => Promise<string>;
254
+ }
255
+ export interface TokenPersistenceConfig {
256
+ store?: (token: string, data: any, expiresIn: string | number) => Promise<void>;
257
+ read?: (...args: any[]) => Promise<string | null>;
258
+ remove?: (...args: any[]) => Promise<void>;
259
+ }
260
+ export interface TokenConfig<TContext = any> {
261
+ embed?: (context: TContext, token: string) => void;
262
+ retrieve?: (context: TContext) => Promise<string | null>;
263
+ rotation?: TokenRotationConfig;
264
+ issuer?: TokenIssuerConfig;
265
+ verifier?: TokenVerifierConfig;
266
+ persistence?: TokenPersistenceConfig;
267
+ additional?: Record<string, unknown>;
268
+ }
269
+ export interface TokenRotationConfig {
270
+ maxRotations?: number;
271
+ rotateToken?: (token: string) => Promise<string>;
272
+ }
273
+ export interface PKCEConfig<TContext> {
274
+ generateCodeVerifier?: () => string;
275
+ storeCodeVerifier?: (context: TContext, codeVerifier: string) => void;
276
+ retrieveCodeVerifier?: (context: TContext) => string | null;
247
277
  }