samlesa 2.16.6 → 2.17.1
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.
Potentially problematic release.
This version of samlesa might be problematic. Click here for more details.
- package/README.md +30 -50
- package/build/index.js +2 -1
- package/build/src/binding-artifact.js +330 -146
- package/build/src/binding-post.js +45 -31
- package/build/src/binding-redirect.js +0 -10
- package/build/src/binding-simplesign.js +0 -1
- package/build/src/entity-idp.js +1 -5
- package/build/src/entity-sp.js +21 -96
- package/build/src/extractor.js +48 -4
- package/build/src/flow.js +24 -166
- package/build/src/libsaml.js +468 -264
- package/build/src/libsamlSoap.js +115 -0
- package/build/src/schema/xml.xsd +88 -88
- package/build/src/schemaValidator.js +5 -13
- package/build/src/soap.js +123 -3
- package/build/src/utility.js +12 -7
- package/package.json +77 -81
- package/types/api.d.ts +15 -0
- package/types/api.d.ts.map +1 -0
- package/types/binding-post.d.ts +48 -0
- package/types/binding-post.d.ts.map +1 -0
- package/types/binding-redirect.d.ts +54 -0
- package/types/binding-redirect.d.ts.map +1 -0
- package/types/binding-simplesign.d.ts +41 -0
- package/types/binding-simplesign.d.ts.map +1 -0
- package/types/entity-idp.d.ts +38 -0
- package/types/entity-idp.d.ts.map +1 -0
- package/types/entity-sp.d.ts +38 -0
- package/types/entity-sp.d.ts.map +1 -0
- package/types/entity.d.ts +100 -0
- package/types/entity.d.ts.map +1 -0
- package/types/extractor.d.ts +26 -0
- package/types/extractor.d.ts.map +1 -0
- package/types/flow.d.ts +7 -0
- package/types/flow.d.ts.map +1 -0
- package/types/index.d.ts +2 -1
- package/types/index.d.ts.map +1 -1
- package/types/libsaml.d.ts +208 -0
- package/types/libsaml.d.ts.map +1 -0
- package/types/metadata-idp.d.ts +25 -0
- package/types/metadata-idp.d.ts.map +1 -0
- package/types/metadata-sp.d.ts +37 -0
- package/types/metadata-sp.d.ts.map +1 -0
- package/types/metadata.d.ts +58 -0
- package/types/metadata.d.ts.map +1 -0
- package/types/src/api.d.ts +3 -3
- package/types/src/api.d.ts.map +1 -1
- package/types/src/binding-artifact.d.ts +24 -29
- package/types/src/binding-artifact.d.ts.map +1 -1
- package/types/src/binding-post.d.ts +22 -22
- package/types/src/binding-post.d.ts.map +1 -1
- package/types/src/binding-redirect.d.ts.map +1 -1
- package/types/src/binding-simplesign.d.ts.map +1 -1
- package/types/src/entity-idp.d.ts +3 -4
- package/types/src/entity-idp.d.ts.map +1 -1
- package/types/src/entity-sp.d.ts +13 -24
- package/types/src/entity-sp.d.ts.map +1 -1
- package/types/src/entity.d.ts.map +1 -1
- package/types/src/extractor.d.ts +22 -0
- package/types/src/extractor.d.ts.map +1 -1
- package/types/src/flow.d.ts +1 -0
- package/types/src/flow.d.ts.map +1 -1
- package/types/src/libsaml.d.ts +16 -7
- package/types/src/libsaml.d.ts.map +1 -1
- package/types/src/libsamlSoap.d.ts +7 -0
- package/types/src/libsamlSoap.d.ts.map +1 -0
- package/types/src/schemaValidator.d.ts +1 -1
- package/types/src/schemaValidator.d.ts.map +1 -1
- package/types/src/soap.d.ts +33 -0
- package/types/src/soap.d.ts.map +1 -1
- package/types/src/utility.d.ts.map +1 -1
- package/types/src/validator.d.ts.map +1 -1
- package/types/types.d.ts +128 -0
- package/types/types.d.ts.map +1 -0
- package/types/urn.d.ts +195 -0
- package/types/urn.d.ts.map +1 -0
- package/types/utility.d.ts +133 -0
- package/types/utility.d.ts.map +1 -0
- package/types/validator.d.ts +4 -0
- package/types/validator.d.ts.map +1 -0
- package/build/src/schema/XMLSchema.dtd +0 -402
- package/build/src/schema/datatypes.dtd +0 -203
package/build/src/flow.js
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
import { base64Decode } from './utility.js';
|
|
2
2
|
import { verifyTime } from './validator.js';
|
|
3
3
|
import libsaml from './libsaml.js';
|
|
4
|
-
import * as uuid from 'uuid';
|
|
5
|
-
import { select } from 'xpath';
|
|
6
|
-
import { DOMParser } from '@xmldom/xmldom';
|
|
7
|
-
import { sendArtifactResolve } from "./soap.js";
|
|
8
4
|
import { extract, loginRequestFields, loginResponseFields, loginResponseStatusFields, loginArtifactResponseStatusFields, logoutRequestFields, logoutResponseFields, logoutResponseStatusFields } from './extractor.js';
|
|
9
5
|
import { BindingNamespace, ParserType, StatusCode, wording } from './urn.js';
|
|
10
6
|
const bindDict = wording.binding;
|
|
@@ -126,58 +122,15 @@ async function redirectFlow(options) {
|
|
|
126
122
|
}
|
|
127
123
|
// proceed the post flow
|
|
128
124
|
async function postFlow(options) {
|
|
129
|
-
const {
|
|
125
|
+
const { request, from, self, parserType, checkSignature = true } = options;
|
|
130
126
|
const { body } = request;
|
|
131
127
|
const direction = libsaml.getQueryParamByType(parserType);
|
|
132
128
|
let encodedRequest = '';
|
|
133
129
|
let samlContent = '';
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
samlContent = String(base64Decode(encodedRequest));
|
|
138
|
-
}
|
|
130
|
+
encodedRequest = body[direction];
|
|
131
|
+
// @ts-ignore
|
|
132
|
+
samlContent = String(base64Decode(encodedRequest));
|
|
139
133
|
/** 增加判断是不是Soap 工件绑定*/
|
|
140
|
-
if (soap) {
|
|
141
|
-
const metadata = {
|
|
142
|
-
idp: from.entityMeta,
|
|
143
|
-
sp: self.entityMeta,
|
|
144
|
-
};
|
|
145
|
-
const spSetting = self.entitySetting;
|
|
146
|
-
let ID = '_' + uuid.v4();
|
|
147
|
-
let url = metadata.idp.getArtifactResolutionService(bindDict.soap);
|
|
148
|
-
let samlSoapRaw = libsaml.replaceTagsByValue(libsaml.defaultArtifactResolveTemplate.context, {
|
|
149
|
-
ID: ID,
|
|
150
|
-
Destination: url,
|
|
151
|
-
Issuer: metadata.sp.getEntityID(),
|
|
152
|
-
IssueInstant: new Date().toISOString(),
|
|
153
|
-
Art: request.Art
|
|
154
|
-
});
|
|
155
|
-
if (!metadata.idp.isWantAuthnRequestsSigned()) {
|
|
156
|
-
samlContent = await sendArtifactResolve(url, samlSoapRaw);
|
|
157
|
-
}
|
|
158
|
-
if (metadata.idp.isWantAuthnRequestsSigned()) {
|
|
159
|
-
const { privateKey, privateKeyPass, requestSignatureAlgorithm: signatureAlgorithm, transformationAlgorithms } = spSetting;
|
|
160
|
-
let signatureSoap = libsaml.constructSAMLSignature({
|
|
161
|
-
referenceTagXPath: "//*[local-name(.)='ArtifactResolve']",
|
|
162
|
-
isMessageSigned: false,
|
|
163
|
-
isBase64Output: false,
|
|
164
|
-
transformationAlgorithms: transformationAlgorithms,
|
|
165
|
-
privateKey,
|
|
166
|
-
privateKeyPass,
|
|
167
|
-
signatureAlgorithm,
|
|
168
|
-
rawSamlMessage: samlSoapRaw,
|
|
169
|
-
signingCert: metadata.sp.getX509Certificate('signing'),
|
|
170
|
-
signatureConfig: {
|
|
171
|
-
prefix: 'ds',
|
|
172
|
-
location: {
|
|
173
|
-
reference: "//*[local-name(.)='Issuer']",
|
|
174
|
-
action: 'after'
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
samlContent = await sendArtifactResolve(url, signatureSoap);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
134
|
const verificationOptions = {
|
|
182
135
|
metadata: from.entityMeta,
|
|
183
136
|
signatureAlgorithm: from.entitySetting.requestSignatureAlgorithm,
|
|
@@ -196,92 +149,26 @@ async function postFlow(options) {
|
|
|
196
149
|
extractorFields = getDefaultExtractorFields(parserType, null);
|
|
197
150
|
}
|
|
198
151
|
// check status based on different scenarios
|
|
199
|
-
await checkStatus(samlContent, parserType
|
|
152
|
+
await checkStatus(samlContent, parserType);
|
|
200
153
|
/**检查签名顺序 */
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
console.log(verified);
|
|
208
|
-
console.log("verified")
|
|
209
|
-
decryptRequired = isDecryptRequired
|
|
210
|
-
if (!verified) {
|
|
211
|
-
return Promise.reject('ERR_FAIL_TO_VERIFY_ETS_SIGNATURE');
|
|
212
|
-
}
|
|
213
|
-
if (!decryptRequired) {
|
|
214
|
-
extractorFields = getDefaultExtractorFields(parserType, verifiedAssertionNode);
|
|
215
|
-
}
|
|
216
|
-
}*/
|
|
217
|
-
if (soap === true) {
|
|
218
|
-
const [verified, verifiedAssertionNode, isDecryptRequired] = libsaml.verifySignatureSoap(samlContent, verificationOptions);
|
|
219
|
-
decryptRequired = isDecryptRequired;
|
|
220
|
-
if (!verified) {
|
|
221
|
-
return Promise.reject('ERR_FAIL_TO_VERIFY_ETS_SIGNATURE');
|
|
222
|
-
}
|
|
223
|
-
if (!decryptRequired) {
|
|
224
|
-
extractorFields = getDefaultExtractorFields(parserType, verifiedAssertionNode);
|
|
225
|
-
}
|
|
226
|
-
if (parserType === 'SAMLResponse' && decryptRequired) {
|
|
227
|
-
// 1. 解密断言
|
|
228
|
-
const [decryptedSAML, decryptedAssertion] = await libsaml.decryptAssertionSoap(self, samlContent);
|
|
229
|
-
// 2. 检查解密后的断言是否包含签名
|
|
230
|
-
const assertionDoc = new DOMParser().parseFromString(decryptedAssertion, 'text/xml');
|
|
231
|
-
const assertionSignatureNodes = select("./*[local-name()='Signature']", assertionDoc.documentElement);
|
|
232
|
-
// 3. 如果存在签名则验证
|
|
233
|
-
if (assertionSignatureNodes.length > 0) {
|
|
234
|
-
// 3.1 创建新的验证选项(保持原配置)
|
|
235
|
-
const assertionVerificationOptions = {
|
|
236
|
-
...verificationOptions,
|
|
237
|
-
isAssertion: true // 添加标识表示正在验证断言
|
|
238
|
-
};
|
|
239
|
-
// 3.2 验证断言签名
|
|
240
|
-
const [assertionVerified, result] = libsaml.verifySignatureSoap(decryptedAssertion, assertionVerificationOptions);
|
|
241
|
-
if (!assertionVerified) {
|
|
242
|
-
console.error("解密后的断言签名验证失败");
|
|
243
|
-
return Promise.reject('ERR_FAIL_TO_VERIFY_ASSERTION_SIGNATURE');
|
|
244
|
-
}
|
|
245
|
-
if (assertionVerified) {
|
|
246
|
-
// @ts-ignore
|
|
247
|
-
samlContent = result;
|
|
248
|
-
extractorFields = getDefaultExtractorFields(parserType, result);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
samlContent = decryptedAssertion;
|
|
253
|
-
extractorFields = getDefaultExtractorFields(parserType, decryptedAssertion);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
154
|
+
const [verified, verifiedAssertionNode, isDecryptRequired, noSignature] = libsaml.verifySignature(samlContent, verificationOptions);
|
|
155
|
+
decryptRequired = isDecryptRequired;
|
|
156
|
+
if (isDecryptRequired && noSignature) {
|
|
157
|
+
const result = await libsaml.decryptAssertion(self, samlContent);
|
|
158
|
+
samlContent = result[0];
|
|
159
|
+
extractorFields = getDefaultExtractorFields(parserType, result[1]);
|
|
256
160
|
}
|
|
257
|
-
if (
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const result = await libsaml.decryptAssertion(self, samlContent);
|
|
268
|
-
samlContent = result[0];
|
|
269
|
-
extractorFields = getDefaultExtractorFields(parserType, result[1]);
|
|
270
|
-
}
|
|
161
|
+
if (!verified && !noSignature && !isDecryptRequired) {
|
|
162
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_ETS_SIGNATURE');
|
|
163
|
+
}
|
|
164
|
+
if (!isDecryptRequired) {
|
|
165
|
+
extractorFields = getDefaultExtractorFields(parserType, verifiedAssertionNode);
|
|
166
|
+
}
|
|
167
|
+
if (parserType === 'SAMLResponse' && isDecryptRequired && !noSignature) {
|
|
168
|
+
const result = await libsaml.decryptAssertion(self, samlContent);
|
|
169
|
+
samlContent = result[0];
|
|
170
|
+
extractorFields = getDefaultExtractorFields(parserType, result[1]);
|
|
271
171
|
}
|
|
272
|
-
// verify the signatures (the response is signed then encrypted, then decrypt first then verify)
|
|
273
|
-
/* if (
|
|
274
|
-
checkSignature &&
|
|
275
|
-
from.entitySetting.messageSigningOrder === MessageSignatureOrder.STE
|
|
276
|
-
) {
|
|
277
|
-
const [verified, verifiedAssertionNode,isDecryptRequired] = libsaml.verifySignature(samlContent, verificationOptions);
|
|
278
|
-
decryptRequired = isDecryptRequired
|
|
279
|
-
if (verified) {
|
|
280
|
-
extractorFields = getDefaultExtractorFields(parserType, verifiedAssertionNode);
|
|
281
|
-
} else {
|
|
282
|
-
return Promise.reject('ERR_FAIL_TO_VERIFY_STE_SIGNATURE');
|
|
283
|
-
}
|
|
284
|
-
}*/
|
|
285
172
|
const parseResult = {
|
|
286
173
|
samlContent: samlContent,
|
|
287
174
|
extract: extract(samlContent, extractorFields),
|
|
@@ -351,29 +238,13 @@ async function postArtifactFlow(options) {
|
|
|
351
238
|
let decryptRequired = from.entitySetting.isAssertionEncrypted;
|
|
352
239
|
let extractorFields = [];
|
|
353
240
|
// validate the xml first
|
|
354
|
-
let res = await libsaml.isValidXml(samlContent);
|
|
241
|
+
let res = await libsaml.isValidXml(samlContent, true);
|
|
355
242
|
if (parserType !== urlParams.samlResponse) {
|
|
356
243
|
extractorFields = getDefaultExtractorFields(parserType, null);
|
|
357
244
|
}
|
|
358
245
|
// check status based on different scenarios
|
|
359
246
|
await checkStatus(samlContent, parserType);
|
|
360
247
|
/**检查签名顺序 */
|
|
361
|
-
/* if (
|
|
362
|
-
checkSignature &&
|
|
363
|
-
from.entitySetting.messageSigningOrder === MessageSignatureOrder.ETS
|
|
364
|
-
) {
|
|
365
|
-
console.log("===============我走的这里=========================")
|
|
366
|
-
const [verified, verifiedAssertionNode,isDecryptRequired] = libsaml.verifySignature(samlContent, verificationOptions);
|
|
367
|
-
console.log(verified);
|
|
368
|
-
console.log("verified")
|
|
369
|
-
decryptRequired = isDecryptRequired
|
|
370
|
-
if (!verified) {
|
|
371
|
-
return Promise.reject('ERR_FAIL_TO_VERIFY_ETS_SIGNATURE');
|
|
372
|
-
}
|
|
373
|
-
if (!decryptRequired) {
|
|
374
|
-
extractorFields = getDefaultExtractorFields(parserType, verifiedAssertionNode);
|
|
375
|
-
}
|
|
376
|
-
}*/
|
|
377
248
|
const [verified, verifiedAssertionNode, isDecryptRequired] = libsaml.verifySignature(samlContent, verificationOptions);
|
|
378
249
|
decryptRequired = isDecryptRequired;
|
|
379
250
|
if (!verified) {
|
|
@@ -387,19 +258,6 @@ async function postArtifactFlow(options) {
|
|
|
387
258
|
samlContent = result[0];
|
|
388
259
|
extractorFields = getDefaultExtractorFields(parserType, result[1]);
|
|
389
260
|
}
|
|
390
|
-
// verify the signatures (the response is signed then encrypted, then decrypt first then verify)
|
|
391
|
-
/* if (
|
|
392
|
-
checkSignature &&
|
|
393
|
-
from.entitySetting.messageSigningOrder === MessageSignatureOrder.STE
|
|
394
|
-
) {
|
|
395
|
-
const [verified, verifiedAssertionNode,isDecryptRequired] = libsaml.verifySignature(samlContent, verificationOptions);
|
|
396
|
-
decryptRequired = isDecryptRequired
|
|
397
|
-
if (verified) {
|
|
398
|
-
extractorFields = getDefaultExtractorFields(parserType, verifiedAssertionNode);
|
|
399
|
-
} else {
|
|
400
|
-
return Promise.reject('ERR_FAIL_TO_VERIFY_STE_SIGNATURE');
|
|
401
|
-
}
|
|
402
|
-
}*/
|
|
403
261
|
const parseResult = {
|
|
404
262
|
samlContent: samlContent,
|
|
405
263
|
extract: extract(samlContent, extractorFields),
|
|
@@ -469,7 +327,7 @@ async function postSimpleSignFlow(options) {
|
|
|
469
327
|
const xmlString = String(base64Decode(encodedRequest));
|
|
470
328
|
// validate the xml
|
|
471
329
|
try {
|
|
472
|
-
await libsaml.isValidXml(xmlString);
|
|
330
|
+
await libsaml.isValidXml(xmlString, false);
|
|
473
331
|
}
|
|
474
332
|
catch (e) {
|
|
475
333
|
return Promise.reject('ERR_INVALID_XML');
|
|
@@ -546,7 +404,7 @@ async function postSimpleSignFlow(options) {
|
|
|
546
404
|
}
|
|
547
405
|
return Promise.resolve(parseResult);
|
|
548
406
|
}
|
|
549
|
-
function checkStatus(content, parserType, soap) {
|
|
407
|
+
export function checkStatus(content, parserType, soap) {
|
|
550
408
|
// only check response parser
|
|
551
409
|
if (parserType !== urlParams.samlResponse && parserType !== urlParams.logoutResponse) {
|
|
552
410
|
return Promise.resolve('SKIPPED');
|