@mcp-abap-adt/auth-broker 0.1.5 → 0.1.7

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +244 -0
  2. package/README.md +181 -16
  3. package/bin/generate-env-from-service-key.ts +128 -0
  4. package/dist/AuthBroker.d.ts +47 -31
  5. package/dist/AuthBroker.d.ts.map +1 -1
  6. package/dist/AuthBroker.js +182 -134
  7. package/dist/__tests__/helpers/configHelpers.d.ts +49 -0
  8. package/dist/__tests__/helpers/configHelpers.d.ts.map +1 -0
  9. package/dist/__tests__/helpers/configHelpers.js +169 -0
  10. package/dist/index.d.ts +4 -4
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +5 -8
  13. package/dist/providers/ITokenProvider.d.ts +49 -0
  14. package/dist/providers/ITokenProvider.d.ts.map +1 -0
  15. package/dist/providers/ITokenProvider.js +10 -0
  16. package/dist/providers/index.d.ts +8 -0
  17. package/dist/providers/index.d.ts.map +1 -0
  18. package/dist/providers/index.js +8 -0
  19. package/dist/stores/index.d.ts +5 -5
  20. package/dist/stores/index.d.ts.map +1 -1
  21. package/dist/stores/index.js +4 -8
  22. package/dist/stores/interfaces.d.ts +88 -22
  23. package/dist/stores/interfaces.d.ts.map +1 -1
  24. package/dist/stores/interfaces.js +1 -2
  25. package/dist/types.d.ts +7 -31
  26. package/dist/types.d.ts.map +1 -1
  27. package/dist/types.js +2 -0
  28. package/package.json +13 -6
  29. package/dist/__tests__/testHelpers.d.ts +0 -44
  30. package/dist/__tests__/testHelpers.d.ts.map +0 -1
  31. package/dist/__tests__/testHelpers.js +0 -136
  32. package/dist/browserAuth.d.ts +0 -17
  33. package/dist/browserAuth.d.ts.map +0 -1
  34. package/dist/browserAuth.js +0 -305
  35. package/dist/cache.d.ts +0 -20
  36. package/dist/cache.d.ts.map +0 -1
  37. package/dist/cache.js +0 -46
  38. package/dist/envLoader.d.ts +0 -12
  39. package/dist/envLoader.d.ts.map +0 -1
  40. package/dist/envLoader.js +0 -90
  41. package/dist/getToken.d.ts +0 -14
  42. package/dist/getToken.d.ts.map +0 -1
  43. package/dist/getToken.js +0 -62
  44. package/dist/logger.d.ts +0 -40
  45. package/dist/logger.d.ts.map +0 -1
  46. package/dist/logger.js +0 -186
  47. package/dist/pathResolver.d.ts +0 -21
  48. package/dist/pathResolver.d.ts.map +0 -1
  49. package/dist/pathResolver.js +0 -105
  50. package/dist/refreshToken.d.ts +0 -14
  51. package/dist/refreshToken.d.ts.map +0 -1
  52. package/dist/refreshToken.js +0 -71
  53. package/dist/serviceKeyLoader.d.ts +0 -12
  54. package/dist/serviceKeyLoader.d.ts.map +0 -1
  55. package/dist/serviceKeyLoader.js +0 -72
  56. package/dist/stores/FileServiceKeyStore.d.ts +0 -38
  57. package/dist/stores/FileServiceKeyStore.d.ts.map +0 -1
  58. package/dist/stores/FileServiceKeyStore.js +0 -47
  59. package/dist/stores/FileSessionStore.d.ts +0 -50
  60. package/dist/stores/FileSessionStore.d.ts.map +0 -1
  61. package/dist/stores/FileSessionStore.js +0 -116
  62. package/dist/stores/SafeSessionStore.d.ts +0 -35
  63. package/dist/stores/SafeSessionStore.d.ts.map +0 -1
  64. package/dist/stores/SafeSessionStore.js +0 -42
  65. package/dist/tokenRefresher.d.ts +0 -17
  66. package/dist/tokenRefresher.d.ts.map +0 -1
  67. package/dist/tokenRefresher.js +0 -53
  68. package/dist/tokenStorage.d.ts +0 -15
  69. package/dist/tokenStorage.d.ts.map +0 -1
  70. package/dist/tokenStorage.js +0 -107
  71. package/dist/tokenValidator.d.ts +0 -11
  72. package/dist/tokenValidator.d.ts.map +0 -1
  73. package/dist/tokenValidator.js +0 -108
package/CHANGELOG.md CHANGED
@@ -9,6 +9,250 @@ 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
+ ## [0.1.7] - 2025-12-04
13
+
14
+ ### Changed
15
+ - **getToken() Fallback Chain** - Improved authentication reliability with multi-step fallback chain
16
+ - **Step 1**: Check if session exists and token is valid (returns immediately if valid)
17
+ - **Step 2**: Verify service key exists (throws error if missing)
18
+ - **Step 3**: Try refresh token authentication (via tokenProvider) if refresh token is available
19
+ - **Step 4**: Try UAA client_credentials authentication (via tokenProvider) if refresh token missing or failed
20
+ - **Step 5**: Try browser authentication (via tokenProvider) if UAA failed or parameters missing
21
+ - **Step 6**: Throw comprehensive error if all methods failed
22
+ - All authentication attempts use `ITokenProvider` interface (no direct implementation imports)
23
+ - Token validation is performed only when checking existing session (step 1)
24
+ - Tokens obtained through refresh/UAA/browser authentication are not validated before being saved
25
+ - Improved error messages with details about which authentication methods failed
26
+
27
+ ## [0.1.6] - 2025-12-04
28
+
29
+ ### Changed
30
+ - **Package Split** - Extracted store and provider implementations into separate packages
31
+ - `@mcp-abap-adt/auth-stores-btp` - BTP and ABAP stores
32
+ - `@mcp-abap-adt/auth-stores-xsuaa` - XSUAA stores
33
+ - `@mcp-abap-adt/auth-providers` - XSUAA and BTP token providers
34
+ - `auth-broker` now only contains interfaces and core broker logic
35
+ - **ITokenProvider Interface** - Added optional `validateToken` method to token provider interface
36
+ - Token validation is now handled by providers, not by auth-broker
37
+ - Providers can implement custom validation logic
38
+ - **Dependencies** - Removed unused dependencies (axios, express, open, dotenv)
39
+ - These are now in provider/store packages
40
+ - `auth-broker` only depends on `@mcp-abap-adt/connection`
41
+
42
+ ### Removed
43
+ - Store implementations (moved to `@mcp-abap-adt/auth-stores-btp` and `@mcp-abap-adt/auth-stores-xsuaa`)
44
+ - Provider implementations (moved to `@mcp-abap-adt/auth-providers`)
45
+ - Token validator utility (moved to providers)
46
+ - Authentication functions (moved to providers)
47
+
48
+ ## [0.1.5] - 2025-12-03
49
+
50
+ ### Changed
51
+ - **Interface Naming** - All interfaces now start with `I` prefix
52
+ - `AuthorizationConfig` → `IAuthorizationConfig`
53
+ - `ConnectionConfig` → `IConnectionConfig`
54
+ - `ServiceKeyStore` → `IServiceKeyStore`
55
+ - `SessionStore` → `ISessionStore`
56
+ - **Type System** - Introduced `IConfig` as optional composition of `IAuthorizationConfig` and `IConnectionConfig`
57
+ - `loadSession()` and `getServiceKey()` now return `IConfig | null`
58
+ - `IConfig` is `Partial<IAuthorizationConfig> & Partial<IConnectionConfig>`
59
+ - **Token Provider Architecture** - Extracted token acquisition logic into `ITokenProvider` interface
60
+ - `XsuaaTokenProvider` - Uses client_credentials grant type (no browser)
61
+ - `BtpTokenProvider` - Uses browser-based OAuth2 or refresh token
62
+ - `AuthBroker` now accepts `tokenProvider` in constructor
63
+ - **XSUAA Configuration** - Renamed `btp_url` to `mcp_url` in YAML configuration
64
+ - For XSUAA, MCP URL is provided via `mcp_url` in YAML config (not `btp_url`)
65
+ - MCP URL is optional and not part of authentication
66
+ - **Constants** - Removed constants from exports (internal implementation details)
67
+ - All file operations are handled by stores through interfaces
68
+ - Consumers should use `IServiceKeyStore` and `ISessionStore` methods
69
+ - **File Structure** - Organized source code into logical subfolders
70
+ - `src/auth/` - Authentication logic (browserAuth, clientCredentialsAuth, tokenRefresher, tokenValidator)
71
+ - `src/cache/` - Token caching
72
+ - `src/constants/` - Internal constants
73
+ - `src/loaders/` - Service key loaders (abap, xsuaa)
74
+ - `src/logger/` - Logging utilities
75
+ - `src/methods/` - AuthBroker methods (getToken, refreshToken)
76
+ - `src/parsers/` - Service key parsers
77
+ - `src/pathResolver/` - Path resolution utilities
78
+ - `src/providers/` - Token providers (ITokenProvider, XsuaaTokenProvider, BtpTokenProvider)
79
+ - `src/storage/` - Environment file loaders and token storage (abap, btp, xsuaa)
80
+ - `src/stores/` - Store implementations (abap, btp, xsuaa)
81
+ - `src/types/` - Type definitions
82
+ - `src/utils/` - Utility functions
83
+ - **Test Structure** - Organized tests into subfolders by implementation
84
+ - `src/__tests__/broker/` - AuthBroker tests
85
+ - `src/__tests__/stores/abap/`, `src/__tests__/stores/btp/`, `src/__tests__/stores/xsuaa/` - Store tests
86
+ - `src/__tests__/loaders/abap/`, `src/__tests__/loaders/xsuaa/` - Loader tests
87
+ - `src/__tests__/storage/abap/`, `src/__tests__/storage/btp/`, `src/__tests__/storage/xsuaa/` - Storage tests
88
+ - `src/__tests__/parsers/` - Parser tests
89
+ - `src/__tests__/utils/` - Utility tests
90
+ - `src/__tests__/helpers/` - Test helpers (configHelpers, testHelpers, AuthBrokerTestHelper)
91
+
92
+ ### Removed
93
+ - **ServiceKey Type** - Removed `ServiceKey` type (internal implementation detail)
94
+ - **Internal Types** - Removed internal storage types from exports
95
+ - `EnvConfig`, `XsuaaSessionConfig`, `BtpSessionConfig` are now internal to store implementations
96
+ - **Constants Export** - Removed constants from public API
97
+ - `ABAP_AUTHORIZATION_VARS`, `ABAP_CONNECTION_VARS`, etc. are internal
98
+ - `ABAP_HEADERS`, `XSUAA_HEADERS`, `BTP_HEADERS` are internal
99
+ - **Parser Exports** - Removed parser interfaces and implementations from exports
100
+ - `IServiceKeyParser`, `AbapServiceKeyParser`, `XsuaaServiceKeyParser` are internal
101
+
102
+ ### Fixed
103
+ - **Test Configuration** - Tests now use YAML configuration file (`tests/test-config.yaml`)
104
+ - Removed hardcoded paths and destinations
105
+ - Added `AuthBrokerTestHelper` for creating broker instances from YAML
106
+ - Tests organized into subfolders by implementation (`abap`, `btp`, `xsuaa`)
107
+ - **Browser Authentication** - Fixed hanging tests when `browser: 'none'` is specified
108
+ - `startBrowserAuth` now immediately throws error with URL when `browser: 'none'`
109
+ - Added timeout to `clientCredentialsAuth` to prevent hanging
110
+ - **Session Store Validation** - Fixed validation in `Safe*SessionStore` classes
111
+ - Now accepts `IConfig` format (with `serviceUrl`/`authorizationToken`) and converts to internal format
112
+ - Validation messages updated to match actual error messages
113
+ - **YAML Configuration** - Fixed path resolution for test configuration
114
+ - Uses `findProjectRoot()` to reliably locate `test-config.yaml`
115
+ - Properly expands `~` to home directory in paths
116
+ - Added diagnostic logging controlled by `TEST_VERBOSE` environment variable
117
+
118
+ ### Added
119
+ - **BTP Full-Scope Authentication** - Full support for BTP authentication to ABAP systems (with full roles and scopes)
120
+ - `BtpSessionStore` - Store for BTP sessions (uses `BTP_*` environment variables)
121
+ - `SafeBtpSessionStore` - In-memory BTP session store
122
+ - `BtpSessionConfig` - Configuration interface for BTP authentication (includes `abapUrl`)
123
+ - `loadBtpEnvFile()` - Loads BTP session configuration from `.env` files with `BTP_*` variables
124
+ - `saveBtpTokenToEnv()` - Saves BTP session configuration to `.env` files with `BTP_*` variables
125
+ - **BTP Environment Variables** - `BTP_ENV_VARS` constants
126
+ - `BTP_ABAP_URL` - ABAP system URL (required, from service key or YAML)
127
+ - `BTP_JWT_TOKEN` - JWT token for `Authorization: Bearer` header
128
+ - `BTP_REFRESH_TOKEN` - Optional refresh token
129
+ - `BTP_UAA_URL`, `BTP_UAA_CLIENT_ID`, `BTP_UAA_CLIENT_SECRET` - UAA credentials (from service key)
130
+ - **BTP HTTP Headers** - `BTP_HEADERS` constants
131
+ - `BTP_HEADERS.AUTHORIZATION` - Authorization header
132
+ - `BTP_HEADERS.ABAP_URL` - ABAP URL header (`x-abap-url`)
133
+ - `BTP_HEADERS.BTP_DESTINATION` - BTP destination header (`x-btp-destination`)
134
+ - `BTP_HEADERS.SAP_CLIENT` - SAP client header (`x-sap-client`)
135
+ - `BTP_HEADERS.LANGUAGE` - Language header (`x-sap-language`)
136
+ - **Helper Functions** - `isBtpEnvVar()` function to check if environment variable is BTP-related
137
+ - **XSUAA Support** - Full support for XSUAA authentication (reduced scope)
138
+ - `XsuaaServiceKeyStore` - Store for XSUAA service keys (direct format from BTP)
139
+ - `XsuaaSessionStore` - Store for XSUAA sessions (uses `XSUAA_*` environment variables)
140
+ - `SafeXsuaaSessionStore` - In-memory XSUAA session store
141
+ - `XsuaaServiceKeyParser` - Parser for direct XSUAA service key format
142
+ - Client credentials grant type for XSUAA (no browser required)
143
+ - **Environment Variable Constants** - Exported constants for consumers
144
+ - `ABAP_ENV_VARS` - Environment variable names for ABAP connections (SAP_URL, SAP_JWT_TOKEN, etc.)
145
+ - `XSUAA_ENV_VARS` - Environment variable names for XSUAA connections (XSUAA_MCP_URL, XSUAA_JWT_TOKEN, etc.)
146
+ - `ABAP_HEADERS` - HTTP header names for ABAP requests (x-sap-url, x-sap-jwt-token, etc.)
147
+ - `XSUAA_HEADERS` - HTTP header names for XSUAA requests (Authorization, x-mcp-url, etc.)
148
+ - Helper functions: `getBtpAuthorizationHeader()`, `isAbapEnvVar()`, `isXsuaaEnvVar()`
149
+ - **Service Key Parsers** - Modular parser architecture
150
+ - `IServiceKeyParser` - Interface for service key parsers
151
+ - `AbapServiceKeyParser` - Parser for standard ABAP service keys
152
+ - `XsuaaServiceKeyParser` - Parser for direct XSUAA service keys
153
+ - **Utility Script** - `generate-env` command
154
+ - Generates `.env` files from service keys
155
+ - Supports both ABAP and XSUAA service key formats
156
+ - Automatically detects service key type and uses appropriate authentication flow
157
+ - **XSUAA Environment Loader** - `loadXsuaaEnvFile()` function
158
+ - Loads XSUAA session configuration from `.env` files with `XSUAA_*` variables
159
+ - **XSUAA Token Storage** - `saveXsuaaTokenToEnv()` function
160
+ - Saves XSUAA session configuration to `.env` files with `XSUAA_*` variables
161
+ - Automatically removes old `SAP_*` variables when saving XSUAA sessions
162
+
163
+ ### Changed
164
+ - **Interface Naming** - All interfaces now start with `I` prefix
165
+ - `AuthorizationConfig` → `IAuthorizationConfig`
166
+ - `ConnectionConfig` → `IConnectionConfig`
167
+ - `ServiceKeyStore` → `IServiceKeyStore`
168
+ - `SessionStore` → `ISessionStore`
169
+ - **Type System** - Introduced `IConfig` as optional composition of `IAuthorizationConfig` and `IConnectionConfig`
170
+ - `loadSession()` and `getServiceKey()` now return `IConfig | null`
171
+ - `IConfig` is `Partial<IAuthorizationConfig> & Partial<IConnectionConfig>`
172
+ - **Token Provider Architecture** - Extracted token acquisition logic into `ITokenProvider` interface
173
+ - `XsuaaTokenProvider` - Uses client_credentials grant type (no browser)
174
+ - `BtpTokenProvider` - Uses browser-based OAuth2 or refresh token
175
+ - `AuthBroker` now accepts `tokenProvider` in constructor
176
+ - **XSUAA Configuration** - Renamed `btp_url` to `mcp_url` in YAML configuration
177
+ - For XSUAA, MCP URL is provided via `mcp_url` in YAML config (not `btp_url`)
178
+ - MCP URL is optional and not part of authentication
179
+ - **Constants** - Removed constants from exports (internal implementation details)
180
+ - All file operations are handled by stores through interfaces
181
+ - Consumers should use `IServiceKeyStore` and `ISessionStore` methods
182
+ - **File Structure** - Organized source code into logical subfolders
183
+ - `src/auth/` - Authentication logic (browserAuth, clientCredentialsAuth, tokenRefresher, tokenValidator)
184
+ - `src/cache/` - Token caching
185
+ - `src/constants/` - Internal constants
186
+ - `src/loaders/` - Service key loaders (abap, xsuaa)
187
+ - `src/logger/` - Logging utilities
188
+ - `src/methods/` - AuthBroker methods (getToken, refreshToken)
189
+ - `src/parsers/` - Service key parsers
190
+ - `src/pathResolver/` - Path resolution utilities
191
+ - `src/providers/` - Token providers (ITokenProvider, XsuaaTokenProvider, BtpTokenProvider)
192
+ - `src/storage/` - Environment file loaders and token storage (abap, btp, xsuaa)
193
+ - `src/stores/` - Store implementations (abap, btp, xsuaa)
194
+ - `src/types/` - Type definitions
195
+ - `src/utils/` - Utility functions
196
+ - **Test Structure** - Organized tests into subfolders by implementation
197
+ - `src/__tests__/broker/` - AuthBroker tests
198
+ - `src/__tests__/stores/abap/`, `src/__tests__/stores/btp/`, `src/__tests__/stores/xsuaa/` - Store tests
199
+ - `src/__tests__/loaders/abap/`, `src/__tests__/loaders/xsuaa/` - Loader tests
200
+ - `src/__tests__/storage/abap/`, `src/__tests__/storage/btp/`, `src/__tests__/storage/xsuaa/` - Storage tests
201
+ - `src/__tests__/parsers/` - Parser tests
202
+ - `src/__tests__/utils/` - Utility tests
203
+ - `src/__tests__/helpers/` - Test helpers (configHelpers, testHelpers, AuthBrokerTestHelper)
204
+ - **Renamed XSUAA Components** - Clarified naming for reduced-scope XSUAA authentication
205
+ - `BtpSessionConfig` → `XsuaaSessionConfig` (for reduced-scope XSUAA)
206
+ - `BTP_ENV_VARS` → `XSUAA_ENV_VARS` (for reduced-scope XSUAA)
207
+ - `BTP_HEADERS` → `XSUAA_HEADERS` (for reduced-scope XSUAA)
208
+ - `BtpSessionStore` → `XsuaaSessionStore` (for reduced-scope XSUAA)
209
+ - `SafeBtpSessionStore` → `SafeXsuaaSessionStore` (for reduced-scope XSUAA)
210
+ - **XSUAA Session Format** - Uses `XSUAA_*` environment variables instead of `SAP_*`
211
+ - `XSUAA_MCP_URL` - MCP server URL (optional, not part of authentication)
212
+ - `XSUAA_JWT_TOKEN` - JWT token for `Authorization: Bearer` header
213
+ - `XSUAA_REFRESH_TOKEN` - Optional refresh token
214
+ - `XSUAA_UAA_URL`, `XSUAA_UAA_CLIENT_ID`, `XSUAA_UAA_CLIENT_SECRET` - UAA credentials
215
+ - **MCP URL Handling** - MCP URL is now optional for XSUAA sessions
216
+ - MCP URL is not part of authentication (only needed for making requests)
217
+ - Can be provided via YAML config (`mcp_url`), parameter, or request header
218
+ - Session files can be created without MCP URL (tokens and UAA credentials are sufficient)
219
+ - **Service Key URL Priority** - For XSUAA service keys, `apiurl` is prioritized over `url` for UAA authorization
220
+ - **Store Naming** - Renamed stores for clarity
221
+ - `FileServiceKeyStore` → `AbapServiceKeyStore` (for ABAP service keys)
222
+ - `FileSessionStore` → `AbapSessionStore` (for ABAP sessions)
223
+ - `SafeSessionStore` → `SafeAbapSessionStore` (for in-memory ABAP sessions)
224
+ - Old names still available as type aliases for backward compatibility
225
+
226
+ ### Removed
227
+ - **ServiceKey Type** - Removed `ServiceKey` type (internal implementation detail)
228
+ - **Internal Types** - Removed internal storage types from exports
229
+ - `EnvConfig`, `XsuaaSessionConfig`, `BtpSessionConfig` are now internal to store implementations
230
+ - **Constants Export** - Removed constants from public API
231
+ - `ABAP_AUTHORIZATION_VARS`, `ABAP_CONNECTION_VARS`, etc. are internal
232
+ - `ABAP_HEADERS`, `XSUAA_HEADERS`, `BTP_HEADERS` are internal
233
+ - **Parser Exports** - Removed parser interfaces and implementations from exports
234
+ - `IServiceKeyParser`, `AbapServiceKeyParser`, `XsuaaServiceKeyParser` are internal
235
+
236
+ ### Fixed
237
+ - **XSUAA Authentication** - Fixed client_credentials grant type implementation
238
+ - Uses POST request to UAA token endpoint with `grant_type=client_credentials`
239
+ - No browser interaction required for XSUAA
240
+ - Proper error handling for OAuth2 redirect parameters
241
+ - **Test Configuration** - Tests now use YAML configuration file (`tests/test-config.yaml`)
242
+ - Removed hardcoded paths and destinations
243
+ - Added `AuthBrokerTestHelper` for creating broker instances from YAML
244
+ - Tests organized into subfolders by implementation (`abap`, `btp`, `xsuaa`)
245
+ - **Browser Authentication** - Fixed hanging tests when `browser: 'none'` is specified
246
+ - `startBrowserAuth` now immediately throws error with URL when `browser: 'none'`
247
+ - Added timeout to `clientCredentialsAuth` to prevent hanging
248
+ - **Session Store Validation** - Fixed validation in `Safe*SessionStore` classes
249
+ - Now accepts `IConfig` format (with `serviceUrl`/`authorizationToken`) and converts to internal format
250
+ - Validation messages updated to match actual error messages
251
+ - **YAML Configuration** - Fixed path resolution for test configuration
252
+ - Uses `findProjectRoot()` to reliably locate `test-config.yaml`
253
+ - Properly expands `~` to home directory in paths
254
+ - Added diagnostic logging controlled by `TEST_VERBOSE` environment variable
255
+
12
256
  ## [0.1.5] - 2025-12-02
13
257
 
14
258
  ### Added
package/README.md CHANGED
@@ -20,21 +20,29 @@ npm install @mcp-abap-adt/auth-broker
20
20
  ## Usage
21
21
 
22
22
  ```typescript
23
- import { AuthBroker, FileServiceKeyStore, FileSessionStore, SafeSessionStore } from '@mcp-abap-adt/auth-broker';
23
+ import {
24
+ AuthBroker,
25
+ AbapServiceKeyStore,
26
+ AbapSessionStore,
27
+ SafeAbapSessionStore,
28
+ BtpTokenProvider
29
+ } from '@mcp-abap-adt/auth-broker';
24
30
 
25
31
  // Use default file-based stores (current working directory)
26
32
  const broker = new AuthBroker();
27
33
 
28
34
  // Use custom file-based stores with specific paths
29
35
  const broker = new AuthBroker({
30
- serviceKeyStore: new FileServiceKeyStore(['/path/to/destinations']),
31
- sessionStore: new FileSessionStore(['/path/to/destinations']),
36
+ serviceKeyStore: new AbapServiceKeyStore(['/path/to/destinations']),
37
+ sessionStore: new AbapSessionStore(['/path/to/destinations']),
38
+ tokenProvider: new BtpTokenProvider(),
32
39
  }, 'chrome');
33
40
 
34
41
  // Use safe in-memory session store (data lost after restart)
35
42
  const broker = new AuthBroker({
36
- serviceKeyStore: new FileServiceKeyStore(['/path/to/destinations']),
37
- sessionStore: new SafeSessionStore(), // In-memory, secure
43
+ serviceKeyStore: new AbapServiceKeyStore(['/path/to/destinations']),
44
+ sessionStore: new SafeAbapSessionStore(), // In-memory, secure
45
+ tokenProvider: new BtpTokenProvider(),
38
46
  });
39
47
 
40
48
  // Get token for destination (loads from .env, validates, refreshes if needed)
@@ -53,7 +61,9 @@ const newToken = await broker.refreshToken('TRIAL');
53
61
 
54
62
  ### File Structure
55
63
 
56
- #### Environment File (`{destination}.env`)
64
+ #### Environment File for ABAP (`{destination}.env`)
65
+
66
+ For ABAP connections, use `SAP_*` environment variables:
57
67
 
58
68
  ```env
59
69
  SAP_URL=https://your-system.abap.us10.hana.ondemand.com
@@ -65,7 +75,41 @@ SAP_UAA_CLIENT_ID=client_id
65
75
  SAP_UAA_CLIENT_SECRET=client_secret
66
76
  ```
67
77
 
68
- #### Service Key File (`{destination}.json`)
78
+ #### Environment File for XSUAA (`{destination}.env`)
79
+
80
+ For XSUAA connections (reduced scope), use `XSUAA_*` environment variables:
81
+
82
+ ```env
83
+ XSUAA_MCP_URL=https://your-mcp-server.cfapps.eu10.hana.ondemand.com
84
+ XSUAA_JWT_TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
85
+ XSUAA_REFRESH_TOKEN=refresh_token_string
86
+ XSUAA_UAA_URL=https://your-account.authentication.eu10.hana.ondemand.com
87
+ XSUAA_UAA_CLIENT_ID=client_id
88
+ XSUAA_UAA_CLIENT_SECRET=client_secret
89
+ ```
90
+
91
+ **Note**: `XSUAA_MCP_URL` is optional - it's not part of authentication, only needed for making requests. The token and UAA credentials are sufficient for authentication.
92
+
93
+ #### Environment File for BTP (`{destination}.env`)
94
+
95
+ For BTP connections (full scope for ABAP systems), use `BTP_*` environment variables:
96
+
97
+ ```env
98
+ BTP_ABAP_URL=https://your-system.abap.us10.hana.ondemand.com
99
+ BTP_JWT_TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
100
+ BTP_REFRESH_TOKEN=refresh_token_string
101
+ BTP_UAA_URL=https://your-account.authentication.eu10.hana.ondemand.com
102
+ BTP_UAA_CLIENT_ID=client_id
103
+ BTP_UAA_CLIENT_SECRET=client_secret
104
+ BTP_SAP_CLIENT=100
105
+ BTP_LANGUAGE=EN
106
+ ```
107
+
108
+ **Note**: `BTP_ABAP_URL` is required - it's the ABAP system URL. All parameters (except tokens) come from service key.
109
+
110
+ #### Service Key File for ABAP (`{destination}.json`)
111
+
112
+ Standard ABAP service key format:
69
113
 
70
114
  ```json
71
115
  {
@@ -78,6 +122,41 @@ SAP_UAA_CLIENT_SECRET=client_secret
78
122
  }
79
123
  ```
80
124
 
125
+ #### Service Key File for XSUAA (`{destination}.json`)
126
+
127
+ Direct XSUAA service key format (from BTP):
128
+
129
+ ```json
130
+ {
131
+ "url": "https://your-account.authentication.eu10.hana.ondemand.com",
132
+ "apiurl": "https://api.authentication.eu10.hana.ondemand.com",
133
+ "clientid": "your_client_id",
134
+ "clientsecret": "your_client_secret"
135
+ }
136
+ ```
137
+
138
+ **Note**: For XSUAA service keys, `apiurl` is prioritized over `url` for UAA authorization if present.
139
+
140
+ ## XSUAA vs BTP Authentication
141
+
142
+ This package supports two types of BTP authentication:
143
+
144
+ ### XSUAA (Reduced Scope)
145
+ - **Purpose**: Access BTP services with limited scopes
146
+ - **Service Key**: Contains only UAA credentials (no ABAP URL)
147
+ - **Session Store**: `XsuaaSessionStore` (uses `XSUAA_*` environment variables)
148
+ - **Authentication**: Client credentials grant type (no browser required)
149
+ - **MCP URL**: Optional, provided separately (from YAML config `mcp_url`, parameter, or request header)
150
+ - **Use Case**: Accessing BTP services like MCP servers with reduced permissions
151
+
152
+ ### BTP (Full Scope for ABAP)
153
+ - **Purpose**: Access ABAP systems with full roles and scopes
154
+ - **Service Key**: Contains UAA credentials and ABAP URL
155
+ - **Session Store**: `BtpSessionStore` (uses `BTP_*` environment variables)
156
+ - **Authentication**: Browser-based OAuth2 (like ABAP) or refresh token
157
+ - **ABAP URL**: Required, from service key or YAML configuration
158
+ - **Use Case**: Accessing ABAP systems in BTP with full permissions
159
+
81
160
  ## API
82
161
 
83
162
  ### `AuthBroker`
@@ -85,24 +164,42 @@ SAP_UAA_CLIENT_SECRET=client_secret
85
164
  #### Constructor
86
165
 
87
166
  ```typescript
88
- new AuthBroker(stores?: { serviceKeyStore?: IServiceKeyStore; sessionStore?: ISessionStore }, browser?: string, logger?: Logger)
167
+ new AuthBroker(
168
+ stores?: {
169
+ serviceKeyStore?: IServiceKeyStore;
170
+ sessionStore?: ISessionStore;
171
+ tokenProvider?: ITokenProvider;
172
+ },
173
+ browser?: string,
174
+ logger?: Logger
175
+ )
89
176
  ```
90
177
 
91
178
  - `stores` - Optional object with custom storage implementations:
92
- - `serviceKeyStore` - Store for service keys (default: `FileServiceKeyStore()`)
93
- - `sessionStore` - Store for session data (default: `FileSessionStore()`)
179
+ - `serviceKeyStore` - Store for service keys (default: `AbapServiceKeyStore()`)
180
+ - `sessionStore` - Store for session data (default: `AbapSessionStore()`)
181
+ - `tokenProvider` - Token provider for token acquisition (default: `BtpTokenProvider()`)
94
182
  - Available implementations:
95
- - `FileServiceKeyStore(searchPaths?)` - File-based service key store
96
- - `FileSessionStore(searchPaths?)` - File-based session store (persists to disk)
97
- - `SafeSessionStore()` - In-memory session store (secure, data lost after restart)
183
+ - **ABAP**: `AbapServiceKeyStore(searchPaths?)`, `AbapSessionStore(searchPaths?)`, `SafeAbapSessionStore()`, `BtpTokenProvider()`
184
+ - **XSUAA** (reduced scope): `XsuaaServiceKeyStore(searchPaths?)`, `XsuaaSessionStore(searchPaths?)`, `SafeXsuaaSessionStore()`, `XsuaaTokenProvider()`
185
+ - **BTP** (full scope for ABAP): `AbapServiceKeyStore(searchPaths?)`, `BtpSessionStore(searchPaths?)`, `SafeBtpSessionStore()`, `BtpTokenProvider()`
98
186
  - `browser` - Optional browser name for authentication (`chrome`, `edge`, `firefox`, `system`, `none`). Default: `system`
187
+ - For XSUAA, browser is not used (client_credentials grant type) - use `'none'`
99
188
  - `logger` - Optional logger instance. If not provided, uses default logger
100
189
 
101
190
  #### Methods
102
191
 
103
192
  ##### `getToken(destination: string): Promise<string>`
104
193
 
105
- Gets authentication token for destination. Tries to load from `.env` file, validates it, and refreshes if needed.
194
+ Gets authentication token for destination. Tries to load from session store, validates it, and refreshes if needed using a fallback chain:
195
+
196
+ 1. **Check session**: Load token from session store and validate it
197
+ 2. **Try refresh token**: If refresh token is available, attempt to refresh using it (via tokenProvider)
198
+ 3. **Try UAA (client_credentials)**: Attempt to get token using UAA credentials (via tokenProvider)
199
+ 4. **Try browser authentication**: Attempt browser-based OAuth2 flow using service key (via tokenProvider)
200
+ 5. **Throw error**: If all authentication methods failed
201
+
202
+ **Note**: Token validation is performed only when checking existing session. Tokens obtained through refresh/UAA/browser authentication are not validated before being saved.
106
203
 
107
204
  ##### `refreshToken(destination: string): Promise<string>`
108
205
 
@@ -116,6 +213,70 @@ Clear cached token for specific destination.
116
213
 
117
214
  Clear all cached tokens.
118
215
 
216
+ ### Token Providers
217
+
218
+ The package uses `ITokenProvider` interface for token acquisition. Two implementations are available:
219
+
220
+ - **`XsuaaTokenProvider`** - For XSUAA authentication (reduced scope)
221
+ - Uses client_credentials grant type
222
+ - No browser interaction required
223
+ - No refresh token provided
224
+
225
+ - **`BtpTokenProvider`** - For BTP/ABAP authentication (full scope)
226
+ - Uses browser-based OAuth2 flow (if no refresh token)
227
+ - Uses refresh token if available
228
+ - Provides refresh token for future use
229
+
230
+ **Example Usage:**
231
+
232
+ ```typescript
233
+ import {
234
+ AuthBroker,
235
+ XsuaaServiceKeyStore,
236
+ XsuaaSessionStore,
237
+ XsuaaTokenProvider,
238
+ BtpTokenProvider
239
+ } from '@mcp-abap-adt/auth-broker';
240
+
241
+ // XSUAA authentication (no browser needed)
242
+ const xsuaaBroker = new AuthBroker({
243
+ serviceKeyStore: new XsuaaServiceKeyStore(['/path/to/keys']),
244
+ sessionStore: new XsuaaSessionStore(['/path/to/sessions']),
245
+ tokenProvider: new XsuaaTokenProvider(),
246
+ }, 'none');
247
+
248
+ // BTP authentication (browser or refresh token)
249
+ const btpBroker = new AuthBroker({
250
+ serviceKeyStore: new AbapServiceKeyStore(['/path/to/keys']),
251
+ sessionStore: new BtpSessionStore(['/path/to/sessions']),
252
+ tokenProvider: new BtpTokenProvider(),
253
+ });
254
+ ```
255
+
256
+ ### Utility Script
257
+
258
+ Generate `.env` files from service keys:
259
+
260
+ ```bash
261
+ npm run generate-env <destination> [service-key-path] [session-path]
262
+ ```
263
+
264
+ **Examples:**
265
+ ```bash
266
+ # Generate .env from service key (auto-detect paths)
267
+ npm run generate-env mcp
268
+
269
+ # Specify paths explicitly
270
+ npm run generate-env mcp ./mcp.json ./mcp.env
271
+
272
+ # Use absolute paths
273
+ npm run generate-env TRIAL ~/.config/mcp-abap-adt/service-keys/TRIAL.json ~/.config/mcp-abap-adt/sessions/TRIAL.env
274
+ ```
275
+
276
+ The script automatically detects service key type (ABAP or XSUAA) and uses the appropriate authentication flow:
277
+ - **ABAP**: Opens browser for OAuth2 authorization code flow
278
+ - **XSUAA**: Uses client_credentials grant type (no browser required)
279
+
119
280
  ## Testing
120
281
 
121
282
  Tests are located in `src/__tests__/` and use Jest as the test runner.
@@ -160,9 +321,13 @@ Tests are designed to run sequentially (guaranteed by `maxWorkers: 1` and `maxCo
160
321
 
161
322
  ### Test Setup
162
323
 
163
- Place your service key file in `./test-destinations/TRIAL.json` to run tests 2 and 3.
324
+ 1. Copy `tests/test-config.yaml.template` to `tests/test-config.yaml`
325
+ 2. Fill in configuration values (paths, destinations, MCP URL for XSUAA)
326
+ 3. Place service key files in configured `service_keys_dir`:
327
+ - `{destination}.json` for ABAP tests (e.g., `trial.json`)
328
+ - `{btp_destination}.json` for XSUAA tests (e.g., `btp.json`)
164
329
 
165
- Tests will automatically skip if required files are missing or present when they shouldn't be.
330
+ Tests will automatically skip if required files are missing or configuration contains placeholders.
166
331
 
167
332
  ## Documentation
168
333
 
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env tsx
2
+ /**
3
+ * Generate .env file from service key
4
+ *
5
+ * Usage:
6
+ * npm run generate-env <destination> [service-key-path] [session-path]
7
+ * or
8
+ * npx tsx bin/generate-env-from-service-key.ts <destination> [service-key-path] [session-path]
9
+ *
10
+ * Examples:
11
+ * npm run generate-env mcp
12
+ * npm run generate-env mcp ./mcp.json ./mcp.env
13
+ * npm run generate-env TRIAL ~/.config/mcp-abap-adt/service-keys/TRIAL.json
14
+ */
15
+
16
+ import * as path from 'path';
17
+ import * as fs from 'fs';
18
+ import { AuthBroker } from '../src/AuthBroker';
19
+ import { AbapServiceKeyStore, AbapSessionStore } from '@mcp-abap-adt/auth-stores-btp';
20
+ import { XsuaaServiceKeyStore, XsuaaSessionStore } from '@mcp-abap-adt/auth-stores-xsuaa';
21
+ import { BtpTokenProvider, XsuaaTokenProvider } from '@mcp-abap-adt/auth-providers';
22
+
23
+ async function main() {
24
+ const args = process.argv.slice(2);
25
+
26
+ if (args.length === 0) {
27
+ console.error('Usage: generate-env-from-service-key <destination> [service-key-path] [session-path]');
28
+ console.error('');
29
+ console.error('Examples:');
30
+ console.error(' generate-env-from-service-key mcp');
31
+ console.error(' generate-env-from-service-key mcp ./mcp.json ./mcp.env');
32
+ console.error(' generate-env-from-service-key TRIAL ~/.config/mcp-abap-adt/service-keys/TRIAL.json');
33
+ process.exit(1);
34
+ }
35
+
36
+ const destination = args[0];
37
+ const serviceKeyPath = args[1] || path.join(process.cwd(), `${destination}.json`);
38
+ const sessionPath = args[2] || path.join(process.cwd(), `${destination}.env`);
39
+
40
+ // Resolve paths
41
+ const resolvedServiceKeyPath = path.resolve(serviceKeyPath);
42
+ const resolvedSessionPath = path.resolve(sessionPath);
43
+ const serviceKeyDir = path.dirname(resolvedServiceKeyPath);
44
+ const sessionDir = path.dirname(resolvedSessionPath);
45
+
46
+ // Check if service key file exists
47
+ if (!fs.existsSync(resolvedServiceKeyPath)) {
48
+ console.error(`❌ Service key file not found: ${resolvedServiceKeyPath}`);
49
+ process.exit(1);
50
+ }
51
+
52
+ console.log(`📁 Service key: ${resolvedServiceKeyPath}`);
53
+ console.log(`📁 Session file: ${resolvedSessionPath}`);
54
+
55
+ try {
56
+ // Load service key to determine type
57
+ const rawServiceKey = JSON.parse(fs.readFileSync(resolvedServiceKeyPath, 'utf8'));
58
+ const isXsuaa = rawServiceKey.url && rawServiceKey.url.includes('authentication') && !rawServiceKey.uaa;
59
+
60
+ // Create appropriate stores
61
+ const serviceKeyStore = isXsuaa
62
+ ? new XsuaaServiceKeyStore([serviceKeyDir])
63
+ : new AbapServiceKeyStore([serviceKeyDir]);
64
+
65
+ const sessionStore = isXsuaa
66
+ ? new XsuaaSessionStore([sessionDir])
67
+ : new AbapSessionStore([sessionDir]);
68
+
69
+ // Create token provider
70
+ const tokenProvider = isXsuaa
71
+ ? new XsuaaTokenProvider()
72
+ : new BtpTokenProvider();
73
+
74
+ // Create AuthBroker
75
+ // For ABAP, use 'system' browser (will open browser for auth)
76
+ // For XSUAA, browser doesn't matter (uses client_credentials)
77
+ const broker = new AuthBroker({
78
+ serviceKeyStore,
79
+ sessionStore,
80
+ tokenProvider,
81
+ }, isXsuaa ? 'none' : 'system');
82
+
83
+ console.log(`🔐 Getting token for destination "${destination}"...`);
84
+ if (isXsuaa) {
85
+ console.log(` Using client_credentials grant type (no browser required)`);
86
+ } else {
87
+ console.log(` Using browser authentication (browser will open)`);
88
+ }
89
+
90
+ // Get token (will use client_credentials for XSUAA or browser auth for ABAP)
91
+ const token = await broker.getToken(destination);
92
+
93
+ console.log(`✅ Token obtained successfully`);
94
+
95
+ // Check if session file was created
96
+ if (fs.existsSync(resolvedSessionPath)) {
97
+ console.log(`✅ Session file created: ${resolvedSessionPath}`);
98
+
99
+ // Show service URL if available
100
+ const connConfig = await broker.getConnectionConfig(destination);
101
+ if (connConfig?.serviceUrl) {
102
+ if (isXsuaa) {
103
+ console.log(`📁 MCP URL: ${connConfig.serviceUrl}`);
104
+ } else {
105
+ console.log(`📁 SAP URL: ${connConfig.serviceUrl}`);
106
+ }
107
+ } else if (isXsuaa) {
108
+ console.log(`💡 Note: MCP URL not set in session (optional for XSUAA).`);
109
+ console.log(` Provide MCP URL via YAML config, parameter, or request header when making requests.`);
110
+ }
111
+ } else {
112
+ console.log(`⚠️ Session file was not created. Token is cached in memory.`);
113
+ }
114
+
115
+ } catch (error: any) {
116
+ console.error(`❌ Error: ${error.message}`);
117
+ if (error.stack) {
118
+ console.error(error.stack);
119
+ }
120
+ process.exit(1);
121
+ }
122
+ }
123
+
124
+ main().catch((error) => {
125
+ console.error('Fatal error:', error);
126
+ process.exit(1);
127
+ });
128
+