@mcp-abap-adt/auth-broker 0.1.12 → 0.2.2
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/CHANGELOG.md +140 -1
- package/README.md +160 -51
- package/dist/AuthBroker.d.ts +57 -35
- package/dist/AuthBroker.d.ts.map +1 -1
- package/dist/AuthBroker.js +454 -198
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/package.json +5 -4
package/dist/AuthBroker.js
CHANGED
|
@@ -2,8 +2,12 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Main AuthBroker class for managing JWT tokens based on destinations
|
|
4
4
|
*/
|
|
5
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
|
+
};
|
|
5
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
9
|
exports.AuthBroker = void 0;
|
|
10
|
+
const axios_1 = __importDefault(require("axios"));
|
|
7
11
|
/**
|
|
8
12
|
* No-op logger implementation for default fallback when logger is not provided
|
|
9
13
|
*/
|
|
@@ -13,9 +17,6 @@ const noOpLogger = {
|
|
|
13
17
|
warn: () => { },
|
|
14
18
|
debug: () => { },
|
|
15
19
|
};
|
|
16
|
-
/**
|
|
17
|
-
* AuthBroker manages JWT authentication tokens for destinations
|
|
18
|
-
*/
|
|
19
20
|
class AuthBroker {
|
|
20
21
|
browser;
|
|
21
22
|
logger;
|
|
@@ -24,43 +25,28 @@ class AuthBroker {
|
|
|
24
25
|
tokenProvider;
|
|
25
26
|
/**
|
|
26
27
|
* Create a new AuthBroker instance
|
|
27
|
-
* @param
|
|
28
|
-
* -
|
|
29
|
-
* -
|
|
30
|
-
* - tokenProvider: Token provider implementing ITokenProvider interface
|
|
28
|
+
* @param config Configuration object with stores and token provider
|
|
29
|
+
* - sessionStore: Store for session data (required)
|
|
30
|
+
* - serviceKeyStore: Store for service keys (optional)
|
|
31
|
+
* - tokenProvider: Token provider implementing ITokenProvider interface (optional). If not provided, direct UAA HTTP requests will be used when UAA credentials are available
|
|
31
32
|
* @param browser Optional browser name for authentication (chrome, edge, firefox, system, none).
|
|
32
33
|
* Default: 'system' (system default browser).
|
|
33
34
|
* Use 'none' to print URL instead of opening browser.
|
|
34
35
|
* @param logger Optional logger instance implementing ILogger interface. If not provided, uses no-op logger.
|
|
35
36
|
*/
|
|
36
|
-
constructor(
|
|
37
|
-
// Validate that
|
|
38
|
-
if (!
|
|
39
|
-
throw new Error('AuthBroker:
|
|
37
|
+
constructor(config, browser, logger) {
|
|
38
|
+
// Validate that config is provided
|
|
39
|
+
if (!config) {
|
|
40
|
+
throw new Error('AuthBroker: config parameter is required');
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
-
if (!stores.sessionStore) {
|
|
42
|
+
// Validate required sessionStore
|
|
43
|
+
if (!config.sessionStore) {
|
|
45
44
|
throw new Error('AuthBroker: sessionStore is required');
|
|
46
45
|
}
|
|
47
|
-
if (!stores.tokenProvider) {
|
|
48
|
-
throw new Error('AuthBroker: tokenProvider is required');
|
|
49
|
-
}
|
|
50
46
|
// Validate that stores and provider are correctly instantiated (have required methods)
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
// Check serviceKeyStore methods
|
|
55
|
-
if (typeof serviceKeyStore.getServiceKey !== 'function') {
|
|
56
|
-
throw new Error('AuthBroker: serviceKeyStore.getServiceKey must be a function');
|
|
57
|
-
}
|
|
58
|
-
if (typeof serviceKeyStore.getAuthorizationConfig !== 'function') {
|
|
59
|
-
throw new Error('AuthBroker: serviceKeyStore.getAuthorizationConfig must be a function');
|
|
60
|
-
}
|
|
61
|
-
if (typeof serviceKeyStore.getConnectionConfig !== 'function') {
|
|
62
|
-
throw new Error('AuthBroker: serviceKeyStore.getConnectionConfig must be a function');
|
|
63
|
-
}
|
|
47
|
+
const sessionStore = config.sessionStore;
|
|
48
|
+
const tokenProvider = config.tokenProvider;
|
|
49
|
+
const serviceKeyStore = config.serviceKeyStore;
|
|
64
50
|
// Check sessionStore methods
|
|
65
51
|
if (typeof sessionStore.getAuthorizationConfig !== 'function') {
|
|
66
52
|
throw new Error('AuthBroker: sessionStore.getAuthorizationConfig must be a function');
|
|
@@ -74,242 +60,504 @@ class AuthBroker {
|
|
|
74
60
|
if (typeof sessionStore.setConnectionConfig !== 'function') {
|
|
75
61
|
throw new Error('AuthBroker: sessionStore.setConnectionConfig must be a function');
|
|
76
62
|
}
|
|
77
|
-
// Check tokenProvider methods
|
|
78
|
-
if (
|
|
79
|
-
|
|
63
|
+
// Check tokenProvider methods (if provided)
|
|
64
|
+
if (tokenProvider) {
|
|
65
|
+
if (typeof tokenProvider.getConnectionConfig !== 'function') {
|
|
66
|
+
throw new Error('AuthBroker: tokenProvider.getConnectionConfig must be a function');
|
|
67
|
+
}
|
|
68
|
+
// validateToken is optional, so we don't check it
|
|
69
|
+
}
|
|
70
|
+
// Check serviceKeyStore methods (if provided)
|
|
71
|
+
if (serviceKeyStore) {
|
|
72
|
+
if (typeof serviceKeyStore.getServiceKey !== 'function') {
|
|
73
|
+
throw new Error('AuthBroker: serviceKeyStore.getServiceKey must be a function');
|
|
74
|
+
}
|
|
75
|
+
if (typeof serviceKeyStore.getAuthorizationConfig !== 'function') {
|
|
76
|
+
throw new Error('AuthBroker: serviceKeyStore.getAuthorizationConfig must be a function');
|
|
77
|
+
}
|
|
78
|
+
if (typeof serviceKeyStore.getConnectionConfig !== 'function') {
|
|
79
|
+
throw new Error('AuthBroker: serviceKeyStore.getConnectionConfig must be a function');
|
|
80
|
+
}
|
|
80
81
|
}
|
|
81
|
-
// validateToken is optional, so we don't check it
|
|
82
82
|
this.serviceKeyStore = serviceKeyStore;
|
|
83
83
|
this.sessionStore = sessionStore;
|
|
84
84
|
this.tokenProvider = tokenProvider;
|
|
85
85
|
this.browser = browser || 'system';
|
|
86
86
|
this.logger = logger || noOpLogger;
|
|
87
87
|
// Log successful initialization
|
|
88
|
-
this.
|
|
88
|
+
const hasServiceKeyStore = !!this.serviceKeyStore;
|
|
89
|
+
const hasTokenProvider = !!this.tokenProvider;
|
|
90
|
+
this.logger?.debug(`AuthBroker initialized: sessionStore(ok), serviceKeyStore(${hasServiceKeyStore ? 'ok' : 'none'}), tokenProvider(${hasTokenProvider ? 'ok' : 'none'})`);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Refresh token using refresh_token grant type (direct UAA HTTP request)
|
|
94
|
+
* @param refreshToken Refresh token
|
|
95
|
+
* @param authConfig UAA authorization configuration
|
|
96
|
+
* @returns Promise that resolves to new tokens
|
|
97
|
+
*/
|
|
98
|
+
async refreshTokenDirect(refreshToken, authConfig) {
|
|
99
|
+
if (!authConfig.uaaUrl || !authConfig.uaaClientId || !authConfig.uaaClientSecret) {
|
|
100
|
+
throw new Error('UAA credentials incomplete: uaaUrl, uaaClientId, and uaaClientSecret are required');
|
|
101
|
+
}
|
|
102
|
+
const tokenUrl = `${authConfig.uaaUrl}/oauth/token`;
|
|
103
|
+
const params = new URLSearchParams();
|
|
104
|
+
params.append('grant_type', 'refresh_token');
|
|
105
|
+
params.append('refresh_token', refreshToken);
|
|
106
|
+
const authString = Buffer.from(`${authConfig.uaaClientId}:${authConfig.uaaClientSecret}`).toString('base64');
|
|
107
|
+
try {
|
|
108
|
+
const response = await (0, axios_1.default)({
|
|
109
|
+
method: 'post',
|
|
110
|
+
url: tokenUrl,
|
|
111
|
+
headers: {
|
|
112
|
+
Authorization: `Basic ${authString}`,
|
|
113
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
114
|
+
},
|
|
115
|
+
data: params.toString(),
|
|
116
|
+
timeout: 30000,
|
|
117
|
+
});
|
|
118
|
+
if (response.data && response.data.access_token) {
|
|
119
|
+
return {
|
|
120
|
+
accessToken: response.data.access_token,
|
|
121
|
+
refreshToken: response.data.refresh_token || refreshToken,
|
|
122
|
+
expiresIn: response.data.expires_in,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
throw new Error('Response does not contain access_token');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
if (error.response) {
|
|
131
|
+
throw new Error(`Token refresh failed (${error.response.status}): ${JSON.stringify(error.response.data)}`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
throw new Error(`Token refresh failed: ${error.message}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get token using client_credentials grant type (direct UAA HTTP request)
|
|
140
|
+
* @param authConfig UAA authorization configuration
|
|
141
|
+
* @returns Promise that resolves to access token
|
|
142
|
+
*/
|
|
143
|
+
async getTokenWithClientCredentials(authConfig) {
|
|
144
|
+
if (!authConfig.uaaUrl || !authConfig.uaaClientId || !authConfig.uaaClientSecret) {
|
|
145
|
+
throw new Error('UAA credentials incomplete: uaaUrl, uaaClientId, and uaaClientSecret are required');
|
|
146
|
+
}
|
|
147
|
+
const tokenUrl = `${authConfig.uaaUrl}/oauth/token`;
|
|
148
|
+
const params = new URLSearchParams();
|
|
149
|
+
params.append('grant_type', 'client_credentials');
|
|
150
|
+
params.append('client_id', authConfig.uaaClientId);
|
|
151
|
+
params.append('client_secret', authConfig.uaaClientSecret);
|
|
152
|
+
try {
|
|
153
|
+
const response = await (0, axios_1.default)({
|
|
154
|
+
method: 'post',
|
|
155
|
+
url: tokenUrl,
|
|
156
|
+
headers: {
|
|
157
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
158
|
+
},
|
|
159
|
+
data: params.toString(),
|
|
160
|
+
timeout: 30000,
|
|
161
|
+
});
|
|
162
|
+
if (response.data && response.data.access_token) {
|
|
163
|
+
return {
|
|
164
|
+
accessToken: response.data.access_token,
|
|
165
|
+
refreshToken: response.data.refresh_token,
|
|
166
|
+
expiresIn: response.data.expires_in,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
throw new Error('Response does not contain access_token');
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (error.response) {
|
|
175
|
+
throw new Error(`Client credentials authentication failed (${error.response.status}): ${JSON.stringify(error.response.data)}`);
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
throw new Error(`Client credentials authentication failed: ${error.message}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
89
181
|
}
|
|
90
182
|
/**
|
|
91
183
|
* Get authentication token for destination.
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
* **Fallback Chain:**
|
|
95
|
-
* 1. **Check session**: Load token from session store and validate it
|
|
96
|
-
* - If token is valid, return it immediately
|
|
97
|
-
* - If token is invalid or missing, continue to next step
|
|
98
|
-
*
|
|
99
|
-
* 2. **Check service key**: Verify that service key exists
|
|
100
|
-
* - If no service key found, throw error
|
|
184
|
+
* Implements a three-step flow: Step 0 (initialize), Step 1 (refresh), Step 2 (UAA).
|
|
101
185
|
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
186
|
+
* **Flow:**
|
|
187
|
+
* **Step 0: Initialize Session with Token (if needed)**
|
|
188
|
+
* - Check if session has `authorizationToken` AND UAA credentials
|
|
189
|
+
* - If both are empty AND serviceKeyStore is available:
|
|
190
|
+
* - Try direct UAA request from service key (if UAA credentials available)
|
|
191
|
+
* - If failed and tokenProvider available → use provider
|
|
192
|
+
* - If session has token OR UAA credentials → proceed to Step 1
|
|
105
193
|
*
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
194
|
+
* **Step 1: Refresh Token Flow**
|
|
195
|
+
* - Check if refresh token exists in session
|
|
196
|
+
* - If refresh token exists:
|
|
197
|
+
* - Try direct UAA refresh (if UAA credentials in session)
|
|
198
|
+
* - If failed and tokenProvider available → use provider
|
|
199
|
+
* - If successful → return new token
|
|
200
|
+
* - Otherwise → proceed to Step 2
|
|
109
201
|
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
202
|
+
* **Step 2: UAA Credentials Flow**
|
|
203
|
+
* - Check if UAA credentials exist in session or service key
|
|
204
|
+
* - Try direct UAA client_credentials request (if UAA credentials available)
|
|
205
|
+
* - If failed and tokenProvider available → use provider
|
|
206
|
+
* - If successful → return new token
|
|
207
|
+
* - If all failed → return error
|
|
113
208
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
209
|
+
* **Important Notes:**
|
|
210
|
+
* - If sessionStore contains valid UAA credentials, neither serviceKeyStore nor tokenProvider are required.
|
|
211
|
+
* Direct UAA HTTP requests will be used automatically.
|
|
212
|
+
* - tokenProvider is only needed when:
|
|
213
|
+
* - Initializing session from service key via browser authentication (Step 0)
|
|
214
|
+
* - Direct UAA requests fail and fallback to provider is needed
|
|
118
215
|
*
|
|
119
216
|
* @param destination Destination name (e.g., "TRIAL")
|
|
120
217
|
* @returns Promise that resolves to JWT token string
|
|
121
|
-
* @throws Error if
|
|
218
|
+
* @throws Error if session initialization fails or all authentication methods failed
|
|
122
219
|
*/
|
|
123
220
|
async getToken(destination) {
|
|
124
221
|
this.logger?.debug(`Getting token for destination: ${destination}`);
|
|
125
|
-
// Step
|
|
222
|
+
// Step 0: Initialize Session with Token (if needed)
|
|
126
223
|
const connConfig = await this.sessionStore.getConnectionConfig(destination);
|
|
127
|
-
|
|
128
|
-
|
|
224
|
+
const authConfig = await this.sessionStore.getAuthorizationConfig(destination);
|
|
225
|
+
// Check if session has serviceUrl (required)
|
|
226
|
+
// If not in session, try to get it from serviceKeyStore
|
|
227
|
+
let serviceUrl = connConfig?.serviceUrl;
|
|
228
|
+
if (!serviceUrl && this.serviceKeyStore) {
|
|
229
|
+
const serviceKeyConnConfig = await this.serviceKeyStore.getConnectionConfig(destination);
|
|
230
|
+
serviceUrl = serviceKeyConnConfig?.serviceUrl;
|
|
231
|
+
if (serviceUrl) {
|
|
232
|
+
this.logger?.debug(`serviceUrl not in session for ${destination}, found in serviceKeyStore`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
if (!serviceUrl) {
|
|
236
|
+
this.logger?.error(`Session for destination "${destination}" is missing required field 'serviceUrl'. SessionStore must contain initial session with serviceUrl${this.serviceKeyStore ? ' or serviceKeyStore must contain serviceUrl' : ''}.`);
|
|
237
|
+
throw new Error(`Session for destination "${destination}" is missing required field 'serviceUrl'. ` +
|
|
238
|
+
`SessionStore must contain initial session with serviceUrl${this.serviceKeyStore ? ' or serviceKeyStore must contain serviceUrl' : ''}.`);
|
|
239
|
+
}
|
|
240
|
+
// Check if we have token or UAA credentials
|
|
241
|
+
const hasToken = !!connConfig?.authorizationToken;
|
|
242
|
+
const hasUaaCredentials = !!(authConfig?.uaaUrl && authConfig?.uaaClientId && authConfig?.uaaClientSecret);
|
|
243
|
+
this.logger?.debug(`Step 0: Session check for ${destination}: hasToken(${hasToken}), hasUaaCredentials(${hasUaaCredentials}), serviceUrl(${serviceUrl ? 'yes' : 'no'})`);
|
|
244
|
+
// If token is empty AND UAA fields are empty, try to initialize from service key
|
|
245
|
+
if (!hasToken && !hasUaaCredentials) {
|
|
246
|
+
this.logger?.debug(`Step 0: Token and UAA credentials are empty for ${destination}, attempting initialization from service key`);
|
|
247
|
+
if (!this.serviceKeyStore) {
|
|
248
|
+
this.logger?.error(`Step 0: Cannot initialize session for ${destination}: authorizationToken is empty, UAA credentials are empty, and serviceKeyStore is not available`);
|
|
249
|
+
throw new Error(`Cannot initialize session for destination "${destination}": authorizationToken is empty, UAA credentials are empty, and serviceKeyStore is not available. ` +
|
|
250
|
+
`Provide serviceKeyStore to initialize from service key.`);
|
|
251
|
+
}
|
|
252
|
+
try {
|
|
253
|
+
// Get UAA credentials from service key
|
|
254
|
+
const serviceKeyAuthConfig = await this.serviceKeyStore.getAuthorizationConfig(destination);
|
|
255
|
+
if (!serviceKeyAuthConfig || !serviceKeyAuthConfig.uaaUrl || !serviceKeyAuthConfig.uaaClientId || !serviceKeyAuthConfig.uaaClientSecret) {
|
|
256
|
+
this.logger?.error(`Step 0: Service key for ${destination} missing UAA credentials`);
|
|
257
|
+
throw new Error(`Service key for destination "${destination}" does not contain UAA credentials`);
|
|
258
|
+
}
|
|
259
|
+
// Try direct UAA request first if UAA credentials are available in service key
|
|
260
|
+
let tokenResult;
|
|
261
|
+
try {
|
|
262
|
+
// Use direct UAA HTTP request (preferred when UAA credentials are available)
|
|
263
|
+
this.logger?.debug(`Step 0: Authenticating via direct UAA request for ${destination} using service key UAA credentials`);
|
|
264
|
+
const uaaResult = await this.getTokenWithClientCredentials(serviceKeyAuthConfig);
|
|
265
|
+
tokenResult = {
|
|
266
|
+
connectionConfig: {
|
|
267
|
+
authorizationToken: uaaResult.accessToken,
|
|
268
|
+
},
|
|
269
|
+
refreshToken: uaaResult.refreshToken,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
catch (directError) {
|
|
273
|
+
this.logger?.debug(`Step 0: Direct UAA request failed for ${destination}: ${directError.message}, trying provider`);
|
|
274
|
+
// If direct UAA failed and we have provider, try provider
|
|
275
|
+
if (this.tokenProvider) {
|
|
276
|
+
this.logger?.debug(`Step 0: Authenticating via provider for ${destination} using service key UAA credentials`);
|
|
277
|
+
tokenResult = await this.tokenProvider.getConnectionConfig(serviceKeyAuthConfig, {
|
|
278
|
+
browser: this.browser,
|
|
279
|
+
logger: this.logger,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
throw directError; // No provider, re-throw direct error
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
const tokenLength = tokenResult.connectionConfig.authorizationToken?.length || 0;
|
|
287
|
+
this.logger?.info(`Step 0: Token initialized for ${destination}: token(${tokenLength} chars), hasRefreshToken(${!!tokenResult.refreshToken})`);
|
|
288
|
+
// Get serviceUrl from service key store if not in connectionConfig
|
|
289
|
+
const serviceKeyConnConfig = await this.serviceKeyStore.getConnectionConfig(destination);
|
|
290
|
+
const connectionConfigWithServiceUrl = {
|
|
291
|
+
...tokenResult.connectionConfig,
|
|
292
|
+
serviceUrl: tokenResult.connectionConfig.serviceUrl || serviceKeyConnConfig?.serviceUrl || serviceUrl,
|
|
293
|
+
};
|
|
294
|
+
// Save token and UAA credentials to session
|
|
295
|
+
await this.sessionStore.setConnectionConfig(destination, connectionConfigWithServiceUrl);
|
|
296
|
+
await this.sessionStore.setAuthorizationConfig(destination, {
|
|
297
|
+
...serviceKeyAuthConfig,
|
|
298
|
+
refreshToken: tokenResult.refreshToken || serviceKeyAuthConfig.refreshToken,
|
|
299
|
+
});
|
|
300
|
+
return tokenResult.connectionConfig.authorizationToken;
|
|
301
|
+
}
|
|
302
|
+
catch (error) {
|
|
303
|
+
this.logger?.error(`Step 0: Failed to initialize session for ${destination}: ${error.message}`);
|
|
304
|
+
const errorMessage = `Cannot initialize session for destination "${destination}": ${error.message}. ` +
|
|
305
|
+
`Ensure serviceKeyStore contains valid service key with UAA credentials${this.tokenProvider ? ' or provide tokenProvider for alternative authentication' : ''}.`;
|
|
306
|
+
throw new Error(errorMessage);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// If we have a token, validate it first
|
|
310
|
+
if (hasToken && connConfig.authorizationToken) {
|
|
311
|
+
this.logger?.debug(`Step 0: Token found for ${destination}, validating`);
|
|
129
312
|
// Validate token if provider supports validation and we have service URL
|
|
130
|
-
if (this.tokenProvider
|
|
131
|
-
this.
|
|
132
|
-
const isValid = await this.tokenProvider.validateToken(connConfig.authorizationToken, connConfig.serviceUrl);
|
|
313
|
+
if (this.tokenProvider?.validateToken && serviceUrl) {
|
|
314
|
+
const isValid = await this.tokenProvider.validateToken(connConfig.authorizationToken, serviceUrl);
|
|
133
315
|
if (isValid) {
|
|
134
|
-
this.logger?.info(`Token valid for ${destination}: token(${connConfig.authorizationToken.length} chars)`);
|
|
316
|
+
this.logger?.info(`Step 0: Token valid for ${destination}: token(${connConfig.authorizationToken.length} chars)`);
|
|
135
317
|
return connConfig.authorizationToken;
|
|
136
318
|
}
|
|
137
|
-
this.logger?.debug(`Token invalid for ${destination}, continuing to refresh`);
|
|
319
|
+
this.logger?.debug(`Step 0: Token invalid for ${destination}, continuing to refresh`);
|
|
138
320
|
}
|
|
139
321
|
else {
|
|
140
322
|
// No service URL or provider doesn't support validation - just return token
|
|
141
|
-
this.logger?.info(`Token found for ${destination} (no validation): token(${connConfig.authorizationToken.length} chars)`);
|
|
323
|
+
this.logger?.info(`Step 0: Token found for ${destination} (no validation): token(${connConfig.authorizationToken.length} chars)`);
|
|
142
324
|
return connConfig.authorizationToken;
|
|
143
325
|
}
|
|
144
326
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
// Step 2: No valid session, check if we have service key
|
|
149
|
-
this.logger?.debug(`Checking service key for ${destination}`);
|
|
150
|
-
const serviceKey = await this.serviceKeyStore.getServiceKey(destination);
|
|
151
|
-
if (!serviceKey) {
|
|
152
|
-
this.logger?.error(`No service key found for ${destination}`);
|
|
153
|
-
throw new Error(`No authentication found for destination "${destination}". ` +
|
|
154
|
-
`No session data and no service key found.`);
|
|
155
|
-
}
|
|
156
|
-
// Get authorization config from service key
|
|
157
|
-
const authConfig = await this.serviceKeyStore.getAuthorizationConfig(destination);
|
|
158
|
-
if (!authConfig) {
|
|
159
|
-
this.logger?.error(`Service key for ${destination} missing UAA credentials`);
|
|
160
|
-
throw new Error(`Service key for destination "${destination}" does not contain UAA credentials`);
|
|
161
|
-
}
|
|
162
|
-
this.logger?.debug(`Service key loaded for ${destination}: uaaUrl(${authConfig.uaaUrl.substring(0, 40)}...)`);
|
|
163
|
-
// Get refresh token from session (if exists)
|
|
164
|
-
const sessionAuthConfig = await this.sessionStore.getAuthorizationConfig(destination);
|
|
165
|
-
const refreshToken = sessionAuthConfig?.refreshToken || authConfig.refreshToken;
|
|
166
|
-
this.logger?.debug(`Refresh token check for ${destination}: hasRefreshToken(${!!refreshToken})`);
|
|
167
|
-
let tokenResult;
|
|
168
|
-
let lastError = null;
|
|
169
|
-
// Step 3: Try to refresh using refresh token (if available) via tokenProvider
|
|
327
|
+
// Step 1: Refresh Token Flow
|
|
328
|
+
this.logger?.debug(`Step 1: Checking refresh token for ${destination}`);
|
|
329
|
+
const refreshToken = authConfig?.refreshToken;
|
|
170
330
|
if (refreshToken) {
|
|
171
331
|
try {
|
|
172
|
-
this.logger?.debug(`Trying refresh token flow for ${destination}`);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
332
|
+
this.logger?.debug(`Step 1: Trying refresh token flow for ${destination}`);
|
|
333
|
+
// Get UAA credentials from session or service key
|
|
334
|
+
const uaaCredentials = authConfig || (this.serviceKeyStore ? await this.serviceKeyStore.getAuthorizationConfig(destination) : null);
|
|
335
|
+
if (!uaaCredentials || !uaaCredentials.uaaUrl || !uaaCredentials.uaaClientId || !uaaCredentials.uaaClientSecret) {
|
|
336
|
+
throw new Error('UAA credentials not found in session and serviceKeyStore not available');
|
|
337
|
+
}
|
|
338
|
+
let tokenResult;
|
|
339
|
+
// Try direct UAA request if UAA credentials are available
|
|
340
|
+
if (uaaCredentials.uaaUrl && uaaCredentials.uaaClientId && uaaCredentials.uaaClientSecret) {
|
|
341
|
+
try {
|
|
342
|
+
this.logger?.debug(`Step 1: Trying direct UAA refresh for ${destination}`);
|
|
343
|
+
const uaaResult = await this.refreshTokenDirect(refreshToken, uaaCredentials);
|
|
344
|
+
tokenResult = {
|
|
345
|
+
connectionConfig: {
|
|
346
|
+
authorizationToken: uaaResult.accessToken,
|
|
347
|
+
},
|
|
348
|
+
refreshToken: uaaResult.refreshToken,
|
|
349
|
+
};
|
|
350
|
+
this.logger?.debug(`Step 1: Direct UAA refresh succeeded for ${destination}`);
|
|
351
|
+
}
|
|
352
|
+
catch (directError) {
|
|
353
|
+
this.logger?.debug(`Step 1: Direct UAA refresh failed for ${destination}: ${directError.message}, trying provider`);
|
|
354
|
+
// If direct UAA failed and we have provider, try provider
|
|
355
|
+
if (this.tokenProvider) {
|
|
356
|
+
const authConfigWithRefresh = { ...uaaCredentials, refreshToken };
|
|
357
|
+
tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithRefresh, {
|
|
358
|
+
browser: this.browser,
|
|
359
|
+
logger: this.logger,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
throw directError; // No provider, re-throw direct error
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
else if (this.tokenProvider) {
|
|
368
|
+
// No UAA credentials but have provider
|
|
369
|
+
const authConfigWithRefresh = { ...uaaCredentials, refreshToken };
|
|
370
|
+
tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithRefresh, {
|
|
371
|
+
browser: this.browser,
|
|
372
|
+
logger: this.logger,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
throw new Error('UAA credentials incomplete and tokenProvider not available');
|
|
377
|
+
}
|
|
178
378
|
const tokenLength = tokenResult.connectionConfig.authorizationToken?.length || 0;
|
|
179
|
-
this.logger?.info(`Token refreshed for ${destination}: token(${tokenLength} chars), hasRefreshToken(${!!tokenResult.refreshToken})`);
|
|
180
|
-
// Get serviceUrl from service key
|
|
181
|
-
|
|
182
|
-
|
|
379
|
+
this.logger?.info(`Step 1: Token refreshed for ${destination}: token(${tokenLength} chars), hasRefreshToken(${!!tokenResult.refreshToken})`);
|
|
380
|
+
// Get serviceUrl from session or service key (use the one we already have from the beginning of the method)
|
|
381
|
+
const finalServiceUrl = tokenResult.connectionConfig.serviceUrl ||
|
|
382
|
+
serviceUrl ||
|
|
383
|
+
(this.serviceKeyStore ? (await this.serviceKeyStore.getConnectionConfig(destination))?.serviceUrl : undefined);
|
|
183
384
|
const connectionConfigWithServiceUrl = {
|
|
184
385
|
...tokenResult.connectionConfig,
|
|
185
|
-
serviceUrl:
|
|
386
|
+
serviceUrl: finalServiceUrl,
|
|
186
387
|
};
|
|
187
|
-
// Update
|
|
388
|
+
// Update session with new token
|
|
188
389
|
await this.sessionStore.setConnectionConfig(destination, connectionConfigWithServiceUrl);
|
|
189
390
|
if (tokenResult.refreshToken) {
|
|
190
391
|
await this.sessionStore.setAuthorizationConfig(destination, {
|
|
191
|
-
...
|
|
392
|
+
...uaaCredentials,
|
|
192
393
|
refreshToken: tokenResult.refreshToken,
|
|
193
394
|
});
|
|
194
395
|
}
|
|
195
396
|
return tokenResult.connectionConfig.authorizationToken;
|
|
196
397
|
}
|
|
197
398
|
catch (error) {
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
// Continue to next step
|
|
399
|
+
this.logger?.debug(`Step 1: Refresh token flow failed for ${destination}: ${error.message}, trying Step 2`);
|
|
400
|
+
// Continue to Step 2
|
|
201
401
|
}
|
|
202
402
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
try {
|
|
206
|
-
this.logger?.debug(`Trying UAA (client_credentials) flow for ${destination}`);
|
|
207
|
-
const authConfigWithoutRefresh = { ...authConfig, refreshToken: undefined };
|
|
208
|
-
tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithoutRefresh, {
|
|
209
|
-
browser: this.browser,
|
|
210
|
-
logger: this.logger,
|
|
211
|
-
});
|
|
212
|
-
const tokenLength = tokenResult.connectionConfig.authorizationToken?.length || 0;
|
|
213
|
-
this.logger?.info(`Token obtained via UAA for ${destination}: token(${tokenLength} chars), hasRefreshToken(${!!tokenResult.refreshToken})`);
|
|
214
|
-
// Get serviceUrl from service key store if not in connectionConfig (required for ABAP stores)
|
|
215
|
-
// For XSUAA service keys, serviceUrl may not exist, which is fine for BTP/XSUAA stores
|
|
216
|
-
const serviceKeyConnConfig = await this.serviceKeyStore.getConnectionConfig(destination);
|
|
217
|
-
const connectionConfigWithServiceUrl = {
|
|
218
|
-
...tokenResult.connectionConfig,
|
|
219
|
-
serviceUrl: tokenResult.connectionConfig.serviceUrl || serviceKeyConnConfig?.serviceUrl,
|
|
220
|
-
};
|
|
221
|
-
// Update or create session with new token (stores handle creation if session doesn't exist)
|
|
222
|
-
await this.sessionStore.setConnectionConfig(destination, connectionConfigWithServiceUrl);
|
|
223
|
-
if (tokenResult.refreshToken) {
|
|
224
|
-
await this.sessionStore.setAuthorizationConfig(destination, {
|
|
225
|
-
...authConfig,
|
|
226
|
-
refreshToken: tokenResult.refreshToken,
|
|
227
|
-
});
|
|
228
|
-
}
|
|
229
|
-
return tokenResult.connectionConfig.authorizationToken;
|
|
403
|
+
else {
|
|
404
|
+
this.logger?.debug(`Step 1: No refresh token found for ${destination}, proceeding to Step 2`);
|
|
230
405
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
406
|
+
// Step 2: UAA Credentials Flow
|
|
407
|
+
this.logger?.debug(`Step 2: Checking UAA credentials for ${destination}`);
|
|
408
|
+
// Get UAA credentials from session or service key
|
|
409
|
+
const uaaCredentials = authConfig || (this.serviceKeyStore ? await this.serviceKeyStore.getAuthorizationConfig(destination) : null);
|
|
410
|
+
if (!uaaCredentials || !uaaCredentials.uaaUrl || !uaaCredentials.uaaClientId || !uaaCredentials.uaaClientSecret) {
|
|
411
|
+
const errorMessage = `Step 2: UAA credentials not found for ${destination}. ` +
|
|
412
|
+
`Session has no UAA credentials${this.serviceKeyStore ? ' and serviceKeyStore has no UAA credentials' : ' and serviceKeyStore is not available'}.`;
|
|
413
|
+
this.logger?.error(errorMessage);
|
|
414
|
+
throw new Error(errorMessage);
|
|
235
415
|
}
|
|
236
|
-
// Step 5: Try browser authentication via tokenProvider (should be last resort)
|
|
237
|
-
// TokenProvider should use browser auth if refresh token and client_credentials don't work
|
|
238
416
|
try {
|
|
239
|
-
this.logger?.debug(`Trying
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
417
|
+
this.logger?.debug(`Step 2: Trying UAA (client_credentials) flow for ${destination}`);
|
|
418
|
+
let tokenResult;
|
|
419
|
+
// Try direct UAA request first if UAA credentials are available
|
|
420
|
+
if (uaaCredentials.uaaUrl && uaaCredentials.uaaClientId && uaaCredentials.uaaClientSecret) {
|
|
421
|
+
try {
|
|
422
|
+
this.logger?.debug(`Step 2: Trying direct UAA client_credentials for ${destination}`);
|
|
423
|
+
const uaaResult = await this.getTokenWithClientCredentials(uaaCredentials);
|
|
424
|
+
tokenResult = {
|
|
425
|
+
connectionConfig: {
|
|
426
|
+
authorizationToken: uaaResult.accessToken,
|
|
427
|
+
},
|
|
428
|
+
refreshToken: uaaResult.refreshToken,
|
|
429
|
+
};
|
|
430
|
+
this.logger?.debug(`Step 2: Direct UAA client_credentials succeeded for ${destination}`);
|
|
431
|
+
}
|
|
432
|
+
catch (directError) {
|
|
433
|
+
this.logger?.debug(`Step 2: Direct UAA client_credentials failed for ${destination}: ${directError.message}, trying provider`);
|
|
434
|
+
// If direct UAA failed and we have provider, try provider
|
|
435
|
+
if (this.tokenProvider) {
|
|
436
|
+
const authConfigWithoutRefresh = { ...uaaCredentials, refreshToken: undefined };
|
|
437
|
+
tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithoutRefresh, {
|
|
438
|
+
browser: this.browser,
|
|
439
|
+
logger: this.logger,
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
throw directError; // No provider, re-throw direct error
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
else if (this.tokenProvider) {
|
|
448
|
+
// No UAA credentials but have provider
|
|
449
|
+
const authConfigWithoutRefresh = { ...uaaCredentials, refreshToken: undefined };
|
|
450
|
+
tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithoutRefresh, {
|
|
451
|
+
browser: this.browser,
|
|
452
|
+
logger: this.logger,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
throw new Error('UAA credentials incomplete and tokenProvider not available');
|
|
457
|
+
}
|
|
245
458
|
const tokenLength = tokenResult.connectionConfig.authorizationToken?.length || 0;
|
|
246
|
-
this.logger?.info(`Token obtained via
|
|
247
|
-
// Get serviceUrl from service key
|
|
248
|
-
|
|
249
|
-
|
|
459
|
+
this.logger?.info(`Step 2: Token obtained via UAA for ${destination}: token(${tokenLength} chars), hasRefreshToken(${!!tokenResult.refreshToken})`);
|
|
460
|
+
// Get serviceUrl from session or service key (use the one we already have from the beginning of the method)
|
|
461
|
+
const finalServiceUrl = tokenResult.connectionConfig.serviceUrl ||
|
|
462
|
+
serviceUrl ||
|
|
463
|
+
(this.serviceKeyStore ? (await this.serviceKeyStore.getConnectionConfig(destination))?.serviceUrl : undefined);
|
|
250
464
|
const connectionConfigWithServiceUrl = {
|
|
251
465
|
...tokenResult.connectionConfig,
|
|
252
|
-
serviceUrl:
|
|
466
|
+
serviceUrl: finalServiceUrl,
|
|
253
467
|
};
|
|
254
|
-
// Update
|
|
468
|
+
// Update session with new token
|
|
255
469
|
await this.sessionStore.setConnectionConfig(destination, connectionConfigWithServiceUrl);
|
|
256
470
|
if (tokenResult.refreshToken) {
|
|
257
471
|
await this.sessionStore.setAuthorizationConfig(destination, {
|
|
258
|
-
...
|
|
472
|
+
...uaaCredentials,
|
|
259
473
|
refreshToken: tokenResult.refreshToken,
|
|
260
474
|
});
|
|
261
475
|
}
|
|
262
476
|
return tokenResult.connectionConfig.authorizationToken;
|
|
263
477
|
}
|
|
264
478
|
catch (error) {
|
|
265
|
-
|
|
266
|
-
//
|
|
479
|
+
this.logger?.error(`Step 2: UAA flow failed for ${destination}: ${error.message}`);
|
|
480
|
+
// If we have serviceKeyStore, we already tried it, so throw error
|
|
267
481
|
const errorMessage = `All authentication methods failed for destination "${destination}". ` +
|
|
268
|
-
`
|
|
269
|
-
`UAA: ${
|
|
270
|
-
|
|
271
|
-
this.logger?.error(`All auth methods failed for ${destination}: refreshToken(${refreshToken ? 'failed' : 'none'}), UAA(${authConfig.uaaUrl && authConfig.uaaClientId && authConfig.uaaClientSecret ? 'failed' : 'missing'}), browser(failed: ${error.message})`);
|
|
482
|
+
`Step 1 (refresh token): ${refreshToken ? 'failed' : 'not available'}. ` +
|
|
483
|
+
`Step 2 (UAA credentials): failed (${error.message}).`;
|
|
484
|
+
this.logger?.error(errorMessage);
|
|
272
485
|
throw new Error(errorMessage);
|
|
273
486
|
}
|
|
274
487
|
}
|
|
275
488
|
/**
|
|
276
|
-
* Force refresh token for destination
|
|
277
|
-
*
|
|
489
|
+
* Force refresh token for destination.
|
|
490
|
+
* Uses refresh token from session if available, otherwise uses UAA credentials from session or service key.
|
|
278
491
|
* @param destination Destination name (e.g., "TRIAL")
|
|
279
492
|
* @returns Promise that resolves to new JWT token string
|
|
280
493
|
*/
|
|
281
494
|
async refreshToken(destination) {
|
|
282
495
|
this.logger?.debug(`Force refreshing token for destination: ${destination}`);
|
|
283
|
-
//
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
this.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
// Get authorization config from service key
|
|
290
|
-
const authConfig = await this.serviceKeyStore.getAuthorizationConfig(destination);
|
|
496
|
+
// Get authorization config from session or service key
|
|
497
|
+
const sessionAuthConfig = await this.sessionStore.getAuthorizationConfig(destination);
|
|
498
|
+
const serviceKeyAuthConfig = this.serviceKeyStore
|
|
499
|
+
? await this.serviceKeyStore.getAuthorizationConfig(destination)
|
|
500
|
+
: null;
|
|
501
|
+
const authConfig = sessionAuthConfig || serviceKeyAuthConfig;
|
|
291
502
|
if (!authConfig) {
|
|
292
|
-
this.logger?.error(`
|
|
293
|
-
throw new Error(`
|
|
503
|
+
this.logger?.error(`Authorization config not found for ${destination}`);
|
|
504
|
+
throw new Error(`Authorization config not found for destination "${destination}". ` +
|
|
505
|
+
`Session has no UAA credentials${this.serviceKeyStore ? ' and serviceKeyStore has no UAA credentials' : ' and serviceKeyStore is not available'}.`);
|
|
294
506
|
}
|
|
295
|
-
// Get refresh token from session
|
|
296
|
-
const sessionAuthConfig = await this.sessionStore.getAuthorizationConfig(destination);
|
|
507
|
+
// Get refresh token from session or service key
|
|
297
508
|
const refreshToken = sessionAuthConfig?.refreshToken || authConfig.refreshToken;
|
|
298
509
|
this.logger?.debug(`Refresh token check for ${destination}: hasRefreshToken(${!!refreshToken})`);
|
|
299
|
-
|
|
300
|
-
//
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
510
|
+
let tokenResult;
|
|
511
|
+
// Try direct UAA request if UAA credentials are available
|
|
512
|
+
if (authConfig.uaaUrl && authConfig.uaaClientId && authConfig.uaaClientSecret && refreshToken) {
|
|
513
|
+
try {
|
|
514
|
+
this.logger?.debug(`Trying direct UAA refresh for ${destination}`);
|
|
515
|
+
const uaaResult = await this.refreshTokenDirect(refreshToken, authConfig);
|
|
516
|
+
tokenResult = {
|
|
517
|
+
connectionConfig: {
|
|
518
|
+
authorizationToken: uaaResult.accessToken,
|
|
519
|
+
},
|
|
520
|
+
refreshToken: uaaResult.refreshToken,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
catch (directError) {
|
|
524
|
+
this.logger?.debug(`Direct UAA refresh failed for ${destination}: ${directError.message}, trying provider`);
|
|
525
|
+
// If direct UAA failed and we have provider, try provider
|
|
526
|
+
if (this.tokenProvider) {
|
|
527
|
+
const authConfigWithRefresh = { ...authConfig, refreshToken };
|
|
528
|
+
tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithRefresh, {
|
|
529
|
+
browser: this.browser,
|
|
530
|
+
logger: this.logger,
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
else {
|
|
534
|
+
throw directError; // No provider, re-throw direct error
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
else if (this.tokenProvider) {
|
|
539
|
+
// No UAA credentials or refresh token, but have provider
|
|
540
|
+
const authConfigWithRefresh = { ...authConfig, refreshToken };
|
|
541
|
+
tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithRefresh, {
|
|
542
|
+
browser: this.browser,
|
|
543
|
+
logger: this.logger,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
throw new Error('UAA credentials incomplete and tokenProvider not available');
|
|
548
|
+
}
|
|
305
549
|
const tokenLength = tokenResult.connectionConfig.authorizationToken?.length || 0;
|
|
306
550
|
this.logger?.info(`Token refreshed for ${destination}: token(${tokenLength} chars), hasRefreshToken(${!!tokenResult.refreshToken})`);
|
|
307
|
-
// Get serviceUrl from service key
|
|
308
|
-
|
|
309
|
-
const serviceKeyConnConfig =
|
|
551
|
+
// Get serviceUrl from session or service key
|
|
552
|
+
const connConfig = await this.sessionStore.getConnectionConfig(destination);
|
|
553
|
+
const serviceKeyConnConfig = this.serviceKeyStore
|
|
554
|
+
? await this.serviceKeyStore.getConnectionConfig(destination)
|
|
555
|
+
: null;
|
|
310
556
|
const connectionConfigWithServiceUrl = {
|
|
311
557
|
...tokenResult.connectionConfig,
|
|
312
|
-
serviceUrl: tokenResult.connectionConfig.serviceUrl ||
|
|
558
|
+
serviceUrl: tokenResult.connectionConfig.serviceUrl ||
|
|
559
|
+
connConfig?.serviceUrl ||
|
|
560
|
+
serviceKeyConnConfig?.serviceUrl,
|
|
313
561
|
};
|
|
314
562
|
// Update or create session with new token (stores handle creation if session doesn't exist)
|
|
315
563
|
await this.sessionStore.setConnectionConfig(destination, connectionConfigWithServiceUrl);
|
|
@@ -335,16 +583,20 @@ class AuthBroker {
|
|
|
335
583
|
this.logger?.debug(`Authorization config from session for ${destination}: hasUaaUrl(${!!sessionAuthConfig.uaaUrl}), hasRefreshToken(${!!sessionAuthConfig.refreshToken})`);
|
|
336
584
|
return sessionAuthConfig;
|
|
337
585
|
}
|
|
338
|
-
// Fall back to service key store (has UAA credentials)
|
|
339
|
-
this.
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
586
|
+
// Fall back to service key store (has UAA credentials) if available
|
|
587
|
+
if (this.serviceKeyStore) {
|
|
588
|
+
this.logger?.debug(`Checking service key store for authorization config: ${destination}`);
|
|
589
|
+
const serviceKeyAuthConfig = await this.serviceKeyStore.getAuthorizationConfig(destination);
|
|
590
|
+
if (serviceKeyAuthConfig) {
|
|
591
|
+
this.logger?.debug(`Authorization config from service key for ${destination}: hasUaaUrl(${!!serviceKeyAuthConfig.uaaUrl})`);
|
|
592
|
+
return serviceKeyAuthConfig;
|
|
593
|
+
}
|
|
343
594
|
}
|
|
344
595
|
else {
|
|
345
|
-
this.logger?.debug(`
|
|
596
|
+
this.logger?.debug(`Service key store not available for ${destination}`);
|
|
346
597
|
}
|
|
347
|
-
|
|
598
|
+
this.logger?.debug(`No authorization config found for ${destination}`);
|
|
599
|
+
return null;
|
|
348
600
|
}
|
|
349
601
|
/**
|
|
350
602
|
* Get connection configuration for destination
|
|
@@ -359,15 +611,19 @@ class AuthBroker {
|
|
|
359
611
|
this.logger?.debug(`Connection config from session for ${destination}: token(${sessionConnConfig.authorizationToken?.length || 0} chars), serviceUrl(${sessionConnConfig.serviceUrl ? 'yes' : 'no'})`);
|
|
360
612
|
return sessionConnConfig;
|
|
361
613
|
}
|
|
362
|
-
// Fall back to service key store (has URLs but no tokens)
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
614
|
+
// Fall back to service key store (has URLs but no tokens) if available
|
|
615
|
+
if (this.serviceKeyStore) {
|
|
616
|
+
const serviceKeyConnConfig = await this.serviceKeyStore.getConnectionConfig(destination);
|
|
617
|
+
if (serviceKeyConnConfig) {
|
|
618
|
+
this.logger?.debug(`Connection config from service key for ${destination}: serviceUrl(${serviceKeyConnConfig.serviceUrl ? 'yes' : 'no'}), token(none)`);
|
|
619
|
+
return serviceKeyConnConfig;
|
|
620
|
+
}
|
|
366
621
|
}
|
|
367
622
|
else {
|
|
368
|
-
this.logger?.debug(`
|
|
623
|
+
this.logger?.debug(`Service key store not available for ${destination}`);
|
|
369
624
|
}
|
|
370
|
-
|
|
625
|
+
this.logger?.debug(`No connection config found for ${destination}`);
|
|
626
|
+
return null;
|
|
371
627
|
}
|
|
372
628
|
}
|
|
373
629
|
exports.AuthBroker = AuthBroker;
|