@mcp-abap-adt/auth-providers 3.0.0 → 4.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +187 -0
  2. package/README.md +773 -77
  3. package/dist/auth/saml2Auth.d.ts +6 -2
  4. package/dist/auth/saml2Auth.d.ts.map +1 -1
  5. package/dist/auth/saml2Auth.js +9 -20
  6. package/dist/auth/samlBearerAssertion.d.ts.map +1 -1
  7. package/dist/auth/samlBearerAssertion.js +6 -2
  8. package/dist/auth/strictXml.d.ts +13 -0
  9. package/dist/auth/strictXml.d.ts.map +1 -0
  10. package/dist/auth/strictXml.js +21 -0
  11. package/dist/errors/AssertionValidationError.d.ts +15 -0
  12. package/dist/errors/AssertionValidationError.d.ts.map +1 -0
  13. package/dist/errors/AssertionValidationError.js +24 -0
  14. package/dist/errors/TokenProviderErrors.d.ts +2 -0
  15. package/dist/errors/TokenProviderErrors.d.ts.map +1 -1
  16. package/dist/errors/TokenProviderErrors.js +3 -1
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +11 -1
  20. package/dist/providers/Saml2BearerProvider.d.ts +1 -0
  21. package/dist/providers/Saml2BearerProvider.d.ts.map +1 -1
  22. package/dist/providers/Saml2BearerProvider.js +17 -2
  23. package/dist/providers/Saml2PureProvider.d.ts +1 -0
  24. package/dist/providers/Saml2PureProvider.d.ts.map +1 -1
  25. package/dist/providers/Saml2PureProvider.js +19 -5
  26. package/dist/providers/saml2Utils.d.ts +50 -2
  27. package/dist/providers/saml2Utils.d.ts.map +1 -1
  28. package/dist/providers/saml2Utils.js +102 -2
  29. package/dist/validation/assertionValidator.d.ts +28 -0
  30. package/dist/validation/assertionValidator.d.ts.map +1 -0
  31. package/dist/validation/assertionValidator.js +519 -0
  32. package/dist/validation/documentIds.d.ts +15 -0
  33. package/dist/validation/documentIds.d.ts.map +1 -0
  34. package/dist/validation/documentIds.js +32 -0
  35. package/dist/validation/inMemoryReplayStore.d.ts +22 -0
  36. package/dist/validation/inMemoryReplayStore.d.ts.map +1 -0
  37. package/dist/validation/inMemoryReplayStore.js +49 -0
  38. package/dist/validation/signedNode.d.ts +54 -0
  39. package/dist/validation/signedNode.d.ts.map +1 -0
  40. package/dist/validation/signedNode.js +182 -0
  41. package/dist/validation/xsdDateTime.d.ts +17 -0
  42. package/dist/validation/xsdDateTime.d.ts.map +1 -0
  43. package/dist/validation/xsdDateTime.js +67 -0
  44. package/package.json +5 -10
  45. package/bin/auth-authorization-code.ts +0 -147
  46. package/bin/auth-client-credentials.ts +0 -109
  47. package/bin/utils/parseConfig.ts +0 -270
@@ -1,270 +0,0 @@
1
- /**
2
- * Utility functions for parsing service keys and env files
3
- */
4
-
5
- import {
6
- ABAP_AUTHORIZATION_VARS,
7
- ABAP_CONNECTION_VARS,
8
- } from '@mcp-abap-adt/auth-stores';
9
- import * as fs from 'node:fs';
10
- import * as path from 'node:path';
11
-
12
- export interface ServiceKey {
13
- // Format 1: ABAP Environment service key (nested uaa object)
14
- uaa?: {
15
- url?: string;
16
- clientid?: string;
17
- clientsecret?: string;
18
- };
19
- // Format 2: XSUAA/BTP service key (flat structure)
20
- url?: string;
21
- clientid?: string;
22
- clientsecret?: string;
23
- // ABAP service URL
24
- sap_url?: string;
25
- }
26
-
27
- export interface EnvConfig {
28
- // ABAP Connection vars
29
- [ABAP_CONNECTION_VARS.SERVICE_URL]?: string;
30
- [ABAP_CONNECTION_VARS.AUTHORIZATION_TOKEN]?: string;
31
- [ABAP_CONNECTION_VARS.USERNAME]?: string;
32
- [ABAP_CONNECTION_VARS.PASSWORD]?: string;
33
- [ABAP_CONNECTION_VARS.SAP_CLIENT]?: string;
34
- [ABAP_CONNECTION_VARS.SAP_LANGUAGE]?: string;
35
- // ABAP Authorization vars
36
- [ABAP_AUTHORIZATION_VARS.UAA_URL]?: string;
37
- [ABAP_AUTHORIZATION_VARS.UAA_CLIENT_ID]?: string;
38
- [ABAP_AUTHORIZATION_VARS.UAA_CLIENT_SECRET]?: string;
39
- [ABAP_AUTHORIZATION_VARS.REFRESH_TOKEN]?: string;
40
- // Legacy support (for backward compatibility)
41
- UAA_URL?: string;
42
- UAA_CLIENT_ID?: string;
43
- UAA_CLIENT_SECRET?: string;
44
- SAP_URL?: string;
45
- SERVICE_URL?: string;
46
- AUTHORIZATION_TOKEN?: string;
47
- REFRESH_TOKEN?: string;
48
- }
49
-
50
- /**
51
- * Parse service key from JSON file
52
- */
53
- export function parseServiceKey(filePath: string): ServiceKey {
54
- const fullPath = path.resolve(filePath);
55
- if (!fs.existsSync(fullPath)) {
56
- throw new Error(`Service key file not found: ${fullPath}`);
57
- }
58
-
59
- const content = fs.readFileSync(fullPath, 'utf8');
60
- try {
61
- return JSON.parse(content) as ServiceKey;
62
- } catch (error) {
63
- throw new Error(
64
- `Failed to parse service key file: ${error instanceof Error ? error.message : String(error)}`,
65
- );
66
- }
67
- }
68
-
69
- /**
70
- * Parse .env file
71
- */
72
- export function parseEnvFile(filePath: string): EnvConfig {
73
- const fullPath = path.resolve(filePath);
74
- if (!fs.existsSync(fullPath)) {
75
- throw new Error(`Env file not found: ${fullPath}`);
76
- }
77
-
78
- const content = fs.readFileSync(fullPath, 'utf8');
79
- const config: EnvConfig = {};
80
-
81
- for (const line of content.split('\n')) {
82
- const trimmed = line.trim();
83
- if (!trimmed || trimmed.startsWith('#')) {
84
- continue;
85
- }
86
-
87
- const match = trimmed.match(/^([^=]+)=(.*)$/);
88
- if (match) {
89
- const key = match[1].trim();
90
- const value = match[2].trim().replace(/^["']|["']$/g, '');
91
- (config as Record<string, string>)[key] = value;
92
- }
93
- }
94
-
95
- return config;
96
- }
97
-
98
- /**
99
- * Get UAA credentials from service key or env file
100
- * Supports two service key formats:
101
- * 1. ABAP Environment: nested uaa object (uaa.url, uaa.clientid, uaa.clientsecret)
102
- * 2. XSUAA/BTP flat: top-level fields (url, clientid, clientsecret)
103
- */
104
- export function getUaaCredentials(
105
- serviceKey?: ServiceKey,
106
- envConfig?: EnvConfig,
107
- ): {
108
- uaaUrl: string;
109
- clientId: string;
110
- clientSecret: string;
111
- } {
112
- if (serviceKey) {
113
- // Format 1: ABAP Environment service key with nested uaa object
114
- if (serviceKey.uaa?.url && serviceKey.uaa?.clientid && serviceKey.uaa?.clientsecret) {
115
- return {
116
- uaaUrl: serviceKey.uaa.url,
117
- clientId: serviceKey.uaa.clientid,
118
- clientSecret: serviceKey.uaa.clientsecret,
119
- };
120
- }
121
-
122
- // Format 2: XSUAA/BTP flat service key (url is UAA URL, no nested uaa object)
123
- if (serviceKey.url && serviceKey.clientid && serviceKey.clientsecret) {
124
- return {
125
- uaaUrl: serviceKey.url,
126
- clientId: serviceKey.clientid,
127
- clientSecret: serviceKey.clientsecret,
128
- };
129
- }
130
-
131
- // Try to provide helpful error message
132
- const hasUaa = !!serviceKey.uaa;
133
- const hasFlat = !!(serviceKey.clientid || serviceKey.clientsecret);
134
- if (hasUaa) {
135
- throw new Error(
136
- 'Service key (ABAP format) missing required UAA fields: uaa.url, uaa.clientid, uaa.clientsecret',
137
- );
138
- } else if (hasFlat) {
139
- throw new Error(
140
- 'Service key (XSUAA format) missing required fields: url, clientid, clientsecret',
141
- );
142
- } else {
143
- throw new Error(
144
- 'Service key format not recognized. Expected either ABAP format (uaa.url, uaa.clientid, uaa.clientsecret) or XSUAA format (url, clientid, clientsecret)',
145
- );
146
- }
147
- }
148
-
149
- if (envConfig) {
150
- // Use constants from auth-stores, fallback to legacy names
151
- const uaaUrl =
152
- envConfig[ABAP_AUTHORIZATION_VARS.UAA_URL] || envConfig.UAA_URL;
153
- const clientId =
154
- envConfig[ABAP_AUTHORIZATION_VARS.UAA_CLIENT_ID] ||
155
- envConfig.UAA_CLIENT_ID;
156
- const clientSecret =
157
- envConfig[ABAP_AUTHORIZATION_VARS.UAA_CLIENT_SECRET] ||
158
- envConfig.UAA_CLIENT_SECRET;
159
-
160
- if (!uaaUrl || !clientId || !clientSecret) {
161
- throw new Error(
162
- `Env file missing required UAA fields: ${ABAP_AUTHORIZATION_VARS.UAA_URL}, ${ABAP_AUTHORIZATION_VARS.UAA_CLIENT_ID}, ${ABAP_AUTHORIZATION_VARS.UAA_CLIENT_SECRET}`,
163
- );
164
- }
165
-
166
- return { uaaUrl, clientId, clientSecret };
167
- }
168
-
169
- throw new Error('No service key or env config provided');
170
- }
171
-
172
- /**
173
- * Convert ABAP URL to ABAP-Web URL for ADT reentrancy ticket
174
- * @param url Original URL (may contain .abap. or .abap-web.)
175
- * @returns URL with .abap-web. domain
176
- */
177
- function convertToAbapWebUrl(url: string): string {
178
- // Replace .abap. with .abap-web. for ADT reentrancy ticket
179
- return url.replace(/\.abap\./g, '.abap-web.');
180
- }
181
-
182
- /**
183
- * Get service URL from service key or env file
184
- * For ADT, converts .abap. to .abap-web. if needed
185
- */
186
- export function getServiceUrl(
187
- serviceKey?: ServiceKey,
188
- envConfig?: EnvConfig,
189
- forAdt: boolean = false,
190
- ): string | undefined {
191
- let url: string | undefined;
192
-
193
- if (serviceKey) {
194
- url = serviceKey.url || serviceKey.sap_url;
195
- } else if (envConfig) {
196
- // Use constants from auth-stores, fallback to legacy names
197
- url =
198
- envConfig[ABAP_CONNECTION_VARS.SERVICE_URL] ||
199
- envConfig.SAP_URL ||
200
- envConfig.SERVICE_URL;
201
- }
202
-
203
- if (url && forAdt) {
204
- url = convertToAbapWebUrl(url);
205
- }
206
-
207
- return url;
208
- }
209
-
210
- /**
211
- * Write tokens to .env file
212
- */
213
- export function writeEnvFile(
214
- filePath: string,
215
- tokens: {
216
- authorizationToken?: string;
217
- refreshToken?: string;
218
- uaaUrl?: string;
219
- clientId?: string;
220
- clientSecret?: string;
221
- serviceUrl?: string;
222
- },
223
- ): void {
224
- const fullPath = path.resolve(filePath);
225
- const lines: string[] = [];
226
-
227
- // Read existing file if it exists
228
- const existing: EnvConfig = fs.existsSync(fullPath)
229
- ? parseEnvFile(fullPath)
230
- : {};
231
-
232
- // Update with new tokens using constants from auth-stores
233
- if (tokens.authorizationToken) {
234
- existing[ABAP_CONNECTION_VARS.AUTHORIZATION_TOKEN] =
235
- tokens.authorizationToken;
236
- }
237
- // Update refresh token only if provided (don't remove existing if not provided)
238
- if (tokens.refreshToken) {
239
- existing[ABAP_AUTHORIZATION_VARS.REFRESH_TOKEN] = tokens.refreshToken;
240
- }
241
- if (tokens.uaaUrl) {
242
- existing[ABAP_AUTHORIZATION_VARS.UAA_URL] = tokens.uaaUrl;
243
- }
244
- if (tokens.clientId) {
245
- existing[ABAP_AUTHORIZATION_VARS.UAA_CLIENT_ID] = tokens.clientId;
246
- }
247
- if (tokens.clientSecret) {
248
- existing[ABAP_AUTHORIZATION_VARS.UAA_CLIENT_SECRET] = tokens.clientSecret;
249
- }
250
- if (tokens.serviceUrl) {
251
- // Use SAP_URL as the standard name for ABAP systems
252
- existing[ABAP_CONNECTION_VARS.SERVICE_URL] = tokens.serviceUrl;
253
- }
254
-
255
- // Write all values
256
- for (const [key, value] of Object.entries(existing)) {
257
- if (value) {
258
- lines.push(`${key}=${value}`);
259
- }
260
- }
261
-
262
- // Ensure directory exists
263
- const dir = path.dirname(fullPath);
264
- if (!fs.existsSync(dir)) {
265
- fs.mkdirSync(dir, { recursive: true });
266
- }
267
-
268
- fs.writeFileSync(fullPath, lines.join('\n') + '\n', 'utf8');
269
- }
270
-