@mcp-abap-adt/auth-broker 0.1.4 → 0.1.6
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 +287 -0
- package/README.md +186 -9
- package/bin/generate-env-from-service-key.ts +128 -0
- package/dist/AuthBroker.d.ts +19 -35
- package/dist/AuthBroker.d.ts.map +1 -1
- package/dist/AuthBroker.js +87 -149
- package/dist/__tests__/helpers/configHelpers.d.ts +49 -0
- package/dist/__tests__/helpers/configHelpers.d.ts.map +1 -0
- package/dist/__tests__/helpers/configHelpers.js +169 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -7
- package/dist/providers/ITokenProvider.d.ts +49 -0
- package/dist/providers/ITokenProvider.d.ts.map +1 -0
- package/dist/providers/ITokenProvider.js +10 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +8 -0
- package/dist/stores/index.d.ts +5 -4
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/index.js +4 -6
- package/dist/stores/interfaces.d.ts +90 -20
- package/dist/stores/interfaces.d.ts.map +1 -1
- package/dist/stores/interfaces.js +1 -2
- package/dist/types.d.ts +7 -31
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -0
- package/package.json +13 -6
- package/dist/__tests__/testHelpers.d.ts +0 -44
- package/dist/__tests__/testHelpers.d.ts.map +0 -1
- package/dist/__tests__/testHelpers.js +0 -129
- package/dist/browserAuth.d.ts +0 -17
- package/dist/browserAuth.d.ts.map +0 -1
- package/dist/browserAuth.js +0 -305
- package/dist/cache.d.ts +0 -20
- package/dist/cache.d.ts.map +0 -1
- package/dist/cache.js +0 -46
- package/dist/envLoader.d.ts +0 -12
- package/dist/envLoader.d.ts.map +0 -1
- package/dist/envLoader.js +0 -90
- package/dist/getToken.d.ts +0 -14
- package/dist/getToken.d.ts.map +0 -1
- package/dist/getToken.js +0 -62
- package/dist/logger.d.ts +0 -40
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js +0 -186
- package/dist/pathResolver.d.ts +0 -21
- package/dist/pathResolver.d.ts.map +0 -1
- package/dist/pathResolver.js +0 -105
- package/dist/refreshToken.d.ts +0 -14
- package/dist/refreshToken.d.ts.map +0 -1
- package/dist/refreshToken.js +0 -71
- package/dist/serviceKeyLoader.d.ts +0 -12
- package/dist/serviceKeyLoader.d.ts.map +0 -1
- package/dist/serviceKeyLoader.js +0 -72
- package/dist/stores/FileServiceKeyStore.d.ts +0 -38
- package/dist/stores/FileServiceKeyStore.d.ts.map +0 -1
- package/dist/stores/FileServiceKeyStore.js +0 -47
- package/dist/stores/FileSessionStore.d.ts +0 -50
- package/dist/stores/FileSessionStore.d.ts.map +0 -1
- package/dist/stores/FileSessionStore.js +0 -116
- package/dist/tokenRefresher.d.ts +0 -17
- package/dist/tokenRefresher.d.ts.map +0 -1
- package/dist/tokenRefresher.js +0 -53
- package/dist/tokenStorage.d.ts +0 -15
- package/dist/tokenStorage.d.ts.map +0 -1
- package/dist/tokenStorage.js +0 -107
- package/dist/tokenValidator.d.ts +0 -11
- package/dist/tokenValidator.d.ts.map +0 -1
- package/dist/tokenValidator.js +0 -108
package/dist/AuthBroker.d.ts
CHANGED
|
@@ -1,35 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Main AuthBroker class for managing JWT tokens based on destinations
|
|
3
3
|
*/
|
|
4
|
-
import { Logger } from '
|
|
5
|
-
import {
|
|
4
|
+
import { Logger } from '@mcp-abap-adt/logger';
|
|
5
|
+
import { IServiceKeyStore, ISessionStore, IAuthorizationConfig, IConnectionConfig } from './stores/interfaces';
|
|
6
|
+
import { ITokenProvider } from './providers';
|
|
6
7
|
/**
|
|
7
8
|
* AuthBroker manages JWT authentication tokens for destinations
|
|
8
9
|
*/
|
|
9
10
|
export declare class AuthBroker {
|
|
10
|
-
private searchPaths;
|
|
11
11
|
private browser;
|
|
12
12
|
private logger;
|
|
13
13
|
private serviceKeyStore;
|
|
14
14
|
private sessionStore;
|
|
15
|
+
private tokenProvider;
|
|
15
16
|
/**
|
|
16
17
|
* Create a new AuthBroker instance
|
|
17
|
-
* @param
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* Priority for searchPaths:
|
|
22
|
-
* 1. Constructor parameter (highest)
|
|
23
|
-
* 2. AUTH_BROKER_PATH environment variable (colon/semicolon-separated)
|
|
24
|
-
* 3. Current working directory (lowest)
|
|
18
|
+
* @param stores Object with stores and token provider
|
|
19
|
+
* - serviceKeyStore: Store for service keys
|
|
20
|
+
* - sessionStore: Store for session data
|
|
21
|
+
* - tokenProvider: Token provider implementing ITokenProvider interface
|
|
25
22
|
* @param browser Optional browser name for authentication (chrome, edge, firefox, system, none).
|
|
26
23
|
* Default: 'system' (system default browser).
|
|
27
24
|
* Use 'none' to print URL instead of opening browser.
|
|
28
25
|
* @param logger Optional logger instance. If not provided, uses default logger.
|
|
29
26
|
*/
|
|
30
|
-
constructor(
|
|
31
|
-
serviceKeyStore
|
|
32
|
-
sessionStore
|
|
27
|
+
constructor(stores: {
|
|
28
|
+
serviceKeyStore: IServiceKeyStore;
|
|
29
|
+
sessionStore: ISessionStore;
|
|
30
|
+
tokenProvider: ITokenProvider;
|
|
33
31
|
}, browser?: string, logger?: Logger);
|
|
34
32
|
/**
|
|
35
33
|
* Get authentication token for destination.
|
|
@@ -47,30 +45,16 @@ export declare class AuthBroker {
|
|
|
47
45
|
*/
|
|
48
46
|
refreshToken(destination: string): Promise<string>;
|
|
49
47
|
/**
|
|
50
|
-
*
|
|
51
|
-
* @private
|
|
52
|
-
*/
|
|
53
|
-
private refreshTokenInternal;
|
|
54
|
-
/**
|
|
55
|
-
* Get SAP URL for destination.
|
|
56
|
-
* Tries to load from session store first, then from service key store.
|
|
48
|
+
* Get authorization configuration for destination
|
|
57
49
|
* @param destination Destination name (e.g., "TRIAL")
|
|
58
|
-
* @returns Promise that resolves to
|
|
59
|
-
*/
|
|
60
|
-
getSapUrl(destination: string): Promise<string | undefined>;
|
|
61
|
-
/**
|
|
62
|
-
* Clear cached token for specific destination
|
|
63
|
-
* @param destination Destination name
|
|
50
|
+
* @returns Promise that resolves to IAuthorizationConfig or null if not found
|
|
64
51
|
*/
|
|
65
|
-
|
|
52
|
+
getAuthorizationConfig(destination: string): Promise<IAuthorizationConfig | null>;
|
|
66
53
|
/**
|
|
67
|
-
*
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Get search paths for error messages (from file stores if available)
|
|
72
|
-
* @private
|
|
54
|
+
* Get connection configuration for destination
|
|
55
|
+
* @param destination Destination name (e.g., "TRIAL")
|
|
56
|
+
* @returns Promise that resolves to IConnectionConfig or null if not found
|
|
73
57
|
*/
|
|
74
|
-
|
|
58
|
+
getConnectionConfig(destination: string): Promise<IConnectionConfig | null>;
|
|
75
59
|
}
|
|
76
60
|
//# sourceMappingURL=AuthBroker.d.ts.map
|
package/dist/AuthBroker.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAiB,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC/G,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,eAAe,CAAmB;IAC1C,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,aAAa,CAAiB;IAEtC;;;;;;;;;;OAUG;gBAED,MAAM,EAAE;QAAE,eAAe,EAAE,gBAAgB,CAAC;QAAC,YAAY,EAAE,aAAa,CAAC;QAAC,aAAa,EAAE,cAAc,CAAA;KAAE,EACzG,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM;IASjB;;;;;;OAMG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAwDpD;;;;;OAKG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAuCxD;;;;OAIG;IACG,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAWvF;;;;OAIG;IACG,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;CAWlF"}
|
package/dist/AuthBroker.js
CHANGED
|
@@ -4,51 +4,31 @@
|
|
|
4
4
|
*/
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.AuthBroker = void 0;
|
|
7
|
-
const
|
|
8
|
-
const tokenRefresher_1 = require("./tokenRefresher");
|
|
9
|
-
const browserAuth_1 = require("./browserAuth");
|
|
10
|
-
const cache_1 = require("./cache");
|
|
11
|
-
const pathResolver_1 = require("./pathResolver");
|
|
12
|
-
const logger_1 = require("./logger");
|
|
13
|
-
const stores_1 = require("./stores");
|
|
7
|
+
const logger_1 = require("@mcp-abap-adt/logger");
|
|
14
8
|
/**
|
|
15
9
|
* AuthBroker manages JWT authentication tokens for destinations
|
|
16
10
|
*/
|
|
17
11
|
class AuthBroker {
|
|
18
|
-
searchPaths;
|
|
19
12
|
browser;
|
|
20
13
|
logger;
|
|
21
14
|
serviceKeyStore;
|
|
22
15
|
sessionStore;
|
|
16
|
+
tokenProvider;
|
|
23
17
|
/**
|
|
24
18
|
* Create a new AuthBroker instance
|
|
25
|
-
* @param
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* Priority for searchPaths:
|
|
30
|
-
* 1. Constructor parameter (highest)
|
|
31
|
-
* 2. AUTH_BROKER_PATH environment variable (colon/semicolon-separated)
|
|
32
|
-
* 3. Current working directory (lowest)
|
|
19
|
+
* @param stores Object with stores and token provider
|
|
20
|
+
* - serviceKeyStore: Store for service keys
|
|
21
|
+
* - sessionStore: Store for session data
|
|
22
|
+
* - tokenProvider: Token provider implementing ITokenProvider interface
|
|
33
23
|
* @param browser Optional browser name for authentication (chrome, edge, firefox, system, none).
|
|
34
24
|
* Default: 'system' (system default browser).
|
|
35
25
|
* Use 'none' to print URL instead of opening browser.
|
|
36
26
|
* @param logger Optional logger instance. If not provided, uses default logger.
|
|
37
27
|
*/
|
|
38
|
-
constructor(
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// Create default file-based stores
|
|
43
|
-
this.serviceKeyStore = new stores_1.FileServiceKeyStore(this.searchPaths);
|
|
44
|
-
this.sessionStore = new stores_1.FileSessionStore(this.searchPaths);
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
// New API: stores provided
|
|
48
|
-
this.searchPaths = (0, pathResolver_1.resolveSearchPaths)(undefined); // Still resolve for backward compatibility in internal functions
|
|
49
|
-
this.serviceKeyStore = searchPathsOrStores.serviceKeyStore || new stores_1.FileServiceKeyStore();
|
|
50
|
-
this.sessionStore = searchPathsOrStores.sessionStore || new stores_1.FileSessionStore();
|
|
51
|
-
}
|
|
28
|
+
constructor(stores, browser, logger) {
|
|
29
|
+
this.serviceKeyStore = stores.serviceKeyStore;
|
|
30
|
+
this.sessionStore = stores.sessionStore;
|
|
31
|
+
this.tokenProvider = stores.tokenProvider;
|
|
52
32
|
this.browser = browser || 'system';
|
|
53
33
|
this.logger = logger || logger_1.defaultLogger;
|
|
54
34
|
}
|
|
@@ -60,46 +40,51 @@ class AuthBroker {
|
|
|
60
40
|
* @throws Error if neither session data nor service key found
|
|
61
41
|
*/
|
|
62
42
|
async getToken(destination) {
|
|
63
|
-
//
|
|
64
|
-
const
|
|
65
|
-
if (
|
|
66
|
-
// Validate
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const isValid = await (0, tokenValidator_1.validateToken)(cachedToken, envConfig.sapUrl);
|
|
43
|
+
// Load connection config from session store
|
|
44
|
+
const connConfig = await this.sessionStore.getConnectionConfig(destination);
|
|
45
|
+
if (connConfig?.authorizationToken) {
|
|
46
|
+
// Validate token if provider supports validation and we have service URL
|
|
47
|
+
if (this.tokenProvider.validateToken && connConfig.serviceUrl) {
|
|
48
|
+
const isValid = await this.tokenProvider.validateToken(connConfig.authorizationToken, connConfig.serviceUrl);
|
|
70
49
|
if (isValid) {
|
|
71
|
-
return
|
|
50
|
+
return connConfig.authorizationToken;
|
|
72
51
|
}
|
|
73
|
-
// Token expired, remove from cache
|
|
74
52
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (envConfig && envConfig.jwtToken) {
|
|
79
|
-
// Validate token
|
|
80
|
-
const isValid = await (0, tokenValidator_1.validateToken)(envConfig.jwtToken, envConfig.sapUrl);
|
|
81
|
-
if (isValid) {
|
|
82
|
-
(0, cache_1.setCachedToken)(destination, envConfig.jwtToken);
|
|
83
|
-
return envConfig.jwtToken;
|
|
53
|
+
else {
|
|
54
|
+
// No service URL or provider doesn't support validation - just return token
|
|
55
|
+
return connConfig.authorizationToken;
|
|
84
56
|
}
|
|
85
57
|
}
|
|
86
|
-
// Token not found or expired, check if we have service key
|
|
58
|
+
// Token not found or expired, check if we have service key
|
|
87
59
|
const serviceKey = await this.serviceKeyStore.getServiceKey(destination);
|
|
88
60
|
if (!serviceKey) {
|
|
89
|
-
// No service key and no valid token
|
|
90
|
-
const searchPaths = this.getSearchPathsForError();
|
|
91
|
-
const searchedPaths = searchPaths.map(p => ` - ${p}`).join('\n');
|
|
61
|
+
// No service key and no valid token
|
|
92
62
|
throw new Error(`No authentication found for destination "${destination}". ` +
|
|
93
|
-
`
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
63
|
+
`No session data and no service key found.`);
|
|
64
|
+
}
|
|
65
|
+
// Get authorization config from service key
|
|
66
|
+
const authConfig = await this.serviceKeyStore.getAuthorizationConfig(destination);
|
|
67
|
+
if (!authConfig) {
|
|
68
|
+
throw new Error(`Service key for destination "${destination}" does not contain UAA credentials`);
|
|
69
|
+
}
|
|
70
|
+
// Get refresh token from session
|
|
71
|
+
const sessionAuthConfig = await this.sessionStore.getAuthorizationConfig(destination);
|
|
72
|
+
const authConfigWithRefresh = { ...authConfig, refreshToken: sessionAuthConfig?.refreshToken || authConfig.refreshToken };
|
|
73
|
+
// Get connection config with token from provider
|
|
74
|
+
const tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithRefresh, {
|
|
75
|
+
browser: this.browser,
|
|
76
|
+
logger: this.logger,
|
|
77
|
+
});
|
|
78
|
+
// Update session with new token
|
|
79
|
+
await this.sessionStore.setConnectionConfig(destination, tokenResult.connectionConfig);
|
|
80
|
+
// Update authorization config with new refresh token if available
|
|
81
|
+
if (tokenResult.refreshToken) {
|
|
82
|
+
await this.sessionStore.setAuthorizationConfig(destination, {
|
|
83
|
+
...authConfig,
|
|
84
|
+
refreshToken: tokenResult.refreshToken,
|
|
85
|
+
});
|
|
98
86
|
}
|
|
99
|
-
|
|
100
|
-
const newToken = await this.refreshTokenInternal(destination, serviceKey, envConfig);
|
|
101
|
-
(0, cache_1.setCachedToken)(destination, newToken);
|
|
102
|
-
return newToken;
|
|
87
|
+
return tokenResult.connectionConfig.authorizationToken;
|
|
103
88
|
}
|
|
104
89
|
/**
|
|
105
90
|
* Force refresh token for destination using service key.
|
|
@@ -111,106 +96,59 @@ class AuthBroker {
|
|
|
111
96
|
// Load service key
|
|
112
97
|
const serviceKey = await this.serviceKeyStore.getServiceKey(destination);
|
|
113
98
|
if (!serviceKey) {
|
|
114
|
-
|
|
115
|
-
const searchedPaths = searchPaths.map(p => ` - ${p}`).join('\n');
|
|
116
|
-
throw new Error(`Service key file not found for destination "${destination}".\n` +
|
|
117
|
-
`Please create file: ${destination}.json\n` +
|
|
118
|
-
`Searched in:\n${searchedPaths}`);
|
|
119
|
-
}
|
|
120
|
-
// Load existing session (for refresh token)
|
|
121
|
-
const envConfig = await this.sessionStore.loadSession(destination);
|
|
122
|
-
return this.refreshTokenInternal(destination, serviceKey, envConfig);
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Internal refresh token implementation
|
|
126
|
-
* @private
|
|
127
|
-
*/
|
|
128
|
-
async refreshTokenInternal(destination, serviceKey, envConfig) {
|
|
129
|
-
// Extract UAA configuration
|
|
130
|
-
const { url: uaaUrl, clientid: clientId, clientsecret: clientSecret } = serviceKey.uaa;
|
|
131
|
-
if (!uaaUrl || !clientId || !clientSecret) {
|
|
132
|
-
throw new Error(`Invalid service key for destination "${destination}". ` +
|
|
133
|
-
`Missing required UAA fields: url, clientid, clientsecret`);
|
|
134
|
-
}
|
|
135
|
-
// Validate SAP URL early (before starting browser auth or refresh)
|
|
136
|
-
const sapUrl = serviceKey.url || serviceKey.abap?.url || serviceKey.sap_url;
|
|
137
|
-
if (!sapUrl) {
|
|
138
|
-
throw new Error(`Service key for destination "${destination}" does not contain SAP URL. ` +
|
|
139
|
-
`Expected field: url, abap.url, or sap_url`);
|
|
140
|
-
}
|
|
141
|
-
// Try to load existing refresh token from session store
|
|
142
|
-
let refreshTokenValue = envConfig?.refreshToken;
|
|
143
|
-
let result;
|
|
144
|
-
// If no refresh token, start browser authentication flow
|
|
145
|
-
if (!refreshTokenValue) {
|
|
146
|
-
this.logger.debug(`No refresh token found for destination "${destination}". Starting browser authentication...`);
|
|
147
|
-
result = await (0, browserAuth_1.startBrowserAuth)(serviceKey, this.browser || 'system', this.logger);
|
|
99
|
+
throw new Error(`Service key not found for destination "${destination}".`);
|
|
148
100
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
101
|
+
// Get authorization config from service key
|
|
102
|
+
const authConfig = await this.serviceKeyStore.getAuthorizationConfig(destination);
|
|
103
|
+
if (!authConfig) {
|
|
104
|
+
throw new Error(`Service key for destination "${destination}" does not contain UAA credentials`);
|
|
152
105
|
}
|
|
153
|
-
//
|
|
154
|
-
await this.sessionStore.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
uaaClientSecret: clientSecret,
|
|
161
|
-
sapClient: envConfig?.sapClient,
|
|
162
|
-
language: envConfig?.language,
|
|
106
|
+
// Get refresh token from session
|
|
107
|
+
const sessionAuthConfig = await this.sessionStore.getAuthorizationConfig(destination);
|
|
108
|
+
const authConfigWithRefresh = { ...authConfig, refreshToken: sessionAuthConfig?.refreshToken || authConfig.refreshToken };
|
|
109
|
+
// Get connection config with token from provider
|
|
110
|
+
const tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithRefresh, {
|
|
111
|
+
browser: this.browser,
|
|
112
|
+
logger: this.logger,
|
|
163
113
|
});
|
|
164
|
-
// Update
|
|
165
|
-
|
|
166
|
-
|
|
114
|
+
// Update session with new token
|
|
115
|
+
await this.sessionStore.setConnectionConfig(destination, tokenResult.connectionConfig);
|
|
116
|
+
// Update authorization config with new refresh token if available
|
|
117
|
+
if (tokenResult.refreshToken) {
|
|
118
|
+
await this.sessionStore.setAuthorizationConfig(destination, {
|
|
119
|
+
...authConfig,
|
|
120
|
+
refreshToken: tokenResult.refreshToken,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return tokenResult.connectionConfig.authorizationToken;
|
|
167
124
|
}
|
|
168
125
|
/**
|
|
169
|
-
* Get
|
|
170
|
-
* Tries to load from session store first, then from service key store.
|
|
126
|
+
* Get authorization configuration for destination
|
|
171
127
|
* @param destination Destination name (e.g., "TRIAL")
|
|
172
|
-
* @returns Promise that resolves to
|
|
128
|
+
* @returns Promise that resolves to IAuthorizationConfig or null if not found
|
|
173
129
|
*/
|
|
174
|
-
async
|
|
175
|
-
// Try
|
|
176
|
-
const
|
|
177
|
-
if (
|
|
178
|
-
return
|
|
179
|
-
}
|
|
180
|
-
// Try service key store
|
|
181
|
-
const serviceKey = await this.serviceKeyStore.getServiceKey(destination);
|
|
182
|
-
if (serviceKey) {
|
|
183
|
-
return serviceKey.url || serviceKey.abap?.url || serviceKey.sap_url;
|
|
130
|
+
async getAuthorizationConfig(destination) {
|
|
131
|
+
// Try session store first (has tokens)
|
|
132
|
+
const sessionAuthConfig = await this.sessionStore.getAuthorizationConfig(destination);
|
|
133
|
+
if (sessionAuthConfig) {
|
|
134
|
+
return sessionAuthConfig;
|
|
184
135
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Clear cached token for specific destination
|
|
189
|
-
* @param destination Destination name
|
|
190
|
-
*/
|
|
191
|
-
clearCache(destination) {
|
|
192
|
-
(0, cache_1.clearCache)(destination);
|
|
136
|
+
// Fall back to service key store (has UAA credentials)
|
|
137
|
+
return await this.serviceKeyStore.getAuthorizationConfig(destination);
|
|
193
138
|
}
|
|
194
139
|
/**
|
|
195
|
-
*
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
(0, cache_1.clearAllCache)();
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Get search paths for error messages (from file stores if available)
|
|
202
|
-
* @private
|
|
140
|
+
* Get connection configuration for destination
|
|
141
|
+
* @param destination Destination name (e.g., "TRIAL")
|
|
142
|
+
* @returns Promise that resolves to IConnectionConfig or null if not found
|
|
203
143
|
*/
|
|
204
|
-
|
|
205
|
-
// Try
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (this.sessionStore instanceof stores_1.FileSessionStore) {
|
|
210
|
-
return this.sessionStore.getSearchPaths();
|
|
144
|
+
async getConnectionConfig(destination) {
|
|
145
|
+
// Try session store first (has tokens and URLs)
|
|
146
|
+
const sessionConnConfig = await this.sessionStore.getConnectionConfig(destination);
|
|
147
|
+
if (sessionConnConfig) {
|
|
148
|
+
return sessionConnConfig;
|
|
211
149
|
}
|
|
212
|
-
//
|
|
213
|
-
return this.
|
|
150
|
+
// Fall back to service key store (has URLs but no tokens)
|
|
151
|
+
return await this.serviceKeyStore.getConnectionConfig(destination);
|
|
214
152
|
}
|
|
215
153
|
}
|
|
216
154
|
exports.AuthBroker = AuthBroker;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration helpers for auth-broker tests
|
|
3
|
+
* Loads test configuration from test-config.yaml
|
|
4
|
+
*/
|
|
5
|
+
export interface TestConfig {
|
|
6
|
+
auth_broker?: {
|
|
7
|
+
paths?: {
|
|
8
|
+
service_keys_dir?: string;
|
|
9
|
+
sessions_dir?: string;
|
|
10
|
+
};
|
|
11
|
+
abap?: {
|
|
12
|
+
destination?: string;
|
|
13
|
+
};
|
|
14
|
+
xsuaa?: {
|
|
15
|
+
btp_destination?: string;
|
|
16
|
+
mcp_destination?: string;
|
|
17
|
+
mcp_url?: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Load test configuration from YAML
|
|
23
|
+
* Uses test-config.yaml from tests/ directory
|
|
24
|
+
*/
|
|
25
|
+
export declare function loadTestConfig(): TestConfig;
|
|
26
|
+
/**
|
|
27
|
+
* Check if test config has real values (not placeholders)
|
|
28
|
+
*/
|
|
29
|
+
export declare function hasRealConfig(config: TestConfig, section: 'abap' | 'xsuaa'): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get ABAP destination from config
|
|
32
|
+
*/
|
|
33
|
+
export declare function getAbapDestination(config?: TestConfig): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Get XSUAA destinations from config
|
|
36
|
+
*/
|
|
37
|
+
export declare function getXsuaaDestinations(config?: TestConfig): {
|
|
38
|
+
btp_destination: string | null;
|
|
39
|
+
mcp_url: string | null;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Get service keys directory from config
|
|
43
|
+
*/
|
|
44
|
+
export declare function getServiceKeysDir(config?: TestConfig): string | null;
|
|
45
|
+
/**
|
|
46
|
+
* Get sessions directory from config
|
|
47
|
+
*/
|
|
48
|
+
export declare function getSessionsDir(config?: TestConfig): string | null;
|
|
49
|
+
//# sourceMappingURL=configHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configHelpers.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/configHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE;YACN,gBAAgB,CAAC,EAAE,MAAM,CAAC;YAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;SACvB,CAAC;QACF,IAAI,CAAC,EAAE;YACL,WAAW,CAAC,EAAE,MAAM,CAAC;SACtB,CAAC;QACF,KAAK,CAAC,EAAE;YACN,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,CAAC;KACH,CAAC;CACH;AAkBD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,UAAU,CA6C3C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CA2BpF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAGrE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG;IACzD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAOA;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAGpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAGjE"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration helpers for auth-broker tests
|
|
4
|
+
* Loads test configuration from test-config.yaml
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.loadTestConfig = loadTestConfig;
|
|
41
|
+
exports.hasRealConfig = hasRealConfig;
|
|
42
|
+
exports.getAbapDestination = getAbapDestination;
|
|
43
|
+
exports.getXsuaaDestinations = getXsuaaDestinations;
|
|
44
|
+
exports.getServiceKeysDir = getServiceKeysDir;
|
|
45
|
+
exports.getSessionsDir = getSessionsDir;
|
|
46
|
+
const fs = __importStar(require("fs"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const yaml = __importStar(require("js-yaml"));
|
|
49
|
+
let cachedConfig = null;
|
|
50
|
+
/**
|
|
51
|
+
* Find project root directory by looking for package.json
|
|
52
|
+
*/
|
|
53
|
+
function findProjectRoot() {
|
|
54
|
+
let currentDir = __dirname;
|
|
55
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
56
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
57
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
58
|
+
return currentDir;
|
|
59
|
+
}
|
|
60
|
+
currentDir = path.dirname(currentDir);
|
|
61
|
+
}
|
|
62
|
+
// Fallback to process.cwd() if package.json not found
|
|
63
|
+
return process.cwd();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Load test configuration from YAML
|
|
67
|
+
* Uses test-config.yaml from tests/ directory
|
|
68
|
+
*/
|
|
69
|
+
function loadTestConfig() {
|
|
70
|
+
if (cachedConfig) {
|
|
71
|
+
return cachedConfig;
|
|
72
|
+
}
|
|
73
|
+
// Find project root and load from tests/test-config.yaml
|
|
74
|
+
const projectRoot = findProjectRoot();
|
|
75
|
+
const configPath = path.resolve(projectRoot, 'tests', 'test-config.yaml');
|
|
76
|
+
const templatePath = path.resolve(projectRoot, 'tests', 'test-config.yaml.template');
|
|
77
|
+
if (process.env.TEST_VERBOSE) {
|
|
78
|
+
console.log(`[configHelpers] Project root: ${projectRoot}`);
|
|
79
|
+
console.log(`[configHelpers] Config path: ${configPath}`);
|
|
80
|
+
console.log(`[configHelpers] Config exists: ${fs.existsSync(configPath)}`);
|
|
81
|
+
}
|
|
82
|
+
if (fs.existsSync(configPath)) {
|
|
83
|
+
try {
|
|
84
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
85
|
+
cachedConfig = yaml.load(configContent) || {};
|
|
86
|
+
if (process.env.TEST_VERBOSE) {
|
|
87
|
+
console.log(`[configHelpers] Loaded config:`, JSON.stringify(cachedConfig, null, 2));
|
|
88
|
+
}
|
|
89
|
+
return cachedConfig;
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.warn(`Failed to load test config from ${configPath}:`, error);
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (fs.existsSync(templatePath)) {
|
|
97
|
+
console.warn('⚠️ tests/test-config.yaml not found. Using template (all integration tests will be disabled).');
|
|
98
|
+
try {
|
|
99
|
+
const templateContent = fs.readFileSync(templatePath, 'utf8');
|
|
100
|
+
cachedConfig = yaml.load(templateContent) || {};
|
|
101
|
+
return cachedConfig;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
console.warn(`Failed to load test config template from ${templatePath}:`, error);
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
console.warn('⚠️ Test configuration files not found.');
|
|
109
|
+
console.warn('Please create tests/test-config.yaml with test parameters.');
|
|
110
|
+
return {};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if test config has real values (not placeholders)
|
|
114
|
+
*/
|
|
115
|
+
function hasRealConfig(config, section) {
|
|
116
|
+
if (!config.auth_broker) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
if (section === 'abap') {
|
|
120
|
+
const abap = config.auth_broker.abap;
|
|
121
|
+
if (!abap?.destination) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
// Check if destination is not a placeholder
|
|
125
|
+
return !abap.destination.includes('<') && !abap.destination.includes('>');
|
|
126
|
+
}
|
|
127
|
+
if (section === 'xsuaa') {
|
|
128
|
+
const xsuaa = config.auth_broker.xsuaa;
|
|
129
|
+
if (!xsuaa?.btp_destination || !xsuaa?.mcp_url) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
// Check if values are not placeholders
|
|
133
|
+
return (!xsuaa.btp_destination.includes('<') &&
|
|
134
|
+
!xsuaa.mcp_url.includes('<'));
|
|
135
|
+
}
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get ABAP destination from config
|
|
140
|
+
*/
|
|
141
|
+
function getAbapDestination(config) {
|
|
142
|
+
const cfg = config || loadTestConfig();
|
|
143
|
+
return cfg.auth_broker?.abap?.destination || null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get XSUAA destinations from config
|
|
147
|
+
*/
|
|
148
|
+
function getXsuaaDestinations(config) {
|
|
149
|
+
const cfg = config || loadTestConfig();
|
|
150
|
+
const xsuaa = cfg.auth_broker?.xsuaa;
|
|
151
|
+
return {
|
|
152
|
+
btp_destination: xsuaa?.btp_destination || null,
|
|
153
|
+
mcp_url: xsuaa?.mcp_url || null,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get service keys directory from config
|
|
158
|
+
*/
|
|
159
|
+
function getServiceKeysDir(config) {
|
|
160
|
+
const cfg = config || loadTestConfig();
|
|
161
|
+
return cfg.auth_broker?.paths?.service_keys_dir || null;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get sessions directory from config
|
|
165
|
+
*/
|
|
166
|
+
function getSessionsDir(config) {
|
|
167
|
+
const cfg = config || loadTestConfig();
|
|
168
|
+
return cfg.auth_broker?.paths?.sessions_dir || null;
|
|
169
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* JWT authentication broker for MCP ABAP ADT server
|
|
4
4
|
*/
|
|
5
5
|
export { AuthBroker } from './AuthBroker';
|
|
6
|
-
export type {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
6
|
+
export type { IAuthorizationConfig, IConnectionConfig, IServiceKeyStore, ISessionStore } from './stores/interfaces';
|
|
7
|
+
export type { IConfig } from './types';
|
|
8
|
+
export type { ITokenProvider, TokenProviderOptions, TokenProviderResult } from './providers';
|
|
9
|
+
export type { Logger } from '@mcp-abap-adt/logger';
|
|
10
10
|
//# 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;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,YAAY,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpH,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,YAAY,EAAE,cAAc,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAE7F,YAAY,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,12 +4,10 @@
|
|
|
4
4
|
* JWT authentication broker for MCP ABAP ADT server
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.
|
|
7
|
+
exports.AuthBroker = void 0;
|
|
8
8
|
var AuthBroker_1 = require("./AuthBroker");
|
|
9
9
|
Object.defineProperty(exports, "AuthBroker", { enumerable: true, get: function () { return AuthBroker_1.AuthBroker; } });
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Object.defineProperty(exports, "FileServiceKeyStore", { enumerable: true, get: function () { return stores_1.FileServiceKeyStore; } });
|
|
15
|
-
Object.defineProperty(exports, "FileSessionStore", { enumerable: true, get: function () { return stores_1.FileSessionStore; } });
|
|
10
|
+
// Store and provider implementations are in separate packages:
|
|
11
|
+
// - @mcp-abap-adt/auth-stores-btp - BTP and ABAP stores
|
|
12
|
+
// - @mcp-abap-adt/auth-stores-xsuaa - XSUAA stores
|
|
13
|
+
// - @mcp-abap-adt/auth-providers - XSUAA and BTP token providers
|