@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.
- package/CHANGELOG.md +187 -0
- package/README.md +773 -77
- package/dist/auth/saml2Auth.d.ts +6 -2
- package/dist/auth/saml2Auth.d.ts.map +1 -1
- package/dist/auth/saml2Auth.js +9 -20
- package/dist/auth/samlBearerAssertion.d.ts.map +1 -1
- package/dist/auth/samlBearerAssertion.js +6 -2
- package/dist/auth/strictXml.d.ts +13 -0
- package/dist/auth/strictXml.d.ts.map +1 -0
- package/dist/auth/strictXml.js +21 -0
- package/dist/errors/AssertionValidationError.d.ts +15 -0
- package/dist/errors/AssertionValidationError.d.ts.map +1 -0
- package/dist/errors/AssertionValidationError.js +24 -0
- package/dist/errors/TokenProviderErrors.d.ts +2 -0
- package/dist/errors/TokenProviderErrors.d.ts.map +1 -1
- package/dist/errors/TokenProviderErrors.js +3 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/providers/Saml2BearerProvider.d.ts +1 -0
- package/dist/providers/Saml2BearerProvider.d.ts.map +1 -1
- package/dist/providers/Saml2BearerProvider.js +17 -2
- package/dist/providers/Saml2PureProvider.d.ts +1 -0
- package/dist/providers/Saml2PureProvider.d.ts.map +1 -1
- package/dist/providers/Saml2PureProvider.js +19 -5
- package/dist/providers/saml2Utils.d.ts +50 -2
- package/dist/providers/saml2Utils.d.ts.map +1 -1
- package/dist/providers/saml2Utils.js +102 -2
- package/dist/validation/assertionValidator.d.ts +28 -0
- package/dist/validation/assertionValidator.d.ts.map +1 -0
- package/dist/validation/assertionValidator.js +519 -0
- package/dist/validation/documentIds.d.ts +15 -0
- package/dist/validation/documentIds.d.ts.map +1 -0
- package/dist/validation/documentIds.js +32 -0
- package/dist/validation/inMemoryReplayStore.d.ts +22 -0
- package/dist/validation/inMemoryReplayStore.d.ts.map +1 -0
- package/dist/validation/inMemoryReplayStore.js +49 -0
- package/dist/validation/signedNode.d.ts +54 -0
- package/dist/validation/signedNode.d.ts.map +1 -0
- package/dist/validation/signedNode.js +182 -0
- package/dist/validation/xsdDateTime.d.ts +17 -0
- package/dist/validation/xsdDateTime.d.ts.map +1 -0
- package/dist/validation/xsdDateTime.js +67 -0
- package/package.json +5 -10
- package/bin/auth-authorization-code.ts +0 -147
- package/bin/auth-client-credentials.ts +0 -109
- package/bin/utils/parseConfig.ts +0 -270
package/bin/utils/parseConfig.ts
DELETED
|
@@ -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
|
-
|