@soapjs/soap-auth 0.1.1 → 0.2.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 +475 -8
  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 +1 -1
  40. package/build/strategies/token-based-auth.strategy.d.ts +0 -25
  41. package/build/strategies/token-based-auth.strategy.js +0 -130
@@ -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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soapjs/soap-auth",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "",
5
5
  "homepage": "https://docs.soapjs.com",
6
6
  "repository": "https://github.com/soapjs/soap-auth",
@@ -1,25 +0,0 @@
1
- import * as Soap from "@soapjs/soap";
2
- import { AuthResult, TokenBasedAuthStrategyConfig } from "../types";
3
- import { BaseAuthStrategy } from "./base-auth.strategy";
4
- import { TokenConfig } from "../types";
5
- import { SessionHandler } from "../session/session-handler";
6
- export declare abstract class TokenBasedAuthStrategy<TContext = unknown, TUser = unknown> extends BaseAuthStrategy<TContext, TUser> {
7
- protected config: TokenBasedAuthStrategyConfig<TContext, TUser>;
8
- protected accessTokenConfig?: TokenConfig;
9
- protected refreshTokenConfig?: TokenConfig;
10
- protected session?: SessionHandler;
11
- protected logger?: Soap.Logger;
12
- constructor(config: TokenBasedAuthStrategyConfig<TContext, TUser>, accessTokenConfig?: TokenConfig, refreshTokenConfig?: TokenConfig, session?: SessionHandler, logger?: Soap.Logger);
13
- protected retrieveUser(decodedToken: any): Promise<TUser | null>;
14
- authenticate(context: TContext): Promise<AuthResult<TUser>>;
15
- logout(context: TContext): Promise<void>;
16
- generateTokens(user: TUser, context: TContext): Promise<{
17
- accessToken: string;
18
- refreshToken?: string;
19
- }>;
20
- rotateToken(context: TContext): Promise<{
21
- accessToken: string;
22
- refreshToken?: string;
23
- }>;
24
- isTokenExpired(token: string): Promise<boolean>;
25
- }
@@ -1,130 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TokenBasedAuthStrategy = void 0;
4
- const base_auth_strategy_1 = require("./base-auth.strategy");
5
- const errors_1 = require("../errors");
6
- class TokenBasedAuthStrategy extends base_auth_strategy_1.BaseAuthStrategy {
7
- config;
8
- accessTokenConfig;
9
- refreshTokenConfig;
10
- session;
11
- logger;
12
- constructor(config, accessTokenConfig, refreshTokenConfig, session, logger) {
13
- super(config, session, logger);
14
- this.config = config;
15
- this.accessTokenConfig = accessTokenConfig;
16
- this.refreshTokenConfig = refreshTokenConfig;
17
- this.session = session;
18
- this.logger = logger;
19
- }
20
- retrieveUser(decodedToken) {
21
- return this.config.login.retrieveUserData(decodedToken);
22
- }
23
- async authenticate(context) {
24
- try {
25
- let accessToken = await this.accessTokenConfig.retrieve?.(context);
26
- let refreshToken;
27
- await this.checkRateLimit(context);
28
- if (accessToken) {
29
- try {
30
- const decoded = await this.accessTokenConfig.verify?.(accessToken);
31
- const user = await this.retrieveUser(decoded);
32
- if (!user) {
33
- throw new errors_1.UserNotFoundError();
34
- }
35
- await this.isAuthorized(user);
36
- return { user, tokens: { accessToken } };
37
- }
38
- catch (error) {
39
- this.logger?.warn("Access token is invalid or expired, trying refresh token...");
40
- }
41
- }
42
- if (this.refreshTokenConfig) {
43
- refreshToken = await this.refreshTokenConfig?.retrieve?.(context);
44
- if (!refreshToken) {
45
- throw new errors_1.MissingTokenError("Refresh");
46
- }
47
- accessToken = await this.refreshTokenConfig?.rotate?.(refreshToken);
48
- if (!accessToken) {
49
- throw new errors_1.MissingTokenError("Access");
50
- }
51
- }
52
- this.accessTokenConfig.embed?.(context, accessToken);
53
- const decoded = await this.accessTokenConfig.verify?.(accessToken);
54
- const user = await this.retrieveUser(decoded);
55
- if (!user) {
56
- throw new errors_1.UserNotFoundError();
57
- }
58
- await this.isAuthorized(user);
59
- return { user, tokens: { accessToken, refreshToken } };
60
- }
61
- catch (error) {
62
- this.logger?.error("Authentication failed:", error);
63
- throw new errors_1.AuthError(error, "Authentication failed.");
64
- }
65
- }
66
- async logout(context) {
67
- try {
68
- await this.accessTokenConfig.remove?.(context);
69
- if (this.refreshTokenConfig) {
70
- await this.refreshTokenConfig.remove?.(context);
71
- }
72
- await this.config.logout.onSuccess?.(context);
73
- this.logger?.info("User logged out successfully.");
74
- }
75
- catch (error) {
76
- this.logger?.error("Error during logout:", error);
77
- await this.config.logout.onFailure?.({ context, error });
78
- throw new errors_1.AuthError(error, "Logout process failed.");
79
- }
80
- }
81
- async generateTokens(user, context) {
82
- const payload = { userId: user.id, roles: user.roles };
83
- const accessToken = this.accessTokenConfig.generate?.(payload);
84
- if (!accessToken)
85
- throw new Error("Failed to generate access token.");
86
- await this.accessTokenConfig.store?.(accessToken, user, +this.accessTokenConfig.expiresIn);
87
- this.accessTokenConfig.embed?.(context, accessToken);
88
- let refreshToken;
89
- if (this.refreshTokenConfig) {
90
- refreshToken = this.refreshTokenConfig.generate?.(payload);
91
- if (refreshToken) {
92
- await this.refreshTokenConfig.store?.(refreshToken, user, +this.refreshTokenConfig.expiresIn);
93
- this.refreshTokenConfig.embed?.(context, refreshToken);
94
- }
95
- }
96
- return { accessToken, refreshToken };
97
- }
98
- async rotateToken(context) {
99
- try {
100
- if (!this.refreshTokenConfig) {
101
- throw new Error("Refresh token handler is not configured.");
102
- }
103
- const refreshToken = await this.refreshTokenConfig.retrieve?.(context);
104
- if (!refreshToken) {
105
- throw new errors_1.MissingTokenError("Refresh");
106
- }
107
- const newAccessToken = await this.refreshTokenConfig.rotate?.(refreshToken);
108
- this.accessTokenConfig.embed?.(context, newAccessToken);
109
- return { accessToken: newAccessToken, refreshToken };
110
- }
111
- catch (error) {
112
- this.logger?.error("Token rotation failed:", error);
113
- throw new errors_1.InvalidTokenError("Refresh");
114
- }
115
- }
116
- async isTokenExpired(token) {
117
- try {
118
- const decoded = JSON.parse(Buffer.from(token.split(".")[1], "base64").toString());
119
- if (!decoded.exp)
120
- return false;
121
- const currentTime = Math.floor(Date.now() / 1000);
122
- return decoded.exp < currentTime;
123
- }
124
- catch (error) {
125
- this.logger?.warn("Failed to decode token:", error);
126
- return false;
127
- }
128
- }
129
- }
130
- exports.TokenBasedAuthStrategy = TokenBasedAuthStrategy;