@mcp-abap-adt/auth-providers 0.1.0
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 +50 -0
- package/LICENSE +22 -0
- package/README.md +200 -0
- package/dist/__tests__/helpers/configHelpers.d.ts +51 -0
- package/dist/__tests__/helpers/configHelpers.d.ts.map +1 -0
- package/dist/__tests__/helpers/configHelpers.js +186 -0
- package/dist/auth/browserAuth.d.ts +17 -0
- package/dist/auth/browserAuth.d.ts.map +1 -0
- package/dist/auth/browserAuth.js +401 -0
- package/dist/auth/clientCredentialsAuth.d.ts +19 -0
- package/dist/auth/clientCredentialsAuth.d.ts.map +1 -0
- package/dist/auth/clientCredentialsAuth.js +55 -0
- package/dist/auth/tokenRefresher.d.ts +17 -0
- package/dist/auth/tokenRefresher.d.ts.map +1 -0
- package/dist/auth/tokenRefresher.js +53 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/providers/BtpTokenProvider.d.ts +18 -0
- package/dist/providers/BtpTokenProvider.d.ts.map +1 -0
- package/dist/providers/BtpTokenProvider.js +89 -0
- package/dist/providers/XsuaaTokenProvider.d.ts +18 -0
- package/dist/providers/XsuaaTokenProvider.d.ts.map +1 -0
- package/dist/providers/XsuaaTokenProvider.js +83 -0
- package/package.json +70 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2024-12-04
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Initial release
|
|
14
|
+
- **XsuaaTokenProvider** - Uses `client_credentials` grant type (no browser required)
|
|
15
|
+
- **BtpTokenProvider** - Uses browser-based OAuth2 or refresh token flow
|
|
16
|
+
- Browser authentication flow with OAuth2 callback server
|
|
17
|
+
- Client credentials authentication
|
|
18
|
+
- Token refresh functionality
|
|
19
|
+
- Token validation (`validateToken` method)
|
|
20
|
+
- **Integration Tests**:
|
|
21
|
+
- Integration tests for all providers using real files from `test-config.yaml`
|
|
22
|
+
- Test configuration helpers (`configHelpers.ts`) matching auth-broker format
|
|
23
|
+
- YAML-based test configuration (`tests/test-config.yaml.template`)
|
|
24
|
+
- Tests for service key to session conversion
|
|
25
|
+
- Tests for token validation
|
|
26
|
+
- BTP tests use `BtpServiceKeyStore` and `BtpSessionStore` (without `sapUrl`)
|
|
27
|
+
- ABAP tests use `AbapServiceKeyStore` and `AbapSessionStore` (with `sapUrl`)
|
|
28
|
+
- BTP tests use `xsuaa.btp_destination` from config
|
|
29
|
+
- ABAP tests use `abap.destination` from config
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
- **Integration Tests**: Corrected BTP and ABAP test separation
|
|
33
|
+
- BTP tests correctly handle base BTP sessions (no `sapUrl` required)
|
|
34
|
+
- ABAP tests correctly handle ABAP sessions (with `sapUrl` from service key)
|
|
35
|
+
- **Token Validation**: BTP tests now handle cases where `serviceUrl` may not be available (base BTP)
|
|
36
|
+
- **Session Storage**: BTP tests no longer attempt to save `serviceUrl` to `BtpSessionStore` (which doesn't accept `sapUrl`)
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
- **Documentation**: Updated README to clarify BTP vs ABAP differences and correct store usage
|
|
40
|
+
- Added explicit examples showing BTP and ABAP as separate entities
|
|
41
|
+
- Clarified that BTP uses `BtpServiceKeyStore`/`BtpSessionStore` (without `sapUrl`)
|
|
42
|
+
- Clarified that ABAP uses `AbapServiceKeyStore`/`AbapSessionStore` (with `sapUrl`)
|
|
43
|
+
- Updated integration test configuration examples
|
|
44
|
+
|
|
45
|
+
### Dependencies
|
|
46
|
+
- `@mcp-abap-adt/auth-broker` ^0.1.6 - Interface definitions
|
|
47
|
+
- `@mcp-abap-adt/auth-stores` ^0.1.2 - Store implementations
|
|
48
|
+
- `@mcp-abap-adt/connection` ^0.1.13 - Connection utilities
|
|
49
|
+
- `@mcp-abap-adt/logger` ^0.1.0 - Logging utilities
|
|
50
|
+
|
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Oleksii Kyslytsia
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# @mcp-abap-adt/auth-providers
|
|
2
|
+
|
|
3
|
+
Token providers for MCP ABAP ADT auth-broker - XSUAA and BTP token providers.
|
|
4
|
+
|
|
5
|
+
This package provides token provider implementations for the `@mcp-abap-adt/auth-broker` package.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @mcp-abap-adt/auth-providers
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Overview
|
|
14
|
+
|
|
15
|
+
This package implements the `ITokenProvider` interface from `@mcp-abap-adt/auth-broker`:
|
|
16
|
+
|
|
17
|
+
- **XsuaaTokenProvider** - Uses `client_credentials` grant type (no browser required)
|
|
18
|
+
- **BtpTokenProvider** - Uses browser-based OAuth2 or refresh token flow
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
### Basic Usage
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { AuthBroker } from '@mcp-abap-adt/auth-broker';
|
|
26
|
+
import { XsuaaTokenProvider, BtpTokenProvider } from '@mcp-abap-adt/auth-providers';
|
|
27
|
+
|
|
28
|
+
// Use XSUAA provider (client_credentials)
|
|
29
|
+
const xsuaaBroker = new AuthBroker({
|
|
30
|
+
tokenProvider: new XsuaaTokenProvider(),
|
|
31
|
+
}, 'none'); // Browser not needed
|
|
32
|
+
|
|
33
|
+
// Use BTP provider (browser OAuth2 or refresh token)
|
|
34
|
+
const btpBroker = new AuthBroker({
|
|
35
|
+
tokenProvider: new BtpTokenProvider(),
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### With Stores
|
|
40
|
+
|
|
41
|
+
**Important**: BTP and ABAP are different entities:
|
|
42
|
+
- **BTP** (base BTP) - uses `BtpServiceKeyStore` and `BtpSessionStore` (without `sapUrl`)
|
|
43
|
+
- **ABAP** - uses `AbapServiceKeyStore` and `AbapSessionStore` (with `sapUrl`)
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { AuthBroker } from '@mcp-abap-adt/auth-broker';
|
|
47
|
+
import { XsuaaTokenProvider, BtpTokenProvider } from '@mcp-abap-adt/auth-providers';
|
|
48
|
+
import {
|
|
49
|
+
XsuaaServiceKeyStore,
|
|
50
|
+
XsuaaSessionStore,
|
|
51
|
+
BtpServiceKeyStore,
|
|
52
|
+
BtpSessionStore,
|
|
53
|
+
AbapServiceKeyStore,
|
|
54
|
+
AbapSessionStore
|
|
55
|
+
} from '@mcp-abap-adt/auth-stores';
|
|
56
|
+
|
|
57
|
+
// XSUAA provider with stores
|
|
58
|
+
const xsuaaServiceKeyStore = new XsuaaServiceKeyStore('/path/to/service-keys');
|
|
59
|
+
const xsuaaSessionStore = new XsuaaSessionStore('/path/to/sessions');
|
|
60
|
+
|
|
61
|
+
const xsuaaBroker = new AuthBroker({
|
|
62
|
+
serviceKeyStore: xsuaaServiceKeyStore,
|
|
63
|
+
sessionStore: xsuaaSessionStore,
|
|
64
|
+
tokenProvider: new XsuaaTokenProvider(),
|
|
65
|
+
}, 'none');
|
|
66
|
+
|
|
67
|
+
// BTP provider with stores (base BTP, without sapUrl)
|
|
68
|
+
const btpServiceKeyStore = new BtpServiceKeyStore('/path/to/service-keys');
|
|
69
|
+
const btpSessionStore = new BtpSessionStore('/path/to/sessions');
|
|
70
|
+
|
|
71
|
+
const btpBroker = new AuthBroker({
|
|
72
|
+
serviceKeyStore: btpServiceKeyStore,
|
|
73
|
+
sessionStore: btpSessionStore,
|
|
74
|
+
tokenProvider: new BtpTokenProvider(),
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// ABAP provider with stores (with sapUrl)
|
|
78
|
+
const abapServiceKeyStore = new AbapServiceKeyStore('/path/to/service-keys');
|
|
79
|
+
const abapSessionStore = new AbapSessionStore('/path/to/sessions');
|
|
80
|
+
|
|
81
|
+
const abapBroker = new AuthBroker({
|
|
82
|
+
serviceKeyStore: abapServiceKeyStore,
|
|
83
|
+
sessionStore: abapSessionStore,
|
|
84
|
+
tokenProvider: new BtpTokenProvider(), // BtpTokenProvider works for ABAP too
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Token Providers
|
|
89
|
+
|
|
90
|
+
#### XsuaaTokenProvider
|
|
91
|
+
|
|
92
|
+
Uses `client_credentials` grant type - no browser interaction required:
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import { XsuaaTokenProvider } from '@mcp-abap-adt/auth-providers';
|
|
96
|
+
import type { IAuthorizationConfig } from '@mcp-abap-adt/auth-broker';
|
|
97
|
+
|
|
98
|
+
const provider = new XsuaaTokenProvider();
|
|
99
|
+
|
|
100
|
+
const authConfig: IAuthorizationConfig = {
|
|
101
|
+
uaaUrl: 'https://...authentication...hana.ondemand.com',
|
|
102
|
+
uaaClientId: '...',
|
|
103
|
+
uaaClientSecret: '...',
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const result = await provider.getConnectionConfig(authConfig, {
|
|
107
|
+
logger: defaultLogger,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// result.connectionConfig.authorizationToken contains the JWT token
|
|
111
|
+
// result.refreshToken is undefined (client_credentials doesn't provide refresh tokens)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
#### BtpTokenProvider
|
|
115
|
+
|
|
116
|
+
Uses browser-based OAuth2 flow or refresh token:
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
import { BtpTokenProvider } from '@mcp-abap-adt/auth-providers';
|
|
120
|
+
import type { IAuthorizationConfig } from '@mcp-abap-adt/auth-broker';
|
|
121
|
+
|
|
122
|
+
const provider = new BtpTokenProvider();
|
|
123
|
+
|
|
124
|
+
const authConfig: IAuthorizationConfig = {
|
|
125
|
+
uaaUrl: 'https://...authentication...hana.ondemand.com',
|
|
126
|
+
uaaClientId: '...',
|
|
127
|
+
uaaClientSecret: '...',
|
|
128
|
+
refreshToken: '...', // Optional - if provided, uses refresh flow instead of browser
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// If refreshToken is provided, uses refresh flow (no browser)
|
|
132
|
+
// Otherwise, opens browser for OAuth2 authorization
|
|
133
|
+
const result = await provider.getConnectionConfig(authConfig, {
|
|
134
|
+
logger: defaultLogger,
|
|
135
|
+
browser: 'system', // 'system', 'none', or undefined
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// result.connectionConfig.authorizationToken contains the JWT token
|
|
139
|
+
// result.refreshToken contains refresh token (if browser flow was used)
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Token Validation
|
|
143
|
+
|
|
144
|
+
Both providers support token validation:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
const isValid = await provider.validateToken(token, serviceUrl);
|
|
148
|
+
// Returns true if token is valid (200-299 status), false otherwise
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Testing
|
|
152
|
+
|
|
153
|
+
The package includes both unit tests (with mocks) and integration tests (with real files and services).
|
|
154
|
+
|
|
155
|
+
### Unit Tests
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npm test
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Integration Tests
|
|
162
|
+
|
|
163
|
+
Integration tests work with real files from `tests/test-config.yaml`:
|
|
164
|
+
|
|
165
|
+
1. Copy `tests/test-config.yaml.template` to `tests/test-config.yaml`
|
|
166
|
+
2. Fill in real paths, destinations, and URLs
|
|
167
|
+
3. Run tests - integration tests will use real services if configured
|
|
168
|
+
|
|
169
|
+
```yaml
|
|
170
|
+
auth_broker:
|
|
171
|
+
paths:
|
|
172
|
+
service_keys_dir: ~/.config/mcp-abap-adt/service-keys/
|
|
173
|
+
sessions_dir: ~/.config/mcp-abap-adt/sessions/
|
|
174
|
+
abap:
|
|
175
|
+
destination: "TRIAL" # For ABAP tests (uses AbapServiceKeyStore, AbapSessionStore)
|
|
176
|
+
xsuaa:
|
|
177
|
+
btp_destination: "mcp" # For BTP tests (uses BtpServiceKeyStore, BtpSessionStore)
|
|
178
|
+
mcp_url: "https://..."
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Integration tests will skip if `test-config.yaml` is not configured or contains placeholder values.
|
|
182
|
+
|
|
183
|
+
**Note**:
|
|
184
|
+
- BTP integration tests use `xsuaa.btp_destination` and require `BtpServiceKeyStore`/`BtpSessionStore` (without `sapUrl`)
|
|
185
|
+
- ABAP integration tests use `abap.destination` and require `AbapServiceKeyStore`/`AbapSessionStore` (with `sapUrl`)
|
|
186
|
+
- BTP/ABAP integration tests may open a browser for authentication if no refresh token is available. This is expected behavior.
|
|
187
|
+
|
|
188
|
+
## Dependencies
|
|
189
|
+
|
|
190
|
+
- `@mcp-abap-adt/auth-broker` (^0.1.6) - Interface definitions
|
|
191
|
+
- `@mcp-abap-adt/auth-stores` (^0.1.2) - Store implementations
|
|
192
|
+
- `@mcp-abap-adt/connection` (^0.1.13) - Connection utilities
|
|
193
|
+
- `@mcp-abap-adt/logger` (^0.1.0) - Logging utilities
|
|
194
|
+
- `axios` - HTTP client
|
|
195
|
+
- `express` - OAuth2 callback server
|
|
196
|
+
- `open` - Browser opening utility
|
|
197
|
+
|
|
198
|
+
## License
|
|
199
|
+
|
|
200
|
+
MIT
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration helpers for auth-providers tests
|
|
3
|
+
* Loads test configuration from test-config.yaml (same format as auth-broker)
|
|
4
|
+
*/
|
|
5
|
+
export interface TestConfig {
|
|
6
|
+
auth_broker?: {
|
|
7
|
+
paths?: {
|
|
8
|
+
service_keys_dir?: string;
|
|
9
|
+
sessions_dir?: string;
|
|
10
|
+
};
|
|
11
|
+
abap?: {
|
|
12
|
+
destination?: string;
|
|
13
|
+
};
|
|
14
|
+
xsuaa?: {
|
|
15
|
+
btp_destination?: string;
|
|
16
|
+
mcp_destination?: string;
|
|
17
|
+
mcp_url?: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Load test configuration from YAML
|
|
23
|
+
* Uses test-config.yaml from tests/ directory
|
|
24
|
+
*/
|
|
25
|
+
export declare function loadTestConfig(): TestConfig;
|
|
26
|
+
/**
|
|
27
|
+
* Check if test config has real values (not placeholders)
|
|
28
|
+
*/
|
|
29
|
+
export declare function hasRealConfig(config: TestConfig, section: 'abap' | 'xsuaa'): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get ABAP destination from config
|
|
32
|
+
*/
|
|
33
|
+
export declare function getAbapDestination(config?: TestConfig): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Get XSUAA destinations from config
|
|
36
|
+
*/
|
|
37
|
+
export declare function getXsuaaDestinations(config?: TestConfig): {
|
|
38
|
+
btp_destination: string | null;
|
|
39
|
+
mcp_url: string | null;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Get service keys directory from config
|
|
43
|
+
* Expands ~ to home directory
|
|
44
|
+
*/
|
|
45
|
+
export declare function getServiceKeysDir(config?: TestConfig): string | null;
|
|
46
|
+
/**
|
|
47
|
+
* Get sessions directory from config
|
|
48
|
+
* Expands ~ to home directory
|
|
49
|
+
*/
|
|
50
|
+
export declare function getSessionsDir(config?: TestConfig): string | null;
|
|
51
|
+
//# sourceMappingURL=configHelpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configHelpers.d.ts","sourceRoot":"","sources":["../../../src/__tests__/helpers/configHelpers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,UAAU;IACzB,WAAW,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE;YACN,gBAAgB,CAAC,EAAE,MAAM,CAAC;YAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;SACvB,CAAC;QACF,IAAI,CAAC,EAAE;YACL,WAAW,CAAC,EAAE,MAAM,CAAC;SACtB,CAAC;QACF,KAAK,CAAC,EAAE;YACN,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,eAAe,CAAC,EAAE,MAAM,CAAC;YACzB,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,CAAC;KACH,CAAC;CACH;AAkBD;;;GAGG;AACH,wBAAgB,cAAc,IAAI,UAAU,CA6C3C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAwBpF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAGrE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG;IACzD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,CAOA;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAYpE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAYjE"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration helpers for auth-providers tests
|
|
4
|
+
* Loads test configuration from test-config.yaml (same format as auth-broker)
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.loadTestConfig = loadTestConfig;
|
|
41
|
+
exports.hasRealConfig = hasRealConfig;
|
|
42
|
+
exports.getAbapDestination = getAbapDestination;
|
|
43
|
+
exports.getXsuaaDestinations = getXsuaaDestinations;
|
|
44
|
+
exports.getServiceKeysDir = getServiceKeysDir;
|
|
45
|
+
exports.getSessionsDir = getSessionsDir;
|
|
46
|
+
const fs = __importStar(require("fs"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const yaml = __importStar(require("js-yaml"));
|
|
49
|
+
let cachedConfig = null;
|
|
50
|
+
/**
|
|
51
|
+
* Find project root directory by looking for package.json
|
|
52
|
+
*/
|
|
53
|
+
function findProjectRoot() {
|
|
54
|
+
let currentDir = __dirname;
|
|
55
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
56
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
57
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
58
|
+
return currentDir;
|
|
59
|
+
}
|
|
60
|
+
currentDir = path.dirname(currentDir);
|
|
61
|
+
}
|
|
62
|
+
// Fallback to process.cwd() if package.json not found
|
|
63
|
+
return process.cwd();
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Load test configuration from YAML
|
|
67
|
+
* Uses test-config.yaml from tests/ directory
|
|
68
|
+
*/
|
|
69
|
+
function loadTestConfig() {
|
|
70
|
+
if (cachedConfig) {
|
|
71
|
+
return cachedConfig;
|
|
72
|
+
}
|
|
73
|
+
// Find project root and load from tests/test-config.yaml
|
|
74
|
+
const projectRoot = findProjectRoot();
|
|
75
|
+
const configPath = path.resolve(projectRoot, 'tests', 'test-config.yaml');
|
|
76
|
+
const templatePath = path.resolve(projectRoot, 'tests', 'test-config.yaml.template');
|
|
77
|
+
if (process.env.TEST_VERBOSE) {
|
|
78
|
+
console.log(`[configHelpers] Project root: ${projectRoot}`);
|
|
79
|
+
console.log(`[configHelpers] Config path: ${configPath}`);
|
|
80
|
+
console.log(`[configHelpers] Config exists: ${fs.existsSync(configPath)}`);
|
|
81
|
+
}
|
|
82
|
+
if (fs.existsSync(configPath)) {
|
|
83
|
+
try {
|
|
84
|
+
const configContent = fs.readFileSync(configPath, 'utf8');
|
|
85
|
+
cachedConfig = yaml.load(configContent) || {};
|
|
86
|
+
if (process.env.TEST_VERBOSE) {
|
|
87
|
+
console.log(`[configHelpers] Loaded config:`, JSON.stringify(cachedConfig, null, 2));
|
|
88
|
+
}
|
|
89
|
+
return cachedConfig;
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.warn(`Failed to load test config from ${configPath}:`, error);
|
|
93
|
+
return {};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (fs.existsSync(templatePath)) {
|
|
97
|
+
console.warn('⚠️ tests/test-config.yaml not found. Using template (all integration tests will be disabled).');
|
|
98
|
+
try {
|
|
99
|
+
const templateContent = fs.readFileSync(templatePath, 'utf8');
|
|
100
|
+
cachedConfig = yaml.load(templateContent) || {};
|
|
101
|
+
return cachedConfig;
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
console.warn(`Failed to load test config template from ${templatePath}:`, error);
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
console.warn('⚠️ Test configuration files not found.');
|
|
109
|
+
console.warn('Please create tests/test-config.yaml with test parameters.');
|
|
110
|
+
return {};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Check if test config has real values (not placeholders)
|
|
114
|
+
*/
|
|
115
|
+
function hasRealConfig(config, section) {
|
|
116
|
+
if (!config.auth_broker) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
if (section === 'abap') {
|
|
120
|
+
const abap = config.auth_broker.abap;
|
|
121
|
+
if (!abap?.destination) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
// Check if destination is not a placeholder
|
|
125
|
+
return !abap.destination.includes('<') && !abap.destination.includes('>');
|
|
126
|
+
}
|
|
127
|
+
if (section === 'xsuaa') {
|
|
128
|
+
const xsuaa = config.auth_broker.xsuaa;
|
|
129
|
+
if (!xsuaa?.btp_destination) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
// Check if values are not placeholders
|
|
133
|
+
return !xsuaa.btp_destination.includes('<');
|
|
134
|
+
}
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get ABAP destination from config
|
|
139
|
+
*/
|
|
140
|
+
function getAbapDestination(config) {
|
|
141
|
+
const cfg = config || loadTestConfig();
|
|
142
|
+
return cfg.auth_broker?.abap?.destination || null;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Get XSUAA destinations from config
|
|
146
|
+
*/
|
|
147
|
+
function getXsuaaDestinations(config) {
|
|
148
|
+
const cfg = config || loadTestConfig();
|
|
149
|
+
const xsuaa = cfg.auth_broker?.xsuaa;
|
|
150
|
+
return {
|
|
151
|
+
btp_destination: xsuaa?.btp_destination || null,
|
|
152
|
+
mcp_url: xsuaa?.mcp_url || null,
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get service keys directory from config
|
|
157
|
+
* Expands ~ to home directory
|
|
158
|
+
*/
|
|
159
|
+
function getServiceKeysDir(config) {
|
|
160
|
+
const cfg = config || loadTestConfig();
|
|
161
|
+
const dir = cfg.auth_broker?.paths?.service_keys_dir;
|
|
162
|
+
if (!dir)
|
|
163
|
+
return null;
|
|
164
|
+
// Expand ~ to home directory
|
|
165
|
+
if (dir.startsWith('~')) {
|
|
166
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
167
|
+
return dir.replace('~', homeDir);
|
|
168
|
+
}
|
|
169
|
+
return dir;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get sessions directory from config
|
|
173
|
+
* Expands ~ to home directory
|
|
174
|
+
*/
|
|
175
|
+
function getSessionsDir(config) {
|
|
176
|
+
const cfg = config || loadTestConfig();
|
|
177
|
+
const dir = cfg.auth_broker?.paths?.sessions_dir;
|
|
178
|
+
if (!dir)
|
|
179
|
+
return null;
|
|
180
|
+
// Expand ~ to home directory
|
|
181
|
+
if (dir.startsWith('~')) {
|
|
182
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
183
|
+
return dir.replace('~', homeDir);
|
|
184
|
+
}
|
|
185
|
+
return dir;
|
|
186
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser authentication - OAuth2 flow for obtaining tokens
|
|
3
|
+
*/
|
|
4
|
+
import type { IAuthorizationConfig } from '@mcp-abap-adt/auth-broker';
|
|
5
|
+
import type { Logger } from '@mcp-abap-adt/logger';
|
|
6
|
+
/**
|
|
7
|
+
* Start browser authentication flow
|
|
8
|
+
* @param authConfig Authorization configuration with UAA credentials
|
|
9
|
+
* @param browser Browser name (chrome, edge, firefox, system, none)
|
|
10
|
+
* @param logger Optional logger instance. If not provided, uses default logger.
|
|
11
|
+
* @returns Promise that resolves to tokens
|
|
12
|
+
*/
|
|
13
|
+
export declare function startBrowserAuth(authConfig: IAuthorizationConfig, browser?: string, logger?: Logger): Promise<{
|
|
14
|
+
accessToken: string;
|
|
15
|
+
refreshToken?: string;
|
|
16
|
+
}>;
|
|
17
|
+
//# sourceMappingURL=browserAuth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browserAuth.d.ts","sourceRoot":"","sources":["../../src/auth/browserAuth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAkFnD;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,oBAAoB,EAChC,OAAO,GAAE,MAAiB,EAC1B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkSzD"}
|