@mcp-abap-adt/auth-broker 0.1.5 → 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 +229 -0
- package/README.md +172 -15
- package/bin/generate-env-from-service-key.ts +128 -0
- package/dist/AuthBroker.d.ts +19 -29
- package/dist/AuthBroker.d.ts.map +1 -1
- package/dist/AuthBroker.js +86 -132
- 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 -8
- 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 -5
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/index.js +4 -8
- package/dist/stores/interfaces.d.ts +88 -22
- 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 -136
- 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/stores/SafeSessionStore.d.ts +0 -35
- package/dist/stores/SafeSessionStore.d.ts.map +0 -1
- package/dist/stores/SafeSessionStore.js +0 -42
- 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,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Main AuthBroker class for managing JWT tokens based on destinations
|
|
3
3
|
*/
|
|
4
|
-
import { Logger } from '
|
|
5
|
-
import { IServiceKeyStore, ISessionStore } from './stores/interfaces';
|
|
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
|
*/
|
|
@@ -11,19 +12,22 @@ export declare class AuthBroker {
|
|
|
11
12
|
private logger;
|
|
12
13
|
private serviceKeyStore;
|
|
13
14
|
private sessionStore;
|
|
15
|
+
private tokenProvider;
|
|
14
16
|
/**
|
|
15
17
|
* Create a new AuthBroker instance
|
|
16
|
-
* @param stores Object with
|
|
17
|
-
* - serviceKeyStore: Store for service keys
|
|
18
|
-
* - sessionStore: Store for session data
|
|
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
|
|
19
22
|
* @param browser Optional browser name for authentication (chrome, edge, firefox, system, none).
|
|
20
23
|
* Default: 'system' (system default browser).
|
|
21
24
|
* Use 'none' to print URL instead of opening browser.
|
|
22
25
|
* @param logger Optional logger instance. If not provided, uses default logger.
|
|
23
26
|
*/
|
|
24
|
-
constructor(stores
|
|
25
|
-
serviceKeyStore
|
|
26
|
-
sessionStore
|
|
27
|
+
constructor(stores: {
|
|
28
|
+
serviceKeyStore: IServiceKeyStore;
|
|
29
|
+
sessionStore: ISessionStore;
|
|
30
|
+
tokenProvider: ITokenProvider;
|
|
27
31
|
}, browser?: string, logger?: Logger);
|
|
28
32
|
/**
|
|
29
33
|
* Get authentication token for destination.
|
|
@@ -41,30 +45,16 @@ export declare class AuthBroker {
|
|
|
41
45
|
*/
|
|
42
46
|
refreshToken(destination: string): Promise<string>;
|
|
43
47
|
/**
|
|
44
|
-
*
|
|
45
|
-
* @private
|
|
46
|
-
*/
|
|
47
|
-
private refreshTokenInternal;
|
|
48
|
-
/**
|
|
49
|
-
* Get SAP URL for destination.
|
|
50
|
-
* Tries to load from session store first, then from service key store.
|
|
48
|
+
* Get authorization configuration for destination
|
|
51
49
|
* @param destination Destination name (e.g., "TRIAL")
|
|
52
|
-
* @returns Promise that resolves to
|
|
53
|
-
*/
|
|
54
|
-
getSapUrl(destination: string): Promise<string | undefined>;
|
|
55
|
-
/**
|
|
56
|
-
* Clear cached token for specific destination
|
|
57
|
-
* @param destination Destination name
|
|
50
|
+
* @returns Promise that resolves to IAuthorizationConfig or null if not found
|
|
58
51
|
*/
|
|
59
|
-
|
|
52
|
+
getAuthorizationConfig(destination: string): Promise<IAuthorizationConfig | null>;
|
|
60
53
|
/**
|
|
61
|
-
*
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Get search paths for error messages (from file stores if available)
|
|
66
|
-
* @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
|
|
67
57
|
*/
|
|
68
|
-
|
|
58
|
+
getConnectionConfig(destination: string): Promise<IConnectionConfig | null>;
|
|
69
59
|
}
|
|
70
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,12 +4,7 @@
|
|
|
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 logger_1 = require("./logger");
|
|
12
|
-
const stores_1 = require("./stores");
|
|
7
|
+
const logger_1 = require("@mcp-abap-adt/logger");
|
|
13
8
|
/**
|
|
14
9
|
* AuthBroker manages JWT authentication tokens for destinations
|
|
15
10
|
*/
|
|
@@ -18,19 +13,22 @@ class AuthBroker {
|
|
|
18
13
|
logger;
|
|
19
14
|
serviceKeyStore;
|
|
20
15
|
sessionStore;
|
|
16
|
+
tokenProvider;
|
|
21
17
|
/**
|
|
22
18
|
* Create a new AuthBroker instance
|
|
23
|
-
* @param stores Object with
|
|
24
|
-
* - serviceKeyStore: Store for service keys
|
|
25
|
-
* - sessionStore: Store for session data
|
|
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
|
|
26
23
|
* @param browser Optional browser name for authentication (chrome, edge, firefox, system, none).
|
|
27
24
|
* Default: 'system' (system default browser).
|
|
28
25
|
* Use 'none' to print URL instead of opening browser.
|
|
29
26
|
* @param logger Optional logger instance. If not provided, uses default logger.
|
|
30
27
|
*/
|
|
31
28
|
constructor(stores, browser, logger) {
|
|
32
|
-
this.serviceKeyStore = stores
|
|
33
|
-
this.sessionStore = stores
|
|
29
|
+
this.serviceKeyStore = stores.serviceKeyStore;
|
|
30
|
+
this.sessionStore = stores.sessionStore;
|
|
31
|
+
this.tokenProvider = stores.tokenProvider;
|
|
34
32
|
this.browser = browser || 'system';
|
|
35
33
|
this.logger = logger || logger_1.defaultLogger;
|
|
36
34
|
}
|
|
@@ -42,47 +40,51 @@ class AuthBroker {
|
|
|
42
40
|
* @throws Error if neither session data nor service key found
|
|
43
41
|
*/
|
|
44
42
|
async getToken(destination) {
|
|
45
|
-
//
|
|
46
|
-
const
|
|
47
|
-
if (
|
|
48
|
-
// Validate
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
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);
|
|
52
49
|
if (isValid) {
|
|
53
|
-
return
|
|
50
|
+
return connConfig.authorizationToken;
|
|
54
51
|
}
|
|
55
|
-
// Token expired, remove from cache
|
|
56
52
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (envConfig && envConfig.jwtToken) {
|
|
61
|
-
// Validate token
|
|
62
|
-
const isValid = await (0, tokenValidator_1.validateToken)(envConfig.jwtToken, envConfig.sapUrl);
|
|
63
|
-
if (isValid) {
|
|
64
|
-
(0, cache_1.setCachedToken)(destination, envConfig.jwtToken);
|
|
65
|
-
return envConfig.jwtToken;
|
|
53
|
+
else {
|
|
54
|
+
// No service URL or provider doesn't support validation - just return token
|
|
55
|
+
return connConfig.authorizationToken;
|
|
66
56
|
}
|
|
67
57
|
}
|
|
68
|
-
// Token not found or expired, check if we have service key
|
|
58
|
+
// Token not found or expired, check if we have service key
|
|
69
59
|
const serviceKey = await this.serviceKeyStore.getServiceKey(destination);
|
|
70
60
|
if (!serviceKey) {
|
|
71
|
-
// No service key and no valid token
|
|
72
|
-
const searchPaths = this.getSearchPathsForError();
|
|
73
|
-
const searchedPaths = searchPaths.length > 0
|
|
74
|
-
? `\nSearched in:\n${searchPaths.map(p => ` - ${p}`).join('\n')}`
|
|
75
|
-
: '';
|
|
61
|
+
// No service key and no valid token
|
|
76
62
|
throw new Error(`No authentication found for destination "${destination}". ` +
|
|
77
|
-
`
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
+
});
|
|
81
86
|
}
|
|
82
|
-
|
|
83
|
-
const newToken = await this.refreshTokenInternal(destination, serviceKey, envConfig);
|
|
84
|
-
(0, cache_1.setCachedToken)(destination, newToken);
|
|
85
|
-
return newToken;
|
|
87
|
+
return tokenResult.connectionConfig.authorizationToken;
|
|
86
88
|
}
|
|
87
89
|
/**
|
|
88
90
|
* Force refresh token for destination using service key.
|
|
@@ -94,107 +96,59 @@ class AuthBroker {
|
|
|
94
96
|
// Load service key
|
|
95
97
|
const serviceKey = await this.serviceKeyStore.getServiceKey(destination);
|
|
96
98
|
if (!serviceKey) {
|
|
97
|
-
|
|
98
|
-
const searchedPaths = searchPaths.length > 0
|
|
99
|
-
? `\nSearched in:\n${searchPaths.map(p => ` - ${p}`).join('\n')}`
|
|
100
|
-
: '';
|
|
101
|
-
throw new Error(`Service key file not found for destination "${destination}".\n` +
|
|
102
|
-
`Please create file: ${destination}.json${searchedPaths}`);
|
|
99
|
+
throw new Error(`Service key not found for destination "${destination}".`);
|
|
103
100
|
}
|
|
104
|
-
//
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Internal refresh token implementation
|
|
110
|
-
* @private
|
|
111
|
-
*/
|
|
112
|
-
async refreshTokenInternal(destination, serviceKey, envConfig) {
|
|
113
|
-
// Extract UAA configuration
|
|
114
|
-
const { url: uaaUrl, clientid: clientId, clientsecret: clientSecret } = serviceKey.uaa;
|
|
115
|
-
if (!uaaUrl || !clientId || !clientSecret) {
|
|
116
|
-
throw new Error(`Invalid service key for destination "${destination}". ` +
|
|
117
|
-
`Missing required UAA fields: url, clientid, clientsecret`);
|
|
118
|
-
}
|
|
119
|
-
// Validate SAP URL early (before starting browser auth or refresh)
|
|
120
|
-
const sapUrl = serviceKey.url || serviceKey.abap?.url || serviceKey.sap_url;
|
|
121
|
-
if (!sapUrl) {
|
|
122
|
-
throw new Error(`Service key for destination "${destination}" does not contain SAP URL. ` +
|
|
123
|
-
`Expected field: url, abap.url, or sap_url`);
|
|
124
|
-
}
|
|
125
|
-
// Try to load existing refresh token from session store
|
|
126
|
-
let refreshTokenValue = envConfig?.refreshToken;
|
|
127
|
-
let result;
|
|
128
|
-
// If no refresh token, start browser authentication flow
|
|
129
|
-
if (!refreshTokenValue) {
|
|
130
|
-
this.logger.debug(`No refresh token found for destination "${destination}". Starting browser authentication...`);
|
|
131
|
-
result = await (0, browserAuth_1.startBrowserAuth)(serviceKey, this.browser || 'system', this.logger);
|
|
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`);
|
|
132
105
|
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
jwtToken: result.accessToken,
|
|
141
|
-
refreshToken: result.refreshToken || refreshTokenValue,
|
|
142
|
-
uaaUrl,
|
|
143
|
-
uaaClientId: clientId,
|
|
144
|
-
uaaClientSecret: clientSecret,
|
|
145
|
-
sapClient: envConfig?.sapClient,
|
|
146
|
-
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,
|
|
147
113
|
});
|
|
148
|
-
// Update
|
|
149
|
-
|
|
150
|
-
|
|
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;
|
|
151
124
|
}
|
|
152
125
|
/**
|
|
153
|
-
* Get
|
|
154
|
-
* Tries to load from session store first, then from service key store.
|
|
126
|
+
* Get authorization configuration for destination
|
|
155
127
|
* @param destination Destination name (e.g., "TRIAL")
|
|
156
|
-
* @returns Promise that resolves to
|
|
128
|
+
* @returns Promise that resolves to IAuthorizationConfig or null if not found
|
|
157
129
|
*/
|
|
158
|
-
async
|
|
159
|
-
// Try
|
|
160
|
-
const
|
|
161
|
-
if (
|
|
162
|
-
return
|
|
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;
|
|
163
135
|
}
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
if (serviceKey) {
|
|
167
|
-
return serviceKey.url || serviceKey.abap?.url || serviceKey.sap_url;
|
|
168
|
-
}
|
|
169
|
-
return undefined;
|
|
170
|
-
}
|
|
171
|
-
/**
|
|
172
|
-
* Clear cached token for specific destination
|
|
173
|
-
* @param destination Destination name
|
|
174
|
-
*/
|
|
175
|
-
clearCache(destination) {
|
|
176
|
-
(0, cache_1.clearCache)(destination);
|
|
136
|
+
// Fall back to service key store (has UAA credentials)
|
|
137
|
+
return await this.serviceKeyStore.getAuthorizationConfig(destination);
|
|
177
138
|
}
|
|
178
139
|
/**
|
|
179
|
-
*
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
(0, cache_1.clearAllCache)();
|
|
183
|
-
}
|
|
184
|
-
/**
|
|
185
|
-
* Get search paths for error messages (from file stores if available)
|
|
186
|
-
* @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
|
|
187
143
|
*/
|
|
188
|
-
|
|
189
|
-
// Try
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (this.sessionStore instanceof stores_1.FileSessionStore) {
|
|
194
|
-
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;
|
|
195
149
|
}
|
|
196
|
-
//
|
|
197
|
-
return
|
|
150
|
+
// Fall back to service key store (has URLs but no tokens)
|
|
151
|
+
return await this.serviceKeyStore.getConnectionConfig(destination);
|
|
198
152
|
}
|
|
199
153
|
}
|
|
200
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,13 +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; } });
|
|
16
|
-
Object.defineProperty(exports, "SafeSessionStore", { enumerable: true, get: function () { return stores_1.SafeSessionStore; } });
|
|
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
|