@memberjunction/actions 2.113.1 → 2.114.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.
- package/dist/generic/OAuth2Manager.d.ts +209 -0
- package/dist/generic/OAuth2Manager.d.ts.map +1 -0
- package/dist/generic/OAuth2Manager.js +328 -0
- package/dist/generic/OAuth2Manager.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
- package/readme.md +39 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration options for OAuth2Manager
|
|
3
|
+
*/
|
|
4
|
+
export interface OAuth2Config {
|
|
5
|
+
/**
|
|
6
|
+
* OAuth2 client ID
|
|
7
|
+
*/
|
|
8
|
+
clientId: string;
|
|
9
|
+
/**
|
|
10
|
+
* OAuth2 client secret
|
|
11
|
+
*/
|
|
12
|
+
clientSecret: string;
|
|
13
|
+
/**
|
|
14
|
+
* Token endpoint URL (e.g., 'https://api.example.com/oauth/token')
|
|
15
|
+
*/
|
|
16
|
+
tokenEndpoint: string;
|
|
17
|
+
/**
|
|
18
|
+
* Authorization endpoint URL (e.g., 'https://api.example.com/oauth/authorize')
|
|
19
|
+
* Only needed for authorization_code flow
|
|
20
|
+
*/
|
|
21
|
+
authorizationEndpoint?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Redirect URI for authorization_code flow
|
|
24
|
+
*/
|
|
25
|
+
redirectUri?: string;
|
|
26
|
+
/**
|
|
27
|
+
* OAuth2 scopes to request
|
|
28
|
+
*/
|
|
29
|
+
scopes?: string[];
|
|
30
|
+
/**
|
|
31
|
+
* Initial access token (if already obtained)
|
|
32
|
+
*/
|
|
33
|
+
accessToken?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Initial refresh token (if available)
|
|
36
|
+
*/
|
|
37
|
+
refreshToken?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Initial token expiration timestamp (milliseconds since epoch)
|
|
40
|
+
*/
|
|
41
|
+
tokenExpiresAt?: number;
|
|
42
|
+
/**
|
|
43
|
+
* Buffer time in milliseconds before token expiration to trigger refresh (default: 60000 = 1 minute)
|
|
44
|
+
*/
|
|
45
|
+
refreshBufferMs?: number;
|
|
46
|
+
/**
|
|
47
|
+
* Custom transformation for token response (for non-standard OAuth2 implementations)
|
|
48
|
+
*/
|
|
49
|
+
tokenResponseTransform?: (response: any) => OAuth2TokenResponse;
|
|
50
|
+
/**
|
|
51
|
+
* Custom transformation for token request body (for provider-specific requirements)
|
|
52
|
+
*/
|
|
53
|
+
tokenRequestTransform?: (params: Record<string, string>) => Record<string, string>;
|
|
54
|
+
/**
|
|
55
|
+
* Additional headers to include in token requests
|
|
56
|
+
*/
|
|
57
|
+
additionalHeaders?: Record<string, string>;
|
|
58
|
+
/**
|
|
59
|
+
* Callback invoked when tokens are updated (for persistence)
|
|
60
|
+
*/
|
|
61
|
+
onTokenUpdate?: (tokens: OAuth2TokenData) => void | Promise<void>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Standard OAuth2 token response
|
|
65
|
+
*/
|
|
66
|
+
export interface OAuth2TokenResponse {
|
|
67
|
+
access_token: string;
|
|
68
|
+
refresh_token?: string;
|
|
69
|
+
expires_in?: number;
|
|
70
|
+
token_type?: string;
|
|
71
|
+
scope?: string;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* OAuth2 token data with computed expiration
|
|
75
|
+
*/
|
|
76
|
+
export interface OAuth2TokenData {
|
|
77
|
+
accessToken: string;
|
|
78
|
+
refreshToken?: string;
|
|
79
|
+
expiresAt: number;
|
|
80
|
+
tokenType?: string;
|
|
81
|
+
scope?: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Generic OAuth2 token manager supporting multiple grant types and automatic token refresh.
|
|
85
|
+
*
|
|
86
|
+
* This class provides a standardized way to handle OAuth2 authentication flows including:
|
|
87
|
+
* - Authorization code flow (with PKCE support)
|
|
88
|
+
* - Client credentials flow
|
|
89
|
+
* - Refresh token flow
|
|
90
|
+
* - Direct access token usage
|
|
91
|
+
*
|
|
92
|
+
* Features:
|
|
93
|
+
* - Automatic token refresh before expiration
|
|
94
|
+
* - Thread-safe token refresh (prevents concurrent refresh requests)
|
|
95
|
+
* - Provider customization hooks for non-standard OAuth2 implementations
|
|
96
|
+
* - Token persistence callbacks
|
|
97
|
+
* - Support for multiple grant types
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```typescript
|
|
101
|
+
* // Initialize with client credentials
|
|
102
|
+
* const oauth = new OAuth2Manager({
|
|
103
|
+
* clientId: 'your-client-id',
|
|
104
|
+
* clientSecret: 'your-client-secret',
|
|
105
|
+
* tokenEndpoint: 'https://api.example.com/oauth/token',
|
|
106
|
+
* authorizationEndpoint: 'https://api.example.com/oauth/authorize',
|
|
107
|
+
* scopes: ['read', 'write']
|
|
108
|
+
* });
|
|
109
|
+
*
|
|
110
|
+
* // Get a valid access token (auto-refreshes if needed)
|
|
111
|
+
* const token = await oauth.getAccessToken();
|
|
112
|
+
*
|
|
113
|
+
* // Use the token in API requests
|
|
114
|
+
* const response = await fetch('https://api.example.com/data', {
|
|
115
|
+
* headers: { 'Authorization': `Bearer ${token}` }
|
|
116
|
+
* });
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare class OAuth2Manager {
|
|
120
|
+
private config;
|
|
121
|
+
private accessToken;
|
|
122
|
+
private refreshToken;
|
|
123
|
+
private tokenExpiresAt;
|
|
124
|
+
private refreshPromise;
|
|
125
|
+
/**
|
|
126
|
+
* Creates a new OAuth2Manager instance
|
|
127
|
+
*
|
|
128
|
+
* @param config - OAuth2 configuration options
|
|
129
|
+
*/
|
|
130
|
+
constructor(config: OAuth2Config);
|
|
131
|
+
/**
|
|
132
|
+
* Gets the authorization URL for the authorization code flow
|
|
133
|
+
*
|
|
134
|
+
* @param state - Optional state parameter for CSRF protection
|
|
135
|
+
* @param additionalParams - Additional query parameters to include
|
|
136
|
+
* @returns The authorization URL
|
|
137
|
+
*/
|
|
138
|
+
getAuthorizationUrl(state?: string, additionalParams?: Record<string, string>): string;
|
|
139
|
+
/**
|
|
140
|
+
* Exchanges an authorization code for an access token
|
|
141
|
+
*
|
|
142
|
+
* @param code - The authorization code received from the authorization endpoint
|
|
143
|
+
* @returns The token data
|
|
144
|
+
*/
|
|
145
|
+
exchangeAuthorizationCode(code: string): Promise<OAuth2TokenData>;
|
|
146
|
+
/**
|
|
147
|
+
* Obtains an access token using client credentials flow
|
|
148
|
+
*
|
|
149
|
+
* @returns The token data
|
|
150
|
+
*/
|
|
151
|
+
getClientCredentialsToken(): Promise<OAuth2TokenData>;
|
|
152
|
+
/**
|
|
153
|
+
* Refreshes the access token using the refresh token
|
|
154
|
+
*
|
|
155
|
+
* @returns The new token data
|
|
156
|
+
* @throws Error if no refresh token is available
|
|
157
|
+
*/
|
|
158
|
+
refreshAccessToken(): Promise<OAuth2TokenData>;
|
|
159
|
+
/**
|
|
160
|
+
* Gets a valid access token, automatically refreshing if needed
|
|
161
|
+
*
|
|
162
|
+
* This is the main method to use when you need an access token for API requests.
|
|
163
|
+
* It handles token refresh automatically if the current token is expired or about to expire.
|
|
164
|
+
*
|
|
165
|
+
* @returns A valid access token
|
|
166
|
+
* @throws Error if no token is available and cannot be obtained
|
|
167
|
+
*/
|
|
168
|
+
getAccessToken(): Promise<string>;
|
|
169
|
+
/**
|
|
170
|
+
* Performs the actual token refresh operation
|
|
171
|
+
*
|
|
172
|
+
* @private
|
|
173
|
+
* @returns The new access token
|
|
174
|
+
*/
|
|
175
|
+
private performTokenRefresh;
|
|
176
|
+
/**
|
|
177
|
+
* Makes a token request to the OAuth2 server
|
|
178
|
+
*
|
|
179
|
+
* @private
|
|
180
|
+
* @param params - Token request parameters
|
|
181
|
+
* @returns The token data
|
|
182
|
+
*/
|
|
183
|
+
private requestToken;
|
|
184
|
+
/**
|
|
185
|
+
* Checks if the current access token is valid (exists and not expired)
|
|
186
|
+
*
|
|
187
|
+
* @returns True if the token is valid, false otherwise
|
|
188
|
+
*/
|
|
189
|
+
isTokenValid(): boolean;
|
|
190
|
+
/**
|
|
191
|
+
* Sets the access token directly (for cases where token is obtained externally)
|
|
192
|
+
*
|
|
193
|
+
* @param accessToken - The access token
|
|
194
|
+
* @param refreshToken - Optional refresh token
|
|
195
|
+
* @param expiresIn - Optional expiration time in seconds
|
|
196
|
+
*/
|
|
197
|
+
setTokens(accessToken: string, refreshToken?: string, expiresIn?: number): void;
|
|
198
|
+
/**
|
|
199
|
+
* Clears all stored tokens
|
|
200
|
+
*/
|
|
201
|
+
clearTokens(): void;
|
|
202
|
+
/**
|
|
203
|
+
* Gets the current token state (for debugging or persistence)
|
|
204
|
+
*
|
|
205
|
+
* @returns The current token data or null if no tokens are available
|
|
206
|
+
*/
|
|
207
|
+
getTokenState(): OAuth2TokenData | null;
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=OAuth2Manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuth2Manager.d.ts","sourceRoot":"","sources":["../../src/generic/OAuth2Manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OAuth2Manager = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Generic OAuth2 token manager supporting multiple grant types and automatic token refresh.
|
|
6
|
+
*
|
|
7
|
+
* This class provides a standardized way to handle OAuth2 authentication flows including:
|
|
8
|
+
* - Authorization code flow (with PKCE support)
|
|
9
|
+
* - Client credentials flow
|
|
10
|
+
* - Refresh token flow
|
|
11
|
+
* - Direct access token usage
|
|
12
|
+
*
|
|
13
|
+
* Features:
|
|
14
|
+
* - Automatic token refresh before expiration
|
|
15
|
+
* - Thread-safe token refresh (prevents concurrent refresh requests)
|
|
16
|
+
* - Provider customization hooks for non-standard OAuth2 implementations
|
|
17
|
+
* - Token persistence callbacks
|
|
18
|
+
* - Support for multiple grant types
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* // Initialize with client credentials
|
|
23
|
+
* const oauth = new OAuth2Manager({
|
|
24
|
+
* clientId: 'your-client-id',
|
|
25
|
+
* clientSecret: 'your-client-secret',
|
|
26
|
+
* tokenEndpoint: 'https://api.example.com/oauth/token',
|
|
27
|
+
* authorizationEndpoint: 'https://api.example.com/oauth/authorize',
|
|
28
|
+
* scopes: ['read', 'write']
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Get a valid access token (auto-refreshes if needed)
|
|
32
|
+
* const token = await oauth.getAccessToken();
|
|
33
|
+
*
|
|
34
|
+
* // Use the token in API requests
|
|
35
|
+
* const response = await fetch('https://api.example.com/data', {
|
|
36
|
+
* headers: { 'Authorization': `Bearer ${token}` }
|
|
37
|
+
* });
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
class OAuth2Manager {
|
|
41
|
+
/**
|
|
42
|
+
* Creates a new OAuth2Manager instance
|
|
43
|
+
*
|
|
44
|
+
* @param config - OAuth2 configuration options
|
|
45
|
+
*/
|
|
46
|
+
constructor(config) {
|
|
47
|
+
this.accessToken = null;
|
|
48
|
+
this.refreshToken = null;
|
|
49
|
+
this.tokenExpiresAt = 0;
|
|
50
|
+
this.refreshPromise = null;
|
|
51
|
+
this.config = {
|
|
52
|
+
clientId: config.clientId,
|
|
53
|
+
clientSecret: config.clientSecret,
|
|
54
|
+
tokenEndpoint: config.tokenEndpoint,
|
|
55
|
+
authorizationEndpoint: config.authorizationEndpoint,
|
|
56
|
+
redirectUri: config.redirectUri,
|
|
57
|
+
scopes: config.scopes,
|
|
58
|
+
refreshBufferMs: config.refreshBufferMs ?? 60000, // Default 1 minute buffer
|
|
59
|
+
tokenResponseTransform: config.tokenResponseTransform,
|
|
60
|
+
tokenRequestTransform: config.tokenRequestTransform,
|
|
61
|
+
additionalHeaders: config.additionalHeaders,
|
|
62
|
+
onTokenUpdate: config.onTokenUpdate
|
|
63
|
+
};
|
|
64
|
+
// Initialize with provided tokens if available
|
|
65
|
+
if (config.accessToken) {
|
|
66
|
+
this.accessToken = config.accessToken;
|
|
67
|
+
}
|
|
68
|
+
if (config.refreshToken) {
|
|
69
|
+
this.refreshToken = config.refreshToken;
|
|
70
|
+
}
|
|
71
|
+
if (config.tokenExpiresAt) {
|
|
72
|
+
this.tokenExpiresAt = config.tokenExpiresAt;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Gets the authorization URL for the authorization code flow
|
|
77
|
+
*
|
|
78
|
+
* @param state - Optional state parameter for CSRF protection
|
|
79
|
+
* @param additionalParams - Additional query parameters to include
|
|
80
|
+
* @returns The authorization URL
|
|
81
|
+
*/
|
|
82
|
+
getAuthorizationUrl(state, additionalParams) {
|
|
83
|
+
if (!this.config.authorizationEndpoint) {
|
|
84
|
+
throw new Error('Authorization endpoint not configured');
|
|
85
|
+
}
|
|
86
|
+
const params = new URLSearchParams({
|
|
87
|
+
client_id: this.config.clientId,
|
|
88
|
+
response_type: 'code',
|
|
89
|
+
...additionalParams
|
|
90
|
+
});
|
|
91
|
+
if (this.config.redirectUri) {
|
|
92
|
+
params.append('redirect_uri', this.config.redirectUri);
|
|
93
|
+
}
|
|
94
|
+
if (this.config.scopes && this.config.scopes.length > 0) {
|
|
95
|
+
params.append('scope', this.config.scopes.join(' '));
|
|
96
|
+
}
|
|
97
|
+
if (state) {
|
|
98
|
+
params.append('state', state);
|
|
99
|
+
}
|
|
100
|
+
return `${this.config.authorizationEndpoint}?${params.toString()}`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Exchanges an authorization code for an access token
|
|
104
|
+
*
|
|
105
|
+
* @param code - The authorization code received from the authorization endpoint
|
|
106
|
+
* @returns The token data
|
|
107
|
+
*/
|
|
108
|
+
async exchangeAuthorizationCode(code) {
|
|
109
|
+
const params = {
|
|
110
|
+
grant_type: 'authorization_code',
|
|
111
|
+
code,
|
|
112
|
+
client_id: this.config.clientId,
|
|
113
|
+
client_secret: this.config.clientSecret
|
|
114
|
+
};
|
|
115
|
+
if (this.config.redirectUri) {
|
|
116
|
+
params.redirect_uri = this.config.redirectUri;
|
|
117
|
+
}
|
|
118
|
+
return this.requestToken(params);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Obtains an access token using client credentials flow
|
|
122
|
+
*
|
|
123
|
+
* @returns The token data
|
|
124
|
+
*/
|
|
125
|
+
async getClientCredentialsToken() {
|
|
126
|
+
const params = {
|
|
127
|
+
grant_type: 'client_credentials',
|
|
128
|
+
client_id: this.config.clientId,
|
|
129
|
+
client_secret: this.config.clientSecret
|
|
130
|
+
};
|
|
131
|
+
if (this.config.scopes && this.config.scopes.length > 0) {
|
|
132
|
+
params.scope = this.config.scopes.join(' ');
|
|
133
|
+
}
|
|
134
|
+
return this.requestToken(params);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Refreshes the access token using the refresh token
|
|
138
|
+
*
|
|
139
|
+
* @returns The new token data
|
|
140
|
+
* @throws Error if no refresh token is available
|
|
141
|
+
*/
|
|
142
|
+
async refreshAccessToken() {
|
|
143
|
+
if (!this.refreshToken) {
|
|
144
|
+
throw new Error('No refresh token available');
|
|
145
|
+
}
|
|
146
|
+
const params = {
|
|
147
|
+
grant_type: 'refresh_token',
|
|
148
|
+
refresh_token: this.refreshToken,
|
|
149
|
+
client_id: this.config.clientId,
|
|
150
|
+
client_secret: this.config.clientSecret
|
|
151
|
+
};
|
|
152
|
+
return this.requestToken(params);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Gets a valid access token, automatically refreshing if needed
|
|
156
|
+
*
|
|
157
|
+
* This is the main method to use when you need an access token for API requests.
|
|
158
|
+
* It handles token refresh automatically if the current token is expired or about to expire.
|
|
159
|
+
*
|
|
160
|
+
* @returns A valid access token
|
|
161
|
+
* @throws Error if no token is available and cannot be obtained
|
|
162
|
+
*/
|
|
163
|
+
async getAccessToken() {
|
|
164
|
+
// If we have a valid token, return it
|
|
165
|
+
if (this.accessToken && this.isTokenValid()) {
|
|
166
|
+
return this.accessToken;
|
|
167
|
+
}
|
|
168
|
+
// If a refresh is already in progress, wait for it
|
|
169
|
+
if (this.refreshPromise) {
|
|
170
|
+
return this.refreshPromise;
|
|
171
|
+
}
|
|
172
|
+
// Start a new refresh operation
|
|
173
|
+
this.refreshPromise = this.performTokenRefresh();
|
|
174
|
+
try {
|
|
175
|
+
const token = await this.refreshPromise;
|
|
176
|
+
return token;
|
|
177
|
+
}
|
|
178
|
+
finally {
|
|
179
|
+
this.refreshPromise = null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Performs the actual token refresh operation
|
|
184
|
+
*
|
|
185
|
+
* @private
|
|
186
|
+
* @returns The new access token
|
|
187
|
+
*/
|
|
188
|
+
async performTokenRefresh() {
|
|
189
|
+
try {
|
|
190
|
+
let tokenData;
|
|
191
|
+
if (this.refreshToken) {
|
|
192
|
+
// Use refresh token if available
|
|
193
|
+
tokenData = await this.refreshAccessToken();
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
// Fall back to client credentials if no refresh token
|
|
197
|
+
tokenData = await this.getClientCredentialsToken();
|
|
198
|
+
}
|
|
199
|
+
return tokenData.accessToken;
|
|
200
|
+
}
|
|
201
|
+
catch (error) {
|
|
202
|
+
throw new Error(`Failed to refresh access token: ${error instanceof Error ? error.message : String(error)}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Makes a token request to the OAuth2 server
|
|
207
|
+
*
|
|
208
|
+
* @private
|
|
209
|
+
* @param params - Token request parameters
|
|
210
|
+
* @returns The token data
|
|
211
|
+
*/
|
|
212
|
+
async requestToken(params) {
|
|
213
|
+
try {
|
|
214
|
+
// Allow provider-specific transformations
|
|
215
|
+
const requestParams = this.config.tokenRequestTransform
|
|
216
|
+
? this.config.tokenRequestTransform(params)
|
|
217
|
+
: params;
|
|
218
|
+
const headers = {
|
|
219
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
220
|
+
...this.config.additionalHeaders
|
|
221
|
+
};
|
|
222
|
+
const response = await fetch(this.config.tokenEndpoint, {
|
|
223
|
+
method: 'POST',
|
|
224
|
+
headers,
|
|
225
|
+
body: new URLSearchParams(requestParams)
|
|
226
|
+
});
|
|
227
|
+
if (!response.ok) {
|
|
228
|
+
const errorText = await response.text();
|
|
229
|
+
throw new Error(`Token request failed: ${response.status} ${response.statusText} - ${errorText}`);
|
|
230
|
+
}
|
|
231
|
+
const responseData = await response.json();
|
|
232
|
+
// Allow provider-specific response transformations
|
|
233
|
+
const tokenResponse = this.config.tokenResponseTransform
|
|
234
|
+
? this.config.tokenResponseTransform(responseData)
|
|
235
|
+
: responseData;
|
|
236
|
+
// Update internal state
|
|
237
|
+
this.accessToken = tokenResponse.access_token;
|
|
238
|
+
if (tokenResponse.refresh_token) {
|
|
239
|
+
this.refreshToken = tokenResponse.refresh_token;
|
|
240
|
+
}
|
|
241
|
+
if (tokenResponse.expires_in) {
|
|
242
|
+
this.tokenExpiresAt = Date.now() + (tokenResponse.expires_in * 1000);
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
// If no expires_in, assume token is long-lived (1 year)
|
|
246
|
+
this.tokenExpiresAt = Date.now() + (365 * 24 * 60 * 60 * 1000);
|
|
247
|
+
}
|
|
248
|
+
const tokenData = {
|
|
249
|
+
accessToken: this.accessToken,
|
|
250
|
+
refreshToken: this.refreshToken || undefined,
|
|
251
|
+
expiresAt: this.tokenExpiresAt,
|
|
252
|
+
tokenType: tokenResponse.token_type,
|
|
253
|
+
scope: tokenResponse.scope
|
|
254
|
+
};
|
|
255
|
+
// Invoke token update callback if provided
|
|
256
|
+
if (this.config.onTokenUpdate) {
|
|
257
|
+
await this.config.onTokenUpdate(tokenData);
|
|
258
|
+
}
|
|
259
|
+
return tokenData;
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
throw new Error(`OAuth2 token request failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Checks if the current access token is valid (exists and not expired)
|
|
267
|
+
*
|
|
268
|
+
* @returns True if the token is valid, false otherwise
|
|
269
|
+
*/
|
|
270
|
+
isTokenValid() {
|
|
271
|
+
if (!this.accessToken) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
// Check if token is expired or about to expire (within buffer time)
|
|
275
|
+
const now = Date.now();
|
|
276
|
+
const expiresWithBuffer = this.tokenExpiresAt - this.config.refreshBufferMs;
|
|
277
|
+
return now < expiresWithBuffer;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Sets the access token directly (for cases where token is obtained externally)
|
|
281
|
+
*
|
|
282
|
+
* @param accessToken - The access token
|
|
283
|
+
* @param refreshToken - Optional refresh token
|
|
284
|
+
* @param expiresIn - Optional expiration time in seconds
|
|
285
|
+
*/
|
|
286
|
+
setTokens(accessToken, refreshToken, expiresIn) {
|
|
287
|
+
this.accessToken = accessToken;
|
|
288
|
+
if (refreshToken) {
|
|
289
|
+
this.refreshToken = refreshToken;
|
|
290
|
+
}
|
|
291
|
+
if (expiresIn) {
|
|
292
|
+
this.tokenExpiresAt = Date.now() + (expiresIn * 1000);
|
|
293
|
+
}
|
|
294
|
+
// Invoke token update callback if provided
|
|
295
|
+
if (this.config.onTokenUpdate) {
|
|
296
|
+
this.config.onTokenUpdate({
|
|
297
|
+
accessToken: this.accessToken,
|
|
298
|
+
refreshToken: this.refreshToken || undefined,
|
|
299
|
+
expiresAt: this.tokenExpiresAt
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Clears all stored tokens
|
|
305
|
+
*/
|
|
306
|
+
clearTokens() {
|
|
307
|
+
this.accessToken = null;
|
|
308
|
+
this.refreshToken = null;
|
|
309
|
+
this.tokenExpiresAt = 0;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Gets the current token state (for debugging or persistence)
|
|
313
|
+
*
|
|
314
|
+
* @returns The current token data or null if no tokens are available
|
|
315
|
+
*/
|
|
316
|
+
getTokenState() {
|
|
317
|
+
if (!this.accessToken) {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
return {
|
|
321
|
+
accessToken: this.accessToken,
|
|
322
|
+
refreshToken: this.refreshToken || undefined,
|
|
323
|
+
expiresAt: this.tokenExpiresAt
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
exports.OAuth2Manager = OAuth2Manager;
|
|
328
|
+
//# sourceMappingURL=OAuth2Manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OAuth2Manager.js","sourceRoot":"","sources":["../../src/generic/OAuth2Manager.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './generic/BaseAction';
|
|
|
2
2
|
export * from './generic/BaseActionFilter';
|
|
3
3
|
export * from './generic/BaseOAuthAction';
|
|
4
4
|
export * from './generic/ActionEngine';
|
|
5
|
+
export * from './generic/OAuth2Manager';
|
|
5
6
|
export * from './entity-actions/EntityActionEngine';
|
|
6
7
|
export * from './entity-actions/EntityActionInvocationTypes';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AAExC,cAAc,qCAAqC,CAAC;AACpD,cAAc,8CAA8C,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ __exportStar(require("./generic/BaseAction"), exports);
|
|
|
18
18
|
__exportStar(require("./generic/BaseActionFilter"), exports);
|
|
19
19
|
__exportStar(require("./generic/BaseOAuthAction"), exports);
|
|
20
20
|
__exportStar(require("./generic/ActionEngine"), exports);
|
|
21
|
+
__exportStar(require("./generic/OAuth2Manager"), exports);
|
|
21
22
|
__exportStar(require("./entity-actions/EntityActionEngine"), exports);
|
|
22
23
|
__exportStar(require("./entity-actions/EntityActionInvocationTypes"), exports);
|
|
23
24
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAqC;AACrC,6DAA2C;AAC3C,4DAA0C;AAC1C,yDAAuC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAqC;AACrC,6DAA2C;AAC3C,4DAA0C;AAC1C,yDAAuC;AACvC,0DAAwC;AAExC,sEAAoD;AACpD,+EAA6D"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/actions",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.114.0",
|
|
4
4
|
"description": "Main library for MemberJunction Actions. This library is only intended to be imported on the server side.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
"typescript": "^5.4.5"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@memberjunction/global": "2.
|
|
23
|
-
"@memberjunction/core": "2.
|
|
24
|
-
"@memberjunction/actions-base": "2.
|
|
25
|
-
"@memberjunction/core-entities": "2.
|
|
26
|
-
"@memberjunction/ai": "2.
|
|
27
|
-
"@memberjunction/ai-core-plus": "2.
|
|
28
|
-
"@memberjunction/aiengine": "2.
|
|
29
|
-
"@memberjunction/ai-prompts": "2.
|
|
30
|
-
"@memberjunction/doc-utils": "2.
|
|
22
|
+
"@memberjunction/global": "2.114.0",
|
|
23
|
+
"@memberjunction/core": "2.114.0",
|
|
24
|
+
"@memberjunction/actions-base": "2.114.0",
|
|
25
|
+
"@memberjunction/core-entities": "2.114.0",
|
|
26
|
+
"@memberjunction/ai": "2.114.0",
|
|
27
|
+
"@memberjunction/ai-core-plus": "2.114.0",
|
|
28
|
+
"@memberjunction/aiengine": "2.114.0",
|
|
29
|
+
"@memberjunction/ai-prompts": "2.114.0",
|
|
30
|
+
"@memberjunction/doc-utils": "2.114.0"
|
|
31
31
|
},
|
|
32
32
|
"repository": {
|
|
33
33
|
"type": "git",
|
package/readme.md
CHANGED
|
@@ -437,6 +437,45 @@ This package integrates seamlessly with:
|
|
|
437
437
|
- **@memberjunction/core-entities**: Provides strongly-typed entity classes
|
|
438
438
|
- **@memberjunction/global**: Manages class registration and instantiation
|
|
439
439
|
|
|
440
|
+
## OAuth2Manager (Server-Side Only)
|
|
441
|
+
|
|
442
|
+
The package includes a generic OAuth2 token manager for server-side integrations:
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
import { OAuth2Manager } from '@memberjunction/actions';
|
|
446
|
+
|
|
447
|
+
// Initialize OAuth2 manager
|
|
448
|
+
const oauth = new OAuth2Manager({
|
|
449
|
+
clientId: process.env.OAUTH_CLIENT_ID,
|
|
450
|
+
clientSecret: process.env.OAUTH_CLIENT_SECRET,
|
|
451
|
+
tokenEndpoint: 'https://api.example.com/oauth/token',
|
|
452
|
+
authorizationEndpoint: 'https://api.example.com/oauth/authorize',
|
|
453
|
+
scopes: ['read', 'write'],
|
|
454
|
+
onTokenUpdate: async (tokens) => {
|
|
455
|
+
// Persist updated tokens to database
|
|
456
|
+
await saveTokens(tokens);
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
// Get authorization URL for user to visit
|
|
461
|
+
const authUrl = oauth.getAuthorizationUrl('random-state-string');
|
|
462
|
+
|
|
463
|
+
// Exchange authorization code for tokens
|
|
464
|
+
const tokens = await oauth.exchangeAuthorizationCode(code);
|
|
465
|
+
|
|
466
|
+
// Get valid access token (auto-refreshes if needed)
|
|
467
|
+
const accessToken = await oauth.getAccessToken();
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
**Features:**
|
|
471
|
+
- Multiple grant type support (authorization_code, client_credentials, refresh_token)
|
|
472
|
+
- Automatic token refresh before expiration
|
|
473
|
+
- Thread-safe token refresh (prevents concurrent requests)
|
|
474
|
+
- Token persistence callbacks
|
|
475
|
+
- Provider customization hooks for non-standard OAuth2 implementations
|
|
476
|
+
|
|
477
|
+
**⚠️ Server-Side Only**: OAuth2Manager requires `process.env` and should only be used in Node.js server environments, not in browser/client code.
|
|
478
|
+
|
|
440
479
|
## Advanced Topics
|
|
441
480
|
|
|
442
481
|
### Custom Action Engines
|