@mcp-abap-adt/auth-broker 0.1.6 → 0.1.8
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 +34 -1
- package/README.md +111 -1
- package/dist/AuthBroker.d.ts +28 -2
- package/dist/AuthBroker.d.ts.map +1 -1
- package/dist/AuthBroker.js +113 -19
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/providers/ITokenProvider.d.ts +4 -40
- package/dist/providers/ITokenProvider.d.ts.map +1 -1
- package/dist/stores/interfaces.d.ts +4 -112
- package/dist/stores/interfaces.d.ts.map +1 -1
- package/dist/stores/interfaces.js +2 -1
- package/dist/types.d.ts +3 -8
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -9,7 +9,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
Thank you to all contributors! See [CONTRIBUTORS.md](CONTRIBUTORS.md) for the complete list.
|
|
11
11
|
|
|
12
|
-
## [
|
|
12
|
+
## [Unreleased]
|
|
13
|
+
|
|
14
|
+
## [0.1.8] - 2024-12-04
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- **Interfaces Package Integration**: Migrated to use `@mcp-abap-adt/interfaces` package for all interface definitions
|
|
18
|
+
- All interfaces now imported from shared package
|
|
19
|
+
- Backward compatibility maintained with type aliases
|
|
20
|
+
- Dependency on `@mcp-abap-adt/interfaces@^0.1.0` added
|
|
21
|
+
- Updated `@mcp-abap-adt/connection` dependency to `^0.1.14`
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
- **Interface Renaming**: Interfaces renamed to follow `I` prefix convention:
|
|
25
|
+
- `TokenProviderResult` → `ITokenProviderResult` (type alias for backward compatibility)
|
|
26
|
+
- `TokenProviderOptions` → `ITokenProviderOptions` (type alias for backward compatibility)
|
|
27
|
+
- Old names still work via type aliases for backward compatibility
|
|
28
|
+
- **AuthType Export**: `AuthType` now exported from `@mcp-abap-adt/interfaces` instead of local definition
|
|
29
|
+
|
|
30
|
+
## [0.1.7] - 2025-12-04
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- **getToken() Fallback Chain** - Improved authentication reliability with multi-step fallback chain
|
|
34
|
+
- **Step 1**: Check if session exists and token is valid (returns immediately if valid)
|
|
35
|
+
- **Step 2**: Verify service key exists (throws error if missing)
|
|
36
|
+
- **Step 3**: Try refresh token authentication (via tokenProvider) if refresh token is available
|
|
37
|
+
- **Step 4**: Try UAA client_credentials authentication (via tokenProvider) if refresh token missing or failed
|
|
38
|
+
- **Step 5**: Try browser authentication (via tokenProvider) if UAA failed or parameters missing
|
|
39
|
+
- **Step 6**: Throw comprehensive error if all methods failed
|
|
40
|
+
- All authentication attempts use `ITokenProvider` interface (no direct implementation imports)
|
|
41
|
+
- Token validation is performed only when checking existing session (step 1)
|
|
42
|
+
- Tokens obtained through refresh/UAA/browser authentication are not validated before being saved
|
|
43
|
+
- Improved error messages with details about which authentication methods failed
|
|
44
|
+
|
|
45
|
+
## [0.1.6] - 2025-12-04
|
|
13
46
|
|
|
14
47
|
### Changed
|
|
15
48
|
- **Package Split** - Extracted store and provider implementations into separate packages
|
package/README.md
CHANGED
|
@@ -157,6 +157,108 @@ This package supports two types of BTP authentication:
|
|
|
157
157
|
- **ABAP URL**: Required, from service key or YAML configuration
|
|
158
158
|
- **Use Case**: Accessing ABAP systems in BTP with full permissions
|
|
159
159
|
|
|
160
|
+
## Responsibilities and Design Principles
|
|
161
|
+
|
|
162
|
+
### Core Development Principle
|
|
163
|
+
|
|
164
|
+
**Interface-Only Communication**: This package follows a fundamental development principle: **all interactions with external dependencies happen ONLY through interfaces**. The code knows **NOTHING beyond what is defined in the interfaces**.
|
|
165
|
+
|
|
166
|
+
This means:
|
|
167
|
+
- Does not know about concrete implementation classes (e.g., `AbapSessionStore`, `BtpTokenProvider`)
|
|
168
|
+
- Does not know about internal data structures or methods not defined in interfaces
|
|
169
|
+
- Does not make assumptions about implementation behavior beyond interface contracts
|
|
170
|
+
- Does not access properties or methods not explicitly defined in interfaces
|
|
171
|
+
|
|
172
|
+
This principle ensures:
|
|
173
|
+
- **Loose coupling**: `AuthBroker` is decoupled from concrete implementations
|
|
174
|
+
- **Flexibility**: New implementations can be added without modifying `AuthBroker`
|
|
175
|
+
- **Testability**: Easy to mock dependencies for testing
|
|
176
|
+
- **Maintainability**: Changes to implementations don't affect `AuthBroker`
|
|
177
|
+
|
|
178
|
+
### Package Responsibilities
|
|
179
|
+
|
|
180
|
+
The `@mcp-abap-adt/auth-broker` package defines **interfaces** and provides **orchestration logic** for authentication. It does **not** implement concrete storage or token acquisition mechanisms - these are provided by separate packages (`@mcp-abap-adt/auth-stores`, `@mcp-abap-adt/auth-providers`).
|
|
181
|
+
|
|
182
|
+
#### What AuthBroker Does
|
|
183
|
+
|
|
184
|
+
- **Orchestrates authentication flows**: Coordinates token retrieval, validation, and refresh using provided stores and providers
|
|
185
|
+
- **Manages token lifecycle**: Handles token caching, validation, and automatic refresh
|
|
186
|
+
- **Works with interfaces only**: Uses `IServiceKeyStore`, `ISessionStore`, and `ITokenProvider` interfaces without knowing concrete implementations
|
|
187
|
+
- **Delegates to providers**: Calls `tokenProvider.getConnectionConfig()` to obtain tokens and connection configuration
|
|
188
|
+
- **Delegates to stores**: Uses `sessionStore.setConnectionConfig()` to save tokens and connection configuration
|
|
189
|
+
|
|
190
|
+
#### What AuthBroker Does NOT Do
|
|
191
|
+
|
|
192
|
+
- **Does NOT know about `serviceUrl`**: `AuthBroker` does not know whether a specific `ISessionStore` implementation requires `serviceUrl` or not. It simply passes the `IConnectionConfig` returned by `tokenProvider` to `sessionStore.setConnectionConfig()`
|
|
193
|
+
- **Does NOT merge configurations**: `AuthBroker` does not merge `serviceUrl` from service keys with connection config from token providers. This is the responsibility of the consumer or the session store implementation
|
|
194
|
+
- **Does NOT implement storage**: File I/O, parsing, and storage logic are handled by concrete store implementations from `@mcp-abap-adt/auth-stores`
|
|
195
|
+
- **Does NOT implement token acquisition**: OAuth2 flows, refresh token logic, and client credentials are handled by concrete provider implementations from `@mcp-abap-adt/auth-providers`
|
|
196
|
+
|
|
197
|
+
### Consumer Responsibilities
|
|
198
|
+
|
|
199
|
+
The **consumer** (application using `AuthBroker`) is responsible for:
|
|
200
|
+
|
|
201
|
+
1. **Selecting appropriate implementations**: Choose the correct `IServiceKeyStore`, `ISessionStore`, and `ITokenProvider` implementations based on the use case:
|
|
202
|
+
- **ABAP systems**: Use `AbapServiceKeyStore`, `AbapSessionStore` (or `SafeAbapSessionStore`), and `BtpTokenProvider`
|
|
203
|
+
- **BTP systems**: Use `AbapServiceKeyStore`, `BtpSessionStore` (or `SafeBtpSessionStore`), and `BtpTokenProvider`
|
|
204
|
+
- **XSUAA services**: Use `XsuaaServiceKeyStore`, `XsuaaSessionStore` (or `SafeXsuaaSessionStore`), and `XsuaaTokenProvider`
|
|
205
|
+
|
|
206
|
+
2. **Ensuring complete configuration**: If a session store requires `serviceUrl` (e.g., `AbapSessionStore` requires `sapUrl`), the consumer must ensure that:
|
|
207
|
+
- The session is created with `serviceUrl` before calling `AuthBroker.getToken()`, OR
|
|
208
|
+
- The session store implementation handles `serviceUrl` retrieval internally (e.g., from `serviceKeyStore`)
|
|
209
|
+
|
|
210
|
+
3. **Understanding store requirements**: Different session store implementations have different requirements:
|
|
211
|
+
- `AbapSessionStore`: Requires `sapUrl` (maps to `serviceUrl` in `IConnectionConfig`)
|
|
212
|
+
- `BtpSessionStore`: Does not require `serviceUrl` (uses `mcpUrl` instead)
|
|
213
|
+
- `XsuaaSessionStore`: Does not require `serviceUrl` (MCP URL is optional)
|
|
214
|
+
|
|
215
|
+
### Store Responsibilities
|
|
216
|
+
|
|
217
|
+
Concrete `ISessionStore` implementations are responsible for:
|
|
218
|
+
|
|
219
|
+
- **Handling their own data format**: Each store knows its internal data format (e.g., `AbapSessionData`, `BtpBaseSessionData`)
|
|
220
|
+
- **Converting between formats**: Converting between `IConfig`/`IConnectionConfig` and internal storage format
|
|
221
|
+
- **Managing required fields**: If a store requires `serviceUrl` (e.g., `AbapSessionStore`), it should:
|
|
222
|
+
- Retrieve it from `serviceKeyStore` if not provided in `IConnectionConfig`, OR
|
|
223
|
+
- Use existing value from current session if available, OR
|
|
224
|
+
- Throw an error if neither is available (depending on implementation)
|
|
225
|
+
|
|
226
|
+
### Provider Responsibilities
|
|
227
|
+
|
|
228
|
+
Concrete `ITokenProvider` implementations are responsible for:
|
|
229
|
+
|
|
230
|
+
- **Obtaining tokens**: Using OAuth2 flows, refresh tokens, or client credentials to obtain JWT tokens
|
|
231
|
+
- **Returning connection config**: Returning `IConnectionConfig` with `authorizationToken` and optionally `serviceUrl` (if known)
|
|
232
|
+
- **Not returning `serviceUrl` if unknown**: Providers like `BtpTokenProvider` may not return `serviceUrl` because they only handle token acquisition, not connection configuration
|
|
233
|
+
|
|
234
|
+
### Design Principles
|
|
235
|
+
|
|
236
|
+
1. **Interface-Only Communication** (Core Principle): All interactions with external dependencies happen **ONLY through interfaces**. The code knows **NOTHING beyond what is defined in the interfaces** (see [Core Development Principle](#core-development-principle) above)
|
|
237
|
+
2. **Dependency Inversion Principle (DIP)**: `AuthBroker` depends on abstractions (`IServiceKeyStore`, `ISessionStore`, `ITokenProvider`), not concrete implementations
|
|
238
|
+
3. **Single Responsibility**: Each component has a single, well-defined responsibility:
|
|
239
|
+
- `AuthBroker`: Orchestration and token lifecycle management
|
|
240
|
+
- `ISessionStore`: Session data storage and retrieval
|
|
241
|
+
- `ITokenProvider`: Token acquisition
|
|
242
|
+
- `IServiceKeyStore`: Service key storage and retrieval
|
|
243
|
+
4. **Interface Segregation**: Interfaces are focused and minimal, containing only what's necessary for their specific purpose
|
|
244
|
+
5. **Open/Closed Principle**: New store and provider implementations can be added without modifying `AuthBroker`
|
|
245
|
+
|
|
246
|
+
### Example: Why AuthBroker Doesn't Handle `serviceUrl`
|
|
247
|
+
|
|
248
|
+
Consider this scenario:
|
|
249
|
+
- `BtpTokenProvider.getConnectionConfig()` returns `IConnectionConfig` with `authorizationToken` but **without** `serviceUrl` (because it only handles token acquisition)
|
|
250
|
+
- `AbapSessionStore.setConnectionConfig()` requires `sapUrl` (which maps to `serviceUrl`)
|
|
251
|
+
|
|
252
|
+
If `AuthBroker` tried to merge `serviceUrl` from `serviceKeyStore`, it would:
|
|
253
|
+
1. Violate the DIP by knowing about specific store requirements
|
|
254
|
+
2. Break the abstraction - `AuthBroker` shouldn't know that `AbapSessionStore` needs `serviceUrl`
|
|
255
|
+
3. Create coupling between `AuthBroker` and concrete implementations
|
|
256
|
+
|
|
257
|
+
Instead, the consumer or `AbapSessionStore` itself should handle this:
|
|
258
|
+
- **Option 1**: Consumer retrieves `serviceUrl` from `serviceKeyStore` and ensures it's in the session before calling `AuthBroker.getToken()`
|
|
259
|
+
- **Option 2**: `AbapSessionStore.setConnectionConfig()` retrieves `serviceUrl` from `serviceKeyStore` internally if not provided
|
|
260
|
+
- **Option 3**: `AbapSessionStore.setConnectionConfig()` uses existing `sapUrl` from current session if available
|
|
261
|
+
|
|
160
262
|
## API
|
|
161
263
|
|
|
162
264
|
### `AuthBroker`
|
|
@@ -191,7 +293,15 @@ new AuthBroker(
|
|
|
191
293
|
|
|
192
294
|
##### `getToken(destination: string): Promise<string>`
|
|
193
295
|
|
|
194
|
-
Gets authentication token for destination. Tries to load from
|
|
296
|
+
Gets authentication token for destination. Tries to load from session store, validates it, and refreshes if needed using a fallback chain:
|
|
297
|
+
|
|
298
|
+
1. **Check session**: Load token from session store and validate it
|
|
299
|
+
2. **Try refresh token**: If refresh token is available, attempt to refresh using it (via tokenProvider)
|
|
300
|
+
3. **Try UAA (client_credentials)**: Attempt to get token using UAA credentials (via tokenProvider)
|
|
301
|
+
4. **Try browser authentication**: Attempt browser-based OAuth2 flow using service key (via tokenProvider)
|
|
302
|
+
5. **Throw error**: If all authentication methods failed
|
|
303
|
+
|
|
304
|
+
**Note**: Token validation is performed only when checking existing session. Tokens obtained through refresh/UAA/browser authentication are not validated before being saved.
|
|
195
305
|
|
|
196
306
|
##### `refreshToken(destination: string): Promise<string>`
|
|
197
307
|
|
package/dist/AuthBroker.d.ts
CHANGED
|
@@ -31,10 +31,36 @@ export declare class AuthBroker {
|
|
|
31
31
|
}, browser?: string, logger?: Logger);
|
|
32
32
|
/**
|
|
33
33
|
* Get authentication token for destination.
|
|
34
|
-
* Tries to load from session store, validates it, and refreshes if needed.
|
|
34
|
+
* Tries to load from session store, validates it, and refreshes if needed using a fallback chain.
|
|
35
|
+
*
|
|
36
|
+
* **Fallback Chain:**
|
|
37
|
+
* 1. **Check session**: Load token from session store and validate it
|
|
38
|
+
* - If token is valid, return it immediately
|
|
39
|
+
* - If token is invalid or missing, continue to next step
|
|
40
|
+
*
|
|
41
|
+
* 2. **Check service key**: Verify that service key exists
|
|
42
|
+
* - If no service key found, throw error
|
|
43
|
+
*
|
|
44
|
+
* 3. **Try refresh token**: If refresh token is available in session, attempt to refresh using it (via tokenProvider)
|
|
45
|
+
* - If successful, save new token to session and return it
|
|
46
|
+
* - If failed, continue to next step
|
|
47
|
+
*
|
|
48
|
+
* 4. **Try UAA (client_credentials)**: Attempt to get token using UAA credentials (via tokenProvider)
|
|
49
|
+
* - If UAA parameters are available and authentication succeeds, save token to session and return it
|
|
50
|
+
* - If failed or parameters missing, continue to next step
|
|
51
|
+
*
|
|
52
|
+
* 5. **Try browser authentication**: Attempt browser-based OAuth2 flow using service key (via tokenProvider)
|
|
53
|
+
* - If successful, save token and refresh token to session and return it
|
|
54
|
+
* - If failed, continue to next step
|
|
55
|
+
*
|
|
56
|
+
* 6. **Throw error**: If all authentication methods failed, throw comprehensive error with details
|
|
57
|
+
*
|
|
58
|
+
* **Note**: Token validation is performed only when checking existing session (step 1).
|
|
59
|
+
* Tokens obtained through refresh/UAA/browser authentication are not validated before being saved.
|
|
60
|
+
*
|
|
35
61
|
* @param destination Destination name (e.g., "TRIAL")
|
|
36
62
|
* @returns Promise that resolves to JWT token string
|
|
37
|
-
* @throws Error if neither session data nor service key found
|
|
63
|
+
* @throws Error if neither session data nor service key found, or if all authentication methods failed
|
|
38
64
|
*/
|
|
39
65
|
getToken(destination: string): Promise<string>;
|
|
40
66
|
/**
|
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;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
|
|
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAmIpD;;;;;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
|
@@ -34,13 +34,39 @@ class AuthBroker {
|
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Get authentication token for destination.
|
|
37
|
-
* Tries to load from session store, validates it, and refreshes if needed.
|
|
37
|
+
* Tries to load from session store, validates it, and refreshes if needed using a fallback chain.
|
|
38
|
+
*
|
|
39
|
+
* **Fallback Chain:**
|
|
40
|
+
* 1. **Check session**: Load token from session store and validate it
|
|
41
|
+
* - If token is valid, return it immediately
|
|
42
|
+
* - If token is invalid or missing, continue to next step
|
|
43
|
+
*
|
|
44
|
+
* 2. **Check service key**: Verify that service key exists
|
|
45
|
+
* - If no service key found, throw error
|
|
46
|
+
*
|
|
47
|
+
* 3. **Try refresh token**: If refresh token is available in session, attempt to refresh using it (via tokenProvider)
|
|
48
|
+
* - If successful, save new token to session and return it
|
|
49
|
+
* - If failed, continue to next step
|
|
50
|
+
*
|
|
51
|
+
* 4. **Try UAA (client_credentials)**: Attempt to get token using UAA credentials (via tokenProvider)
|
|
52
|
+
* - If UAA parameters are available and authentication succeeds, save token to session and return it
|
|
53
|
+
* - If failed or parameters missing, continue to next step
|
|
54
|
+
*
|
|
55
|
+
* 5. **Try browser authentication**: Attempt browser-based OAuth2 flow using service key (via tokenProvider)
|
|
56
|
+
* - If successful, save token and refresh token to session and return it
|
|
57
|
+
* - If failed, continue to next step
|
|
58
|
+
*
|
|
59
|
+
* 6. **Throw error**: If all authentication methods failed, throw comprehensive error with details
|
|
60
|
+
*
|
|
61
|
+
* **Note**: Token validation is performed only when checking existing session (step 1).
|
|
62
|
+
* Tokens obtained through refresh/UAA/browser authentication are not validated before being saved.
|
|
63
|
+
*
|
|
38
64
|
* @param destination Destination name (e.g., "TRIAL")
|
|
39
65
|
* @returns Promise that resolves to JWT token string
|
|
40
|
-
* @throws Error if neither session data nor service key found
|
|
66
|
+
* @throws Error if neither session data nor service key found, or if all authentication methods failed
|
|
41
67
|
*/
|
|
42
68
|
async getToken(destination) {
|
|
43
|
-
//
|
|
69
|
+
// Step 1: Check if session exists and token is valid
|
|
44
70
|
const connConfig = await this.sessionStore.getConnectionConfig(destination);
|
|
45
71
|
if (connConfig?.authorizationToken) {
|
|
46
72
|
// Validate token if provider supports validation and we have service URL
|
|
@@ -55,7 +81,7 @@ class AuthBroker {
|
|
|
55
81
|
return connConfig.authorizationToken;
|
|
56
82
|
}
|
|
57
83
|
}
|
|
58
|
-
//
|
|
84
|
+
// Step 2: No valid session, check if we have service key
|
|
59
85
|
const serviceKey = await this.serviceKeyStore.getServiceKey(destination);
|
|
60
86
|
if (!serviceKey) {
|
|
61
87
|
// No service key and no valid token
|
|
@@ -67,24 +93,92 @@ class AuthBroker {
|
|
|
67
93
|
if (!authConfig) {
|
|
68
94
|
throw new Error(`Service key for destination "${destination}" does not contain UAA credentials`);
|
|
69
95
|
}
|
|
70
|
-
// Get refresh token from session
|
|
96
|
+
// Get refresh token from session (if exists)
|
|
71
97
|
const sessionAuthConfig = await this.sessionStore.getAuthorizationConfig(destination);
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
98
|
+
const refreshToken = sessionAuthConfig?.refreshToken || authConfig.refreshToken;
|
|
99
|
+
let tokenResult;
|
|
100
|
+
let lastError = null;
|
|
101
|
+
// Step 3: Try to refresh using refresh token (if available) via tokenProvider
|
|
102
|
+
if (refreshToken) {
|
|
103
|
+
try {
|
|
104
|
+
this.logger.debug(`Attempting to refresh token using refresh token for destination "${destination}"...`);
|
|
105
|
+
const authConfigWithRefresh = { ...authConfig, refreshToken };
|
|
106
|
+
tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithRefresh, {
|
|
107
|
+
browser: this.browser,
|
|
108
|
+
logger: this.logger,
|
|
109
|
+
});
|
|
110
|
+
this.logger.debug(`Token refreshed successfully using refresh token for destination "${destination}"`);
|
|
111
|
+
// Update session with new token
|
|
112
|
+
await this.sessionStore.setConnectionConfig(destination, tokenResult.connectionConfig);
|
|
113
|
+
if (tokenResult.refreshToken) {
|
|
114
|
+
await this.sessionStore.setAuthorizationConfig(destination, {
|
|
115
|
+
...authConfig,
|
|
116
|
+
refreshToken: tokenResult.refreshToken,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return tokenResult.connectionConfig.authorizationToken;
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
lastError = error;
|
|
123
|
+
this.logger.debug(`Token refresh failed for destination "${destination}": ${error.message}. Trying without refresh token...`);
|
|
124
|
+
// Continue to next step
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Step 4: Try UAA (client_credentials) via tokenProvider (without refresh token)
|
|
128
|
+
// TokenProvider should try client_credentials if refresh token is not provided
|
|
129
|
+
try {
|
|
130
|
+
this.logger.debug(`Attempting to get token using UAA (client_credentials) for destination "${destination}"...`);
|
|
131
|
+
const authConfigWithoutRefresh = { ...authConfig, refreshToken: undefined };
|
|
132
|
+
tokenResult = await this.tokenProvider.getConnectionConfig(authConfigWithoutRefresh, {
|
|
133
|
+
browser: this.browser,
|
|
134
|
+
logger: this.logger,
|
|
135
|
+
});
|
|
136
|
+
this.logger.debug(`Token obtained successfully using UAA for destination "${destination}"`);
|
|
137
|
+
// Update session with new token
|
|
138
|
+
await this.sessionStore.setConnectionConfig(destination, tokenResult.connectionConfig);
|
|
139
|
+
if (tokenResult.refreshToken) {
|
|
140
|
+
await this.sessionStore.setAuthorizationConfig(destination, {
|
|
141
|
+
...authConfig,
|
|
142
|
+
refreshToken: tokenResult.refreshToken,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
return tokenResult.connectionConfig.authorizationToken;
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
lastError = error;
|
|
149
|
+
this.logger.debug(`UAA authentication failed for destination "${destination}": ${error.message}. Trying browser authentication...`);
|
|
150
|
+
// Continue to next step
|
|
151
|
+
}
|
|
152
|
+
// Step 5: Try browser authentication via tokenProvider (should be last resort)
|
|
153
|
+
// TokenProvider should use browser auth if refresh token and client_credentials don't work
|
|
154
|
+
try {
|
|
155
|
+
this.logger.debug(`Starting browser authentication flow for destination "${destination}"...`);
|
|
156
|
+
const authConfigForBrowser = { ...authConfig, refreshToken: undefined };
|
|
157
|
+
tokenResult = await this.tokenProvider.getConnectionConfig(authConfigForBrowser, {
|
|
158
|
+
browser: this.browser,
|
|
159
|
+
logger: this.logger,
|
|
85
160
|
});
|
|
161
|
+
this.logger.debug(`Token obtained successfully using browser authentication for destination "${destination}"`);
|
|
162
|
+
// Update session with new token
|
|
163
|
+
await this.sessionStore.setConnectionConfig(destination, tokenResult.connectionConfig);
|
|
164
|
+
if (tokenResult.refreshToken) {
|
|
165
|
+
await this.sessionStore.setAuthorizationConfig(destination, {
|
|
166
|
+
...authConfig,
|
|
167
|
+
refreshToken: tokenResult.refreshToken,
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return tokenResult.connectionConfig.authorizationToken;
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
lastError = error;
|
|
174
|
+
// Step 6: All methods failed - throw error
|
|
175
|
+
const errorMessage = `All authentication methods failed for destination "${destination}". ` +
|
|
176
|
+
`Refresh token: ${refreshToken ? 'failed' : 'not available'}. ` +
|
|
177
|
+
`UAA: ${authConfig.uaaUrl && authConfig.uaaClientId && authConfig.uaaClientSecret ? 'failed' : 'parameters missing'}. ` +
|
|
178
|
+
`Browser authentication: failed (${error.message})`;
|
|
179
|
+
this.logger.error(errorMessage);
|
|
180
|
+
throw new Error(errorMessage);
|
|
86
181
|
}
|
|
87
|
-
return tokenResult.connectionConfig.authorizationToken;
|
|
88
182
|
}
|
|
89
183
|
/**
|
|
90
184
|
* Force refresh token for destination using service key.
|
package/dist/index.d.ts
CHANGED
|
@@ -7,4 +7,5 @@ export type { IAuthorizationConfig, IConnectionConfig, IServiceKeyStore, ISessio
|
|
|
7
7
|
export type { IConfig } from './types';
|
|
8
8
|
export type { ITokenProvider, TokenProviderOptions, TokenProviderResult } from './providers';
|
|
9
9
|
export type { Logger } from '@mcp-abap-adt/logger';
|
|
10
|
+
export type { AuthType } from '@mcp-abap-adt/interfaces';
|
|
10
11
|
//# 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;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"}
|
|
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;AAEnD,YAAY,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -6,44 +6,8 @@
|
|
|
6
6
|
* - XSUAA: client_credentials grant type (no browser)
|
|
7
7
|
* - BTP/ABAP: browser-based OAuth2 or refresh token
|
|
8
8
|
*/
|
|
9
|
-
import { IAuthorizationConfig, IConnectionConfig } from '
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export interface TokenProviderResult {
|
|
14
|
-
/** Connection configuration with authorization token */
|
|
15
|
-
connectionConfig: IConnectionConfig;
|
|
16
|
-
/** Refresh token (optional, for BTP/ABAP) */
|
|
17
|
-
refreshToken?: string;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Interface for token providers
|
|
21
|
-
*
|
|
22
|
-
* Takes authorization configuration and returns connection configuration with token.
|
|
23
|
-
*/
|
|
24
|
-
export interface ITokenProvider {
|
|
25
|
-
/**
|
|
26
|
-
* Get connection configuration with token from authorization configuration
|
|
27
|
-
* @param authConfig Authorization configuration (UAA credentials, optional refresh token)
|
|
28
|
-
* @param options Optional provider-specific options (e.g., browser type for BTP)
|
|
29
|
-
* @returns Promise that resolves to connection configuration with authorization token and optional refresh token
|
|
30
|
-
*/
|
|
31
|
-
getConnectionConfig(authConfig: IAuthorizationConfig, options?: TokenProviderOptions): Promise<TokenProviderResult>;
|
|
32
|
-
/**
|
|
33
|
-
* Validate JWT token by testing connection to service
|
|
34
|
-
* @param token JWT token to validate
|
|
35
|
-
* @param serviceUrl Service URL (optional, for services that require URL validation)
|
|
36
|
-
* @returns Promise that resolves to true if token is valid, false otherwise
|
|
37
|
-
*/
|
|
38
|
-
validateToken?(token: string, serviceUrl?: string): Promise<boolean>;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Options for token providers
|
|
42
|
-
*/
|
|
43
|
-
export interface TokenProviderOptions {
|
|
44
|
-
/** Browser type for browser-based authentication (chrome, edge, firefox, system, none) */
|
|
45
|
-
browser?: string;
|
|
46
|
-
/** Logger instance for logging */
|
|
47
|
-
logger?: import('@mcp-abap-adt/logger').Logger;
|
|
48
|
-
}
|
|
9
|
+
import type { IAuthorizationConfig, IConnectionConfig, ITokenProvider, ITokenProviderResult, ITokenProviderOptions } from '@mcp-abap-adt/interfaces';
|
|
10
|
+
export type { ITokenProvider, IAuthorizationConfig, IConnectionConfig, };
|
|
11
|
+
export type TokenProviderResult = ITokenProviderResult;
|
|
12
|
+
export type TokenProviderOptions = ITokenProviderOptions;
|
|
49
13
|
//# sourceMappingURL=ITokenProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ITokenProvider.d.ts","sourceRoot":"","sources":["../../src/providers/ITokenProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;
|
|
1
|
+
{"version":3,"file":"ITokenProvider.d.ts","sourceRoot":"","sources":["../../src/providers/ITokenProvider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,iBAAiB,GAClB,CAAC;AACF,MAAM,MAAM,mBAAmB,GAAG,oBAAoB,CAAC;AACvD,MAAM,MAAM,oBAAoB,GAAG,qBAAqB,CAAC"}
|
|
@@ -1,117 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Storage interfaces for AuthBroker
|
|
3
3
|
*
|
|
4
|
-
* All interfaces are
|
|
4
|
+
* All interfaces are imported from @mcp-abap-adt/interfaces package.
|
|
5
|
+
* Type aliases (type) are in types.ts.
|
|
5
6
|
*/
|
|
6
|
-
import type {
|
|
7
|
-
|
|
8
|
-
* Authorization configuration - values needed for obtaining and refreshing tokens
|
|
9
|
-
* Returned by stores with actual values (not file paths)
|
|
10
|
-
*/
|
|
11
|
-
export interface IAuthorizationConfig {
|
|
12
|
-
/** UAA URL for token refresh */
|
|
13
|
-
uaaUrl: string;
|
|
14
|
-
/** UAA client ID */
|
|
15
|
-
uaaClientId: string;
|
|
16
|
-
/** UAA client secret */
|
|
17
|
-
uaaClientSecret: string;
|
|
18
|
-
/** Refresh token for token renewal (optional) */
|
|
19
|
-
refreshToken?: string;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Connection configuration - values needed for connecting to services
|
|
23
|
-
* Returned by stores with actual values (not file paths)
|
|
24
|
-
*/
|
|
25
|
-
export interface IConnectionConfig {
|
|
26
|
-
/** Service URL (SAP/ABAP/MCP URL) - undefined for XSUAA if not provided */
|
|
27
|
-
serviceUrl?: string;
|
|
28
|
-
/** Authorization token (JWT token) */
|
|
29
|
-
authorizationToken: string;
|
|
30
|
-
/** SAP client number (optional, for ABAP/BTP) */
|
|
31
|
-
sapClient?: string;
|
|
32
|
-
/** Language (optional, for ABAP/BTP) */
|
|
33
|
-
language?: string;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Interface for storing and retrieving service keys
|
|
37
|
-
*
|
|
38
|
-
* Service keys contain UAA credentials and connection URLs.
|
|
39
|
-
*/
|
|
40
|
-
export interface IServiceKeyStore {
|
|
41
|
-
/**
|
|
42
|
-
* Get raw service key for destination
|
|
43
|
-
* @param destination Destination name (e.g., "TRIAL")
|
|
44
|
-
* @returns Service key object (implementation-specific) or null if not found
|
|
45
|
-
*/
|
|
46
|
-
getServiceKey(destination: string): Promise<IConfig | null>;
|
|
47
|
-
/**
|
|
48
|
-
* Get authorization configuration from service key
|
|
49
|
-
* Returns values needed for obtaining and refreshing tokens
|
|
50
|
-
* @param destination Destination name (e.g., "TRIAL")
|
|
51
|
-
* @returns IAuthorizationConfig with actual values or null if not found
|
|
52
|
-
*/
|
|
53
|
-
getAuthorizationConfig(destination: string): Promise<IAuthorizationConfig | null>;
|
|
54
|
-
/**
|
|
55
|
-
* Get connection configuration from service key
|
|
56
|
-
* Returns values needed for connecting to services
|
|
57
|
-
* @param destination Destination name (e.g., "TRIAL")
|
|
58
|
-
* @returns IConnectionConfig with actual values or null if not found
|
|
59
|
-
*/
|
|
60
|
-
getConnectionConfig(destination: string): Promise<IConnectionConfig | null>;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Interface for session stores - stores and retrieves session data
|
|
64
|
-
*
|
|
65
|
-
* Session stores handle loading, saving, and managing session data (tokens, configuration).
|
|
66
|
-
*/
|
|
67
|
-
export interface ISessionStore {
|
|
68
|
-
/**
|
|
69
|
-
* Load session configuration for destination
|
|
70
|
-
* Returns optional composition of IAuthorizationConfig and IConnectionConfig
|
|
71
|
-
* Can contain either authorization config, or connection config, or both
|
|
72
|
-
* @param destination Destination name (e.g., "TRIAL" or "mcp")
|
|
73
|
-
* @returns IConfig with actual values or null if not found
|
|
74
|
-
*/
|
|
75
|
-
loadSession(destination: string): Promise<IConfig | null>;
|
|
76
|
-
/**
|
|
77
|
-
* Save session configuration for destination
|
|
78
|
-
* Accepts IConfig (optional composition) or internal representation (for backward compatibility)
|
|
79
|
-
* @param destination Destination name (e.g., "TRIAL" or "mcp")
|
|
80
|
-
* @param config IConfig or internal session configuration to save
|
|
81
|
-
*/
|
|
82
|
-
saveSession(destination: string, config: IConfig | unknown): Promise<void>;
|
|
83
|
-
/**
|
|
84
|
-
* Delete session for destination (optional)
|
|
85
|
-
* @param destination Destination name (e.g., "TRIAL" or "mcp")
|
|
86
|
-
*/
|
|
87
|
-
deleteSession?(destination: string): Promise<void>;
|
|
88
|
-
/**
|
|
89
|
-
* Get authorization configuration with actual values (not file paths)
|
|
90
|
-
* Returns values needed for obtaining and refreshing tokens
|
|
91
|
-
* @param destination Destination name (e.g., "TRIAL" or "mcp")
|
|
92
|
-
* @returns IAuthorizationConfig with actual values or null if not found
|
|
93
|
-
*/
|
|
94
|
-
getAuthorizationConfig(destination: string): Promise<IAuthorizationConfig | null>;
|
|
95
|
-
/**
|
|
96
|
-
* Get connection configuration with actual values (not file paths)
|
|
97
|
-
* Returns values needed for connecting to services
|
|
98
|
-
* @param destination Destination name (e.g., "TRIAL" or "mcp")
|
|
99
|
-
* @returns IConnectionConfig with actual values or null if not found
|
|
100
|
-
*/
|
|
101
|
-
getConnectionConfig(destination: string): Promise<IConnectionConfig | null>;
|
|
102
|
-
/**
|
|
103
|
-
* Set authorization configuration
|
|
104
|
-
* Updates values needed for obtaining and refreshing tokens
|
|
105
|
-
* @param destination Destination name (e.g., "TRIAL" or "mcp")
|
|
106
|
-
* @param config IAuthorizationConfig with values to set
|
|
107
|
-
*/
|
|
108
|
-
setAuthorizationConfig(destination: string, config: IAuthorizationConfig): Promise<void>;
|
|
109
|
-
/**
|
|
110
|
-
* Set connection configuration
|
|
111
|
-
* Updates values needed for connecting to services
|
|
112
|
-
* @param destination Destination name (e.g., "TRIAL" or "mcp")
|
|
113
|
-
* @param config IConnectionConfig with values to set
|
|
114
|
-
*/
|
|
115
|
-
setConnectionConfig(destination: string, config: IConnectionConfig): Promise<void>;
|
|
116
|
-
}
|
|
7
|
+
import type { IAuthorizationConfig, IConnectionConfig, IServiceKeyStore, ISessionStore } from '@mcp-abap-adt/interfaces';
|
|
8
|
+
export type { IAuthorizationConfig, IConnectionConfig, IServiceKeyStore, ISessionStore, };
|
|
117
9
|
//# sourceMappingURL=interfaces.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/stores/interfaces.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/stores/interfaces.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EAEd,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,GACd,CAAC"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Storage interfaces for AuthBroker
|
|
4
4
|
*
|
|
5
|
-
* All interfaces are
|
|
5
|
+
* All interfaces are imported from @mcp-abap-adt/interfaces package.
|
|
6
|
+
* Type aliases (type) are in types.ts.
|
|
6
7
|
*/
|
|
7
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
package/dist/types.d.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Type definitions for auth-broker package
|
|
3
3
|
*
|
|
4
|
-
* Type aliases (type) are defined here. Interfaces are
|
|
4
|
+
* Type aliases (type) are defined here. Interfaces are imported from @mcp-abap-adt/interfaces.
|
|
5
5
|
*/
|
|
6
|
-
import type { IAuthorizationConfig, IConnectionConfig } from '
|
|
7
|
-
|
|
8
|
-
* Configuration - optional composition of authorization and connection configuration
|
|
9
|
-
* Can contain either authorization config, or connection config, or both
|
|
10
|
-
*/
|
|
11
|
-
export type IConfig = Partial<IAuthorizationConfig> & Partial<IConnectionConfig>;
|
|
12
|
-
export type { IAuthorizationConfig, IConnectionConfig, IServiceKeyStore, ISessionStore, } from './stores/interfaces';
|
|
6
|
+
import type { IAuthorizationConfig, IConnectionConfig, IConfig, IServiceKeyStore, ISessionStore } from '@mcp-abap-adt/interfaces';
|
|
7
|
+
export type { IConfig, IAuthorizationConfig, IConnectionConfig, IServiceKeyStore, ISessionStore, };
|
|
13
8
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,OAAO,EACP,gBAAgB,EAChB,aAAa,EACd,MAAM,0BAA0B,CAAC;AAGlC,YAAY,EACV,OAAO,EACP,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,GACd,CAAC"}
|
package/dist/types.js
CHANGED
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Type definitions for auth-broker package
|
|
4
4
|
*
|
|
5
|
-
* Type aliases (type) are defined here. Interfaces are
|
|
5
|
+
* Type aliases (type) are defined here. Interfaces are imported from @mcp-abap-adt/interfaces.
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-abap-adt/auth-broker",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "JWT authentication broker for MCP ABAP ADT - manages tokens based on destination headers",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -51,7 +51,8 @@
|
|
|
51
51
|
"node": ">=18.0.0"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@mcp-abap-adt/connection": "^0.1.
|
|
54
|
+
"@mcp-abap-adt/connection": "^0.1.14",
|
|
55
|
+
"@mcp-abap-adt/interfaces": "^0.1.0",
|
|
55
56
|
"@mcp-abap-adt/logger": "^0.1.0"
|
|
56
57
|
},
|
|
57
58
|
"devDependencies": {
|