@soapjs/soap-auth 0.1.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 (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +223 -0
  3. package/build/errors.d.ts +53 -0
  4. package/build/errors.js +117 -0
  5. package/build/factories/auth-strategy.factory.d.ts +9 -0
  6. package/build/factories/auth-strategy.factory.js +16 -0
  7. package/build/factories/http-auth-strategy.factory.d.ts +5 -0
  8. package/build/factories/http-auth-strategy.factory.js +42 -0
  9. package/build/factories/socket-auth-strategy.factory.d.ts +5 -0
  10. package/build/factories/socket-auth-strategy.factory.js +27 -0
  11. package/build/index.d.ts +28 -0
  12. package/build/index.js +44 -0
  13. package/build/session/file.session-store.d.ts +10 -0
  14. package/build/session/file.session-store.js +59 -0
  15. package/build/session/memory.session-store.d.ts +7 -0
  16. package/build/session/memory.session-store.js +19 -0
  17. package/build/session/session-handler.d.ts +17 -0
  18. package/build/session/session-handler.js +145 -0
  19. package/build/soap-auth.d.ts +16 -0
  20. package/build/soap-auth.js +75 -0
  21. package/build/strategies/api-key/api-key.errors.d.ts +9 -0
  22. package/build/strategies/api-key/api-key.errors.js +24 -0
  23. package/build/strategies/api-key/api-key.strategy.d.ts +14 -0
  24. package/build/strategies/api-key/api-key.strategy.js +95 -0
  25. package/build/strategies/api-key/api-key.types.d.ts +13 -0
  26. package/build/strategies/api-key/api-key.types.js +2 -0
  27. package/build/strategies/base-auth.strategy.d.ts +17 -0
  28. package/build/strategies/base-auth.strategy.js +69 -0
  29. package/build/strategies/basic/basic.strategy.d.ts +25 -0
  30. package/build/strategies/basic/basic.strategy.js +53 -0
  31. package/build/strategies/basic/basic.types.d.ts +10 -0
  32. package/build/strategies/basic/basic.types.js +2 -0
  33. package/build/strategies/credential-based-auth.strategy.d.ts +30 -0
  34. package/build/strategies/credential-based-auth.strategy.js +205 -0
  35. package/build/strategies/jwt/jwt.strategy.d.ts +10 -0
  36. package/build/strategies/jwt/jwt.strategy.js +69 -0
  37. package/build/strategies/jwt/jwt.tools.d.ts +3 -0
  38. package/build/strategies/jwt/jwt.tools.js +79 -0
  39. package/build/strategies/jwt/jwt.types.d.ts +33 -0
  40. package/build/strategies/jwt/jwt.types.js +2 -0
  41. package/build/strategies/local/local.strategy.d.ts +25 -0
  42. package/build/strategies/local/local.strategy.js +76 -0
  43. package/build/strategies/local/local.types.d.ts +3 -0
  44. package/build/strategies/local/local.types.js +2 -0
  45. package/build/strategies/oauth2/oauth2.strategy.d.ts +35 -0
  46. package/build/strategies/oauth2/oauth2.strategy.js +259 -0
  47. package/build/strategies/oauth2/oauth2.tools.d.ts +4 -0
  48. package/build/strategies/oauth2/oauth2.tools.js +22 -0
  49. package/build/strategies/oauth2/oauth2.types.d.ts +29 -0
  50. package/build/strategies/oauth2/oauth2.types.js +2 -0
  51. package/build/strategies/token-based-auth.strategy.d.ts +25 -0
  52. package/build/strategies/token-based-auth.strategy.js +124 -0
  53. package/build/tools/session.tools.d.ts +6 -0
  54. package/build/tools/session.tools.js +15 -0
  55. package/build/tools/token.tools.d.ts +7 -0
  56. package/build/tools/token.tools.js +32 -0
  57. package/build/tools/tools.d.ts +3 -0
  58. package/build/tools/tools.js +23 -0
  59. package/build/types.d.ts +251 -0
  60. package/build/types.js +2 -0
  61. package/jest.config.unit.json +10 -0
  62. package/ldap.md +62 -0
  63. package/package.json +33 -0
  64. package/saml.md +244 -0
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.OAuth2Strategy = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const errors_1 = require("../../errors");
9
+ const token_based_auth_strategy_1 = require("../token-based-auth.strategy");
10
+ const oauth2_tools_1 = require("./oauth2.tools");
11
+ class OAuth2Strategy extends token_based_auth_strategy_1.TokenBasedAuthStrategy {
12
+ config;
13
+ accessTokenHandler;
14
+ refreshTokenHandler;
15
+ session;
16
+ logger;
17
+ constructor(config, accessTokenHandler, refreshTokenHandler, session, logger) {
18
+ super(config, accessTokenHandler, refreshTokenHandler, session, logger);
19
+ this.config = config;
20
+ this.accessTokenHandler = accessTokenHandler;
21
+ this.refreshTokenHandler = refreshTokenHandler;
22
+ this.session = session;
23
+ this.logger = logger;
24
+ this.config.scope = this.config.scope ?? "openid profile email";
25
+ }
26
+ async authenticate(context) {
27
+ try {
28
+ let user;
29
+ let refreshToken;
30
+ let accessToken = await this.accessTokenHandler.retrieve?.(context);
31
+ if (!accessToken) {
32
+ this.logger?.info("No access token found, checking for refresh token.");
33
+ refreshToken = await this.refreshTokenHandler?.retrieve?.(context);
34
+ if (refreshToken) {
35
+ this.logger?.info("Found refresh token, attempting to refresh access token.");
36
+ const newTokens = await this.refreshAccessToken(context);
37
+ accessToken = newTokens.accessToken;
38
+ this.accessTokenHandler.embed?.(context, accessToken);
39
+ if (newTokens.refreshToken) {
40
+ refreshToken = newTokens.refreshToken;
41
+ this.refreshTokenHandler?.embed?.(context, newTokens.refreshToken);
42
+ }
43
+ }
44
+ else {
45
+ 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.accessTokenHandler.embed?.(context, accessToken);
71
+ if (refreshToken) {
72
+ this.refreshTokenHandler?.embed?.(context, refreshToken);
73
+ }
74
+ }
75
+ }
76
+ else if (accessToken && (await this.isTokenExpired(accessToken))) {
77
+ this.logger?.info("Access token expired, attempting refresh.");
78
+ refreshToken = await this.refreshTokenHandler?.retrieve?.(context);
79
+ if (!refreshToken) {
80
+ throw new errors_1.MissingTokenError("Refresh");
81
+ }
82
+ const newTokens = await this.refreshAccessToken(context);
83
+ accessToken = newTokens.accessToken;
84
+ this.accessTokenHandler.embed?.(context, accessToken);
85
+ if (newTokens.refreshToken && newTokens.refreshToken !== refreshToken) {
86
+ refreshToken = newTokens.refreshToken;
87
+ this.refreshTokenHandler?.embed?.(context, newTokens.refreshToken);
88
+ }
89
+ }
90
+ if (!accessToken) {
91
+ throw new errors_1.MissingTokenError("Access");
92
+ }
93
+ user = await this.retrieveUser(accessToken);
94
+ if (!user) {
95
+ throw new errors_1.UserNotFoundError();
96
+ }
97
+ await this.isAuthorized(user);
98
+ return { user, tokens: { accessToken, refreshToken } };
99
+ }
100
+ catch (error) {
101
+ this.logger?.error("OAuth2 authentication failed:", error);
102
+ throw new errors_1.AuthError(error, "OAuth2 authentication failed.");
103
+ }
104
+ }
105
+ verifyAuthorizationCode(context, code) {
106
+ if (!code) {
107
+ this.logger?.warn("Authorization code missing, redirecting user.");
108
+ const authUrl = this.buildAuthorizationUrl(context);
109
+ this.redirectUser(context, authUrl);
110
+ throw new errors_1.MissingAuthorizationCodeError();
111
+ }
112
+ }
113
+ extractAuthorizationCode(context) {
114
+ if (typeof context === "object" && "query" in context) {
115
+ return context.query.code || null;
116
+ }
117
+ return null;
118
+ }
119
+ redirectUser(context, authUrl) {
120
+ if (typeof context === "object" && "response" in context) {
121
+ context.response.redirect(authUrl);
122
+ }
123
+ else {
124
+ this.logger?.warn("Redirect attempted in unsupported context.");
125
+ }
126
+ }
127
+ buildAuthorizationUrl(context) {
128
+ let authorizationUrl = `${this.config.endpoints.authorizationUrl}?client_id=${this.config.clientId}&redirect_uri=${encodeURIComponent(this.config.redirectUri)}&response_type=code&scope=${this.config.scope ?? ""}`;
129
+ if (this.config.pkce?.enabled) {
130
+ const codeVerifier = this.config.pkce.generateCodeVerifier
131
+ ? this.config.pkce.generateCodeVerifier()
132
+ : oauth2_tools_1.OAuth2Tools.generateCodeVerifier();
133
+ const codeChallenge = oauth2_tools_1.OAuth2Tools.generateCodeChallenge(codeVerifier);
134
+ this.config.pkce.storeCodeVerifier?.(context, codeVerifier);
135
+ authorizationUrl += `&code_challenge=${codeChallenge}&code_challenge_method=S256`;
136
+ }
137
+ return authorizationUrl;
138
+ }
139
+ async exchangeCodeForToken(context, code) {
140
+ const data = {
141
+ grant_type: "authorization_code",
142
+ client_id: this.config.clientId,
143
+ code,
144
+ redirect_uri: this.config.redirectUri,
145
+ };
146
+ if (this.config.pkce?.enabled) {
147
+ const codeVerifier = this.config.pkce.retrieveCodeVerifier?.(context);
148
+ if (!codeVerifier) {
149
+ throw new Error("Missing PKCE code verifier in context.");
150
+ }
151
+ data.code_verifier = codeVerifier;
152
+ }
153
+ else if (this.config.clientSecret) {
154
+ data.client_secret = this.config.clientSecret;
155
+ }
156
+ const response = await fetch(this.config.endpoints.tokenUrl, {
157
+ method: "POST",
158
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
159
+ body: new URLSearchParams(data).toString(),
160
+ });
161
+ if (!response.ok) {
162
+ throw new Error(`Token exchange failed with status: ${response.status}`);
163
+ }
164
+ const tokenData = await response.json();
165
+ return {
166
+ accessToken: tokenData.access_token,
167
+ refreshToken: tokenData.refresh_token,
168
+ };
169
+ }
170
+ handleAuthorizationRedirect(context) {
171
+ try {
172
+ const authUrl = this.buildAuthorizationUrl(context);
173
+ this.redirectUser(context, authUrl);
174
+ }
175
+ catch (error) {
176
+ this.logger?.error("Authorization redirect failed:", error);
177
+ throw new errors_1.AuthError(error, "Authorization redirect failed.");
178
+ }
179
+ }
180
+ async retrieveUser(accessToken) {
181
+ try {
182
+ if (!this.config.endpoints.userInfoUrl) {
183
+ throw new Error("User info endpoint not configured.");
184
+ }
185
+ const response = await axios_1.default.get(this.config.endpoints.userInfoUrl, {
186
+ headers: { Authorization: `Bearer ${accessToken}` },
187
+ });
188
+ return (await this.config.validateUser?.(response.data)) || null;
189
+ }
190
+ catch (error) {
191
+ this.logger?.error("Failed to fetch user information:", error);
192
+ return null;
193
+ }
194
+ }
195
+ async exchangeClientCredentials() {
196
+ const response = await axios_1.default.post(this.config.endpoints.tokenUrl, {
197
+ grant_type: "client_credentials",
198
+ client_id: this.config.clientId,
199
+ client_secret: this.config.clientSecret,
200
+ });
201
+ return { accessToken: response.data.access_token };
202
+ }
203
+ async exchangePasswordGrant() {
204
+ if (!this.config.credentials) {
205
+ throw new Error("Missing credentials for password grant.");
206
+ }
207
+ const response = await axios_1.default.post(this.config.endpoints.tokenUrl, {
208
+ grant_type: "password",
209
+ client_id: this.config.clientId,
210
+ client_secret: this.config.clientSecret,
211
+ username: this.config.credentials.username,
212
+ password: this.config.credentials.password,
213
+ });
214
+ return { accessToken: response.data.access_token };
215
+ }
216
+ async refreshAccessToken(context) {
217
+ try {
218
+ const refreshToken = await this.refreshTokenHandler?.retrieve?.(context);
219
+ if (!refreshToken) {
220
+ throw new errors_1.MissingTokenError("Refresh");
221
+ }
222
+ const response = await axios_1.default.post(this.config.endpoints.tokenUrl, {
223
+ grant_type: "refresh_token",
224
+ client_id: this.config.clientId,
225
+ client_secret: this.config.clientSecret,
226
+ refresh_token: refreshToken,
227
+ });
228
+ const refreshedTokens = {
229
+ accessToken: response.data.access_token,
230
+ refreshToken: response.data.refresh_token,
231
+ };
232
+ await this.accessTokenHandler.embed?.(context, refreshedTokens.accessToken);
233
+ if (refreshedTokens.refreshToken) {
234
+ await this.refreshTokenHandler?.embed?.(context, refreshedTokens.refreshToken);
235
+ }
236
+ return refreshedTokens;
237
+ }
238
+ catch (error) {
239
+ this.logger?.error("Token refresh failed:", error);
240
+ throw new errors_1.AuthError(error, "Token refresh failed.");
241
+ }
242
+ }
243
+ async revokeToken(token) {
244
+ if (!this.config.endpoints.revocationUrl)
245
+ return;
246
+ try {
247
+ await axios_1.default.post(this.config.endpoints.revocationUrl, {
248
+ token,
249
+ client_id: this.config.clientId,
250
+ client_secret: this.config.clientSecret,
251
+ });
252
+ this.logger?.info("Token revoked successfully.");
253
+ }
254
+ catch (error) {
255
+ this.logger?.error("Failed to revoke token:", error);
256
+ }
257
+ }
258
+ }
259
+ exports.OAuth2Strategy = OAuth2Strategy;
@@ -0,0 +1,4 @@
1
+ export declare class OAuth2Tools {
2
+ static generateCodeVerifier(): string;
3
+ static generateCodeChallenge(codeVerifier: string): string;
4
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.OAuth2Tools = void 0;
7
+ const crypto_1 = __importDefault(require("crypto"));
8
+ class OAuth2Tools {
9
+ static generateCodeVerifier() {
10
+ return crypto_1.default.randomBytes(32).toString("hex");
11
+ }
12
+ static generateCodeChallenge(codeVerifier) {
13
+ return crypto_1.default
14
+ .createHash("sha256")
15
+ .update(codeVerifier)
16
+ .digest("base64")
17
+ .replace(/\+/g, "-")
18
+ .replace(/\//g, "_")
19
+ .replace(/=+$/, "");
20
+ }
21
+ }
22
+ exports.OAuth2Tools = OAuth2Tools;
@@ -0,0 +1,29 @@
1
+ import { TokenBasedAuthStrategyConfig } from "../../types";
2
+ export interface OAuth2Endpoints {
3
+ authorizationUrl: string;
4
+ tokenUrl: string;
5
+ userInfoUrl?: string;
6
+ introspectionUrl?: string;
7
+ revocationUrl?: string;
8
+ }
9
+ export interface OAuth2StrategyConfig<TContext = unknown, TUser = unknown> extends TokenBasedAuthStrategyConfig<TContext, TUser>, PKCEConfig<TContext> {
10
+ clientId: string;
11
+ clientSecret: string;
12
+ redirectUri: string;
13
+ scope?: string;
14
+ grantType: "authorization_code" | "client_credentials" | "password" | "refresh_token";
15
+ endpoints: OAuth2Endpoints;
16
+ validateUser?: (tokenPayload: any) => Promise<TUser | null>;
17
+ credentials?: {
18
+ username: string;
19
+ password: string;
20
+ };
21
+ }
22
+ export interface PKCEConfig<TContext> {
23
+ pkce?: {
24
+ enabled?: boolean;
25
+ generateCodeVerifier?: () => string;
26
+ storeCodeVerifier?: (context: TContext, codeVerifier: string) => void;
27
+ retrieveCodeVerifier?: (context: TContext) => string | null;
28
+ };
29
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,25 @@
1
+ import * as Soap from "@soapjs/soap";
2
+ import { AuthResult, TokenBasedAuthStrategyConfig } from "../types";
3
+ import { BaseAuthStrategy } from "./base-auth.strategy";
4
+ import { TokenHandlerConfig } 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 accessTokenHandler: TokenHandlerConfig;
9
+ protected refreshTokenHandler?: TokenHandlerConfig;
10
+ protected session?: SessionHandler;
11
+ protected logger?: Soap.Logger;
12
+ constructor(config: TokenBasedAuthStrategyConfig<TContext, TUser>, accessTokenHandler: TokenHandlerConfig, refreshTokenHandler?: TokenHandlerConfig, 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
+ }
@@ -0,0 +1,124 @@
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
+ accessTokenHandler;
9
+ refreshTokenHandler;
10
+ session;
11
+ logger;
12
+ constructor(config, accessTokenHandler, refreshTokenHandler, session, logger) {
13
+ super(config, session, logger);
14
+ this.config = config;
15
+ this.accessTokenHandler = accessTokenHandler;
16
+ this.refreshTokenHandler = refreshTokenHandler;
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.accessTokenHandler.retrieve?.(context);
26
+ await this.checkRateLimit(context);
27
+ if (accessToken) {
28
+ try {
29
+ const decoded = await this.accessTokenHandler.verify?.(accessToken);
30
+ const user = await this.retrieveUser(decoded);
31
+ if (!user) {
32
+ throw new errors_1.UserNotFoundError();
33
+ }
34
+ await this.isAuthorized(user);
35
+ return { user, tokens: { accessToken } };
36
+ }
37
+ catch (error) {
38
+ this.logger?.warn("Access token is invalid or expired, trying refresh token...");
39
+ }
40
+ }
41
+ const refreshToken = await this.refreshTokenHandler?.retrieve?.(context);
42
+ if (!refreshToken) {
43
+ throw new errors_1.MissingTokenError();
44
+ }
45
+ accessToken = await this.refreshTokenHandler?.rotate?.(refreshToken);
46
+ this.accessTokenHandler.embed?.(context, accessToken);
47
+ const decoded = await this.accessTokenHandler.verify?.(accessToken);
48
+ const user = await this.retrieveUser(decoded);
49
+ if (!user) {
50
+ throw new errors_1.UserNotFoundError();
51
+ }
52
+ await this.isAuthorized(user);
53
+ return { user, tokens: { accessToken, refreshToken } };
54
+ }
55
+ catch (error) {
56
+ this.logger?.error("Authentication failed:", error);
57
+ throw new errors_1.AuthError(error, "Authentication failed.");
58
+ }
59
+ }
60
+ async logout(context) {
61
+ try {
62
+ await this.accessTokenHandler.remove?.(context);
63
+ if (this.refreshTokenHandler) {
64
+ await this.refreshTokenHandler.remove?.(context);
65
+ }
66
+ await this.config.logout.onSuccess?.(context);
67
+ this.logger?.info("User logged out successfully.");
68
+ }
69
+ catch (error) {
70
+ this.logger?.error("Error during logout:", error);
71
+ await this.config.logout.onFailure?.({ context, error });
72
+ throw new errors_1.AuthError(error, "Logout process failed.");
73
+ }
74
+ }
75
+ async generateTokens(user, context) {
76
+ const payload = { userId: user.id, roles: user.roles };
77
+ const accessToken = this.accessTokenHandler.generate?.(payload);
78
+ if (!accessToken)
79
+ throw new Error("Failed to generate access token.");
80
+ await this.accessTokenHandler.store?.(accessToken, user, +this.accessTokenHandler.expiresIn);
81
+ this.accessTokenHandler.embed?.(context, accessToken);
82
+ let refreshToken;
83
+ if (this.refreshTokenHandler) {
84
+ refreshToken = this.refreshTokenHandler.generate?.(payload);
85
+ if (refreshToken) {
86
+ await this.refreshTokenHandler.store?.(refreshToken, user, +this.refreshTokenHandler.expiresIn);
87
+ this.refreshTokenHandler.embed?.(context, refreshToken);
88
+ }
89
+ }
90
+ return { accessToken, refreshToken };
91
+ }
92
+ async rotateToken(context) {
93
+ try {
94
+ if (!this.refreshTokenHandler) {
95
+ throw new Error("Refresh token handler is not configured.");
96
+ }
97
+ const refreshToken = await this.refreshTokenHandler.retrieve?.(context);
98
+ if (!refreshToken) {
99
+ throw new errors_1.MissingTokenError("Refresh");
100
+ }
101
+ const newAccessToken = await this.refreshTokenHandler.rotate?.(refreshToken);
102
+ this.accessTokenHandler.embed?.(context, newAccessToken);
103
+ return { accessToken: newAccessToken, refreshToken };
104
+ }
105
+ catch (error) {
106
+ this.logger?.error("Token rotation failed:", error);
107
+ throw new errors_1.InvalidTokenError("Refresh");
108
+ }
109
+ }
110
+ async isTokenExpired(token) {
111
+ try {
112
+ const decoded = JSON.parse(Buffer.from(token.split(".")[1], "base64").toString());
113
+ if (!decoded.exp)
114
+ return false;
115
+ const currentTime = Math.floor(Date.now() / 1000);
116
+ return decoded.exp < currentTime;
117
+ }
118
+ catch (error) {
119
+ this.logger?.warn("Failed to decode token:", error);
120
+ return false;
121
+ }
122
+ }
123
+ }
124
+ exports.TokenBasedAuthStrategy = TokenBasedAuthStrategy;
@@ -0,0 +1,6 @@
1
+ import { SessionData } from "../types";
2
+ export declare class SessionTools {
3
+ static defaultGenerateSessionId(): string;
4
+ static defaultCreateSessionData(user?: unknown, context?: unknown): SessionData;
5
+ static defaultDeliverSessionId(context: any, value: string): void;
6
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SessionTools = void 0;
4
+ const uuid_1 = require("uuid");
5
+ class SessionTools {
6
+ static defaultGenerateSessionId() {
7
+ return (0, uuid_1.v4)();
8
+ }
9
+ static defaultCreateSessionData(user, context) {
10
+ return {};
11
+ }
12
+ static defaultDeliverSessionId(context, value) {
13
+ }
14
+ }
15
+ exports.SessionTools = SessionTools;
@@ -0,0 +1,7 @@
1
+ import { BodyStorageOptions, CookieStorageOptions, HeaderStorageOptions, SessionStorageOptions } from "../types";
2
+ export declare class TokenTools {
3
+ static storeInHeader<TContext = unknown>(context: TContext, token: string, options?: HeaderStorageOptions): void;
4
+ static storeInCookie<TContext = unknown>(context: TContext, token: string, options?: CookieStorageOptions, isAccessToken?: boolean): void;
5
+ static storeInBody<TContext = unknown>(context: TContext, token: string, options?: BodyStorageOptions, isAccessToken?: boolean): void;
6
+ static storeInSession<TContext = unknown>(context: TContext, token: string, options?: SessionStorageOptions, isAccessToken?: boolean): void;
7
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenTools = void 0;
4
+ class TokenTools {
5
+ static storeInHeader(context, token, options) {
6
+ const headerName = options?.headerName ?? "Authorization";
7
+ context.setHeader(headerName, token);
8
+ }
9
+ static storeInCookie(context, token, options, isAccessToken = true) {
10
+ const cookieName = options?.cookieName ?? (isAccessToken ? "AccessToken" : "RefreshToken");
11
+ const ctx = context;
12
+ ctx.res.cookie(cookieName, token, {
13
+ httpOnly: options?.httpOnly ?? true,
14
+ secure: options?.secure ?? true,
15
+ sameSite: options?.sameSite ?? "Lax",
16
+ maxAge: options?.maxAge ?? 3600000,
17
+ });
18
+ }
19
+ static storeInBody(context, token, options, isAccessToken = true) {
20
+ const ctx = context;
21
+ ctx.body = ctx.body || {};
22
+ const fieldName = options?.name ?? (isAccessToken ? "accessToken" : "refreshToken");
23
+ ctx.body[fieldName] = token;
24
+ }
25
+ static storeInSession(context, token, options, isAccessToken = true) {
26
+ const ctx = context;
27
+ ctx.session = ctx.session || {};
28
+ const sessionKey = options?.name ?? (isAccessToken ? "accessToken" : "refreshToken");
29
+ ctx.session[sessionKey] = token;
30
+ }
31
+ }
32
+ exports.TokenTools = TokenTools;
@@ -0,0 +1,3 @@
1
+ export declare const generateUUID: () => Promise<string>;
2
+ export declare const generateSecureToken: (tokenLength?: number, encoding?: string) => Promise<string>;
3
+ export declare function resolveConfig<T>(strategyConfig: T | undefined, globalConfig: T | undefined): T | undefined;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveConfig = exports.generateSecureToken = exports.generateUUID = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const uuid_1 = require("uuid");
6
+ const generateUUID = async () => {
7
+ return Promise.resolve((0, uuid_1.v4)());
8
+ };
9
+ 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
+ function resolveConfig(strategyConfig, globalConfig) {
21
+ return strategyConfig || globalConfig;
22
+ }
23
+ exports.resolveConfig = resolveConfig;