@mcp-abap-adt/auth-broker 0.2.5 → 0.2.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.
- package/CHANGELOG.md +24 -2
- package/README.md +13 -4
- package/dist/AuthBroker.d.ts +10 -2
- package/dist/AuthBroker.d.ts.map +1 -1
- package/dist/AuthBroker.js +28 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -11,10 +11,32 @@ Thank you to all contributors! See [CONTRIBUTORS.md](CONTRIBUTORS.md) for the co
|
|
|
11
11
|
|
|
12
12
|
## [Unreleased]
|
|
13
13
|
|
|
14
|
-
## [0.2.
|
|
14
|
+
## [0.2.7] - 2025-12-21
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- **Headless Browser Mode**: Added `browser: 'headless'` option for SSH and remote sessions
|
|
18
|
+
- Logs authentication URL and waits for manual callback
|
|
19
|
+
- Ideal for environments without display (SSH, Docker, CI/CD)
|
|
20
|
+
- Differs from `'none'` which rejects immediately (for automated tests)
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
- **Documentation Update**: Updated browser option documentation to clarify `headless` vs `none` modes
|
|
24
|
+
|
|
25
|
+
### Dependencies
|
|
26
|
+
- Updated `@mcp-abap-adt/interfaces` to `^0.2.4` for headless browser mode support
|
|
27
|
+
- Updated `@mcp-abap-adt/auth-providers` to `^0.2.3` (devDependency, tests only) for headless mode implementation
|
|
28
|
+
|
|
29
|
+
## [0.2.5] - 2025-12-20
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
- **`allowBrowserAuth` Option**: New configuration option to control browser-based authentication
|
|
33
|
+
- When `allowBrowserAuth: false`, broker throws `BROWSER_AUTH_REQUIRED` error instead of blocking on browser auth
|
|
34
|
+
- Useful for headless/non-interactive environments (e.g., MCP stdio transport with Cline)
|
|
35
|
+
- Error includes `code: 'BROWSER_AUTH_REQUIRED'` and `destination` property for programmatic handling
|
|
36
|
+
- Broker still works with valid session tokens or refresh tokens when browser auth is disabled
|
|
15
37
|
|
|
16
38
|
### Dependencies
|
|
17
|
-
- Updated `@mcp-abap-adt/auth-providers` to `^0.2.
|
|
39
|
+
- Updated `@mcp-abap-adt/auth-providers` to `^0.2.2` for automatic port selection, improved server shutdown, and process termination cleanup
|
|
18
40
|
- Browser auth server now automatically finds an available port if the requested port is in use
|
|
19
41
|
- Improved server shutdown ensures ports are properly freed after authentication completes
|
|
20
42
|
- Prevents `EADDRINUSE` errors when multiple stdio servers run simultaneously
|
package/README.md
CHANGED
|
@@ -53,12 +53,12 @@ const broker = new AuthBroker({
|
|
|
53
53
|
tokenProvider: new BtpTokenProvider(), // optional
|
|
54
54
|
}, 'chrome', logger);
|
|
55
55
|
|
|
56
|
-
// Disable
|
|
57
|
-
const
|
|
56
|
+
// Disable browser authentication for headless/stdio environments (e.g., MCP with Cline)
|
|
57
|
+
const brokerNoBrowser = new AuthBroker({
|
|
58
58
|
sessionStore: new AbapSessionStore('/path/to/destinations'),
|
|
59
59
|
serviceKeyStore: new AbapServiceKeyStore('/path/to/destinations'),
|
|
60
60
|
tokenProvider: new BtpTokenProvider(),
|
|
61
|
-
|
|
61
|
+
allowBrowserAuth: false, // Throws BROWSER_AUTH_REQUIRED if browser auth needed
|
|
62
62
|
}, 'chrome', logger);
|
|
63
63
|
```
|
|
64
64
|
|
|
@@ -368,7 +368,9 @@ new AuthBroker(
|
|
|
368
368
|
- `sessionStore` - **Required** - Store for session data. Must contain initial session with `serviceUrl`
|
|
369
369
|
- `serviceKeyStore` - **Optional** - Store for service keys. Only needed for initializing sessions from service keys
|
|
370
370
|
- `tokenProvider` - **Optional** - Token provider for token acquisition. Only needed for browser authentication or when direct UAA requests fail
|
|
371
|
-
- `browser` - Optional browser name for authentication (`chrome`, `edge`, `firefox`, `system`, `none`). Default: `system`
|
|
371
|
+
- `browser` - Optional browser name for authentication (`chrome`, `edge`, `firefox`, `system`, `headless`, `none`). Default: `system`
|
|
372
|
+
- Use `'headless'` for SSH/remote sessions - logs URL and waits for manual callback
|
|
373
|
+
- Use `'none'` for automated tests - logs URL and rejects immediately
|
|
372
374
|
- For XSUAA, browser is not used (client_credentials grant type) - use `'none'`
|
|
373
375
|
- `logger` - Optional logger instance. If not provided, uses no-op logger
|
|
374
376
|
|
|
@@ -456,6 +458,13 @@ try {
|
|
|
456
458
|
- `BROWSER_AUTH_ERROR` - Browser authentication failed or cancelled (logged, throws)
|
|
457
459
|
- `REFRESH_ERROR` - Token refresh failed at UAA server (logged, throws)
|
|
458
460
|
|
|
461
|
+
**4. Browser Auth Disabled Errors** (when `allowBrowserAuth: false`):
|
|
462
|
+
- `BROWSER_AUTH_REQUIRED` - Browser authentication is required but disabled. Thrown when:
|
|
463
|
+
- **Step 0**: No token and no UAA credentials in session, service key exists but browser auth needed
|
|
464
|
+
- **Step 2b**: Refresh token expired/invalid and browser auth needed for new token
|
|
465
|
+
- Error includes `destination` property for context
|
|
466
|
+
- Use case: Non-interactive environments (MCP stdio, Cline) where browser cannot open
|
|
467
|
+
|
|
459
468
|
**Defensive Design Principles:**
|
|
460
469
|
- **All external operations wrapped in try-catch**: Files may be missing/corrupted, network may fail
|
|
461
470
|
- **Graceful degradation**: Store errors trigger fallback mechanisms (serviceKey → session → provider)
|
package/dist/AuthBroker.d.ts
CHANGED
|
@@ -14,6 +14,12 @@ export interface AuthBrokerConfig {
|
|
|
14
14
|
serviceKeyStore?: IServiceKeyStore;
|
|
15
15
|
/** Token provider (required) - handles token refresh and authentication flows through browser-based authorization (e.g., XSUAA provider) */
|
|
16
16
|
tokenProvider: ITokenProvider;
|
|
17
|
+
/**
|
|
18
|
+
* Allow browser-based authentication (optional, default: true)
|
|
19
|
+
* When false, getToken() will throw BROWSER_AUTH_REQUIRED error instead of blocking on browser auth.
|
|
20
|
+
* Use this for headless/non-interactive environments (e.g., MCP stdio transport).
|
|
21
|
+
*/
|
|
22
|
+
allowBrowserAuth?: boolean;
|
|
17
23
|
}
|
|
18
24
|
/**
|
|
19
25
|
* AuthBroker manages JWT authentication tokens for destinations
|
|
@@ -24,15 +30,17 @@ export declare class AuthBroker {
|
|
|
24
30
|
private serviceKeyStore;
|
|
25
31
|
private sessionStore;
|
|
26
32
|
private tokenProvider;
|
|
33
|
+
private allowBrowserAuth;
|
|
27
34
|
/**
|
|
28
35
|
* Create a new AuthBroker instance
|
|
29
36
|
* @param config Configuration object with stores and token provider
|
|
30
37
|
* - sessionStore: Store for session data (required)
|
|
31
38
|
* - serviceKeyStore: Store for service keys (optional)
|
|
32
39
|
* - tokenProvider: Token provider implementing ITokenProvider interface (required) - handles browser-based authorization
|
|
33
|
-
* @param browser Optional browser name for authentication (chrome, edge, firefox, system, none).
|
|
40
|
+
* @param browser Optional browser name for authentication (chrome, edge, firefox, system, headless, none).
|
|
34
41
|
* Default: 'system' (system default browser).
|
|
35
|
-
* Use '
|
|
42
|
+
* Use 'headless' for SSH/remote sessions - logs URL and waits for manual callback.
|
|
43
|
+
* Use 'none' for automated tests - logs URL and rejects immediately.
|
|
36
44
|
* @param logger Optional logger instance implementing ILogger interface. If not provided, uses no-op logger.
|
|
37
45
|
*/
|
|
38
46
|
constructor(config: AuthBrokerConfig, browser?: string, logger?: ILogger);
|
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,OAAO,EAA8C,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC/G,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAa7C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,YAAY,EAAE,aAAa,CAAC;IAC5B,uEAAuE;IACvE,eAAe,CAAC,EAAE,gBAAgB,CAAC;IACnC,4IAA4I;IAC5I,aAAa,EAAE,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"AuthBroker.d.ts","sourceRoot":"","sources":["../src/AuthBroker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAA8C,MAAM,0BAA0B,CAAC;AAC/F,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC/G,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAa7C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,YAAY,EAAE,aAAa,CAAC;IAC5B,uEAAuE;IACvE,eAAe,CAAC,EAAE,gBAAgB,CAAC;IACnC,4IAA4I;IAC5I,aAAa,EAAE,cAAc,CAAC;IAC9B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,YAAY,CAAgB;IACpC,OAAO,CAAC,aAAa,CAAiB;IACtC,OAAO,CAAC,gBAAgB,CAAU;IAElC;;;;;;;;;;;OAWG;gBAED,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,OAAO;IAuElB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACG,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgYpD;;;;;OAKG;IACG,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAOxD;;;;OAIG;IACG,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IA4CvF;;;;OAIG;IACG,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;CA0ClF"}
|
package/dist/AuthBroker.js
CHANGED
|
@@ -23,15 +23,17 @@ class AuthBroker {
|
|
|
23
23
|
serviceKeyStore;
|
|
24
24
|
sessionStore;
|
|
25
25
|
tokenProvider;
|
|
26
|
+
allowBrowserAuth;
|
|
26
27
|
/**
|
|
27
28
|
* Create a new AuthBroker instance
|
|
28
29
|
* @param config Configuration object with stores and token provider
|
|
29
30
|
* - sessionStore: Store for session data (required)
|
|
30
31
|
* - serviceKeyStore: Store for service keys (optional)
|
|
31
32
|
* - tokenProvider: Token provider implementing ITokenProvider interface (required) - handles browser-based authorization
|
|
32
|
-
* @param browser Optional browser name for authentication (chrome, edge, firefox, system, none).
|
|
33
|
+
* @param browser Optional browser name for authentication (chrome, edge, firefox, system, headless, none).
|
|
33
34
|
* Default: 'system' (system default browser).
|
|
34
|
-
* Use '
|
|
35
|
+
* Use 'headless' for SSH/remote sessions - logs URL and waits for manual callback.
|
|
36
|
+
* Use 'none' for automated tests - logs URL and rejects immediately.
|
|
35
37
|
* @param logger Optional logger instance implementing ILogger interface. If not provided, uses no-op logger.
|
|
36
38
|
*/
|
|
37
39
|
constructor(config, browser, logger) {
|
|
@@ -86,6 +88,7 @@ class AuthBroker {
|
|
|
86
88
|
this.tokenProvider = tokenProvider;
|
|
87
89
|
this.browser = browser || 'system';
|
|
88
90
|
this.logger = logger || noOpLogger;
|
|
91
|
+
this.allowBrowserAuth = config.allowBrowserAuth ?? true;
|
|
89
92
|
// Log successful initialization
|
|
90
93
|
const hasServiceKeyStore = !!this.serviceKeyStore;
|
|
91
94
|
this.logger?.debug(`AuthBroker initialized: sessionStore(ok), serviceKeyStore(${hasServiceKeyStore ? 'ok' : 'none'}), tokenProvider(ok)`);
|
|
@@ -213,6 +216,15 @@ class AuthBroker {
|
|
|
213
216
|
this.logger?.error(`Step 0: Service key for ${destination} missing UAA credentials`);
|
|
214
217
|
throw new Error(`Service key for destination "${destination}" does not contain UAA credentials`);
|
|
215
218
|
}
|
|
219
|
+
// Check if browser auth is allowed
|
|
220
|
+
if (!this.allowBrowserAuth) {
|
|
221
|
+
const error = new Error(`Browser authentication required for destination "${destination}" but allowBrowserAuth is disabled. ` +
|
|
222
|
+
`Either enable browser auth or provide a valid session with token.`);
|
|
223
|
+
error.code = 'BROWSER_AUTH_REQUIRED';
|
|
224
|
+
error.destination = destination;
|
|
225
|
+
this.logger?.error(`Step 0: Browser auth required but disabled for ${destination}`);
|
|
226
|
+
throw error;
|
|
227
|
+
}
|
|
216
228
|
// Use tokenProvider for browser-based authentication
|
|
217
229
|
this.logger?.debug(`Step 0: Authenticating via provider (browser) for ${destination} using service key UAA credentials`);
|
|
218
230
|
let tokenResult;
|
|
@@ -268,6 +280,10 @@ class AuthBroker {
|
|
|
268
280
|
return tokenResult.connectionConfig.authorizationToken;
|
|
269
281
|
}
|
|
270
282
|
catch (error) {
|
|
283
|
+
// Re-throw BROWSER_AUTH_REQUIRED error without wrapping
|
|
284
|
+
if (error.code === 'BROWSER_AUTH_REQUIRED') {
|
|
285
|
+
throw error;
|
|
286
|
+
}
|
|
271
287
|
// Handle typed store errors
|
|
272
288
|
if (error.code === interfaces_1.STORE_ERROR_CODES.FILE_NOT_FOUND) {
|
|
273
289
|
this.logger?.error(`Step 0: Service key file not found for ${destination}: ${error.filePath || 'unknown path'}`);
|
|
@@ -408,6 +424,16 @@ class AuthBroker {
|
|
|
408
424
|
this.logger?.debug(`Step 2a: No refresh token in session for ${destination}, skipping to service key refresh`);
|
|
409
425
|
}
|
|
410
426
|
// Try refresh from service key (browser authentication)
|
|
427
|
+
// Check if browser auth is allowed
|
|
428
|
+
if (!this.allowBrowserAuth) {
|
|
429
|
+
const error = new Error(`Browser authentication required for destination "${destination}" but allowBrowserAuth is disabled. ` +
|
|
430
|
+
`Token refresh via session failed and browser auth is not allowed. ` +
|
|
431
|
+
`Either enable browser auth or ensure a valid refresh token exists in session.`);
|
|
432
|
+
error.code = 'BROWSER_AUTH_REQUIRED';
|
|
433
|
+
error.destination = destination;
|
|
434
|
+
this.logger?.error(`Step 2b: Browser auth required but disabled for ${destination}`);
|
|
435
|
+
throw error;
|
|
436
|
+
}
|
|
411
437
|
try {
|
|
412
438
|
this.logger?.debug(`Step 2b: Trying refreshTokenFromServiceKey for ${destination}`);
|
|
413
439
|
const tokenResult = await this.tokenProvider.refreshTokenFromServiceKey(uaaCredentials, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-abap-adt/auth-broker",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.7",
|
|
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,11 +51,11 @@
|
|
|
51
51
|
"node": ">=18.0.0"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@mcp-abap-adt/interfaces": "^0.2.
|
|
54
|
+
"@mcp-abap-adt/interfaces": "^0.2.4",
|
|
55
55
|
"axios": "^1.13.2"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@mcp-abap-adt/auth-providers": "^0.2.
|
|
58
|
+
"@mcp-abap-adt/auth-providers": "^0.2.3",
|
|
59
59
|
"@mcp-abap-adt/auth-stores": "^0.2.5",
|
|
60
60
|
"@types/express": "^5.0.5",
|
|
61
61
|
"@types/jest": "^30.0.0",
|