samlesa 2.17.2 → 2.18.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/build/src/binding-artifact.js +24 -14
- package/build/src/binding-post.js +0 -2
- package/build/src/flow.js +169 -27
- package/build/src/libsaml.js +442 -213
- package/build/src/metadata-idp.js +26 -24
- package/build/src/metadata-sp.js +19 -19
- package/build/src/schemaValidator.js +30 -6
- package/package.json +77 -78
- 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/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/binding-artifact.d.ts.map +1 -1
- package/types/src/binding-post.d.ts.map +1 -1
- package/types/src/flow.d.ts.map +1 -1
- package/types/src/libsaml.d.ts +50 -1
- package/types/src/libsaml.d.ts.map +1 -1
- package/types/src/metadata-idp.d.ts.map +1 -1
- package/types/src/metadata-sp.d.ts.map +1 -1
- package/types/src/schemaValidator.d.ts +1 -1
- package/types/src/schemaValidator.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
|
@@ -383,22 +383,32 @@ async function parseLoginResponseResolve(params) {
|
|
|
383
383
|
return Promise.reject('ERR_FAIL_TO_VERIFY_ETS_SIGNATURE');
|
|
384
384
|
}
|
|
385
385
|
samlContent = verifiedAssertionNode1;
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
386
|
+
// 改进的postFlow函数中关于签名验证的部分
|
|
387
|
+
const verificationResult = libsaml.verifySignature(samlContent, verificationOptions, self);
|
|
388
|
+
// 检查验证结果
|
|
389
|
+
if (!verificationResult.status) {
|
|
390
|
+
// 如果验证失败,根据具体情况返回错误
|
|
391
|
+
if (verificationResult.isMessageSigned && !verificationResult.MessageSignatureStatus) {
|
|
392
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_MESSAGE_SIGNATURE');
|
|
393
|
+
}
|
|
394
|
+
if (verificationResult.isAssertionSigned && !verificationResult.AssertionSignatureStatus) {
|
|
395
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_ASSERTION_SIGNATURE');
|
|
396
|
+
}
|
|
397
|
+
if (verificationResult.encrypted && !verificationResult.decrypted) {
|
|
398
|
+
return Promise.reject('ERR_FAIL_TO_DECRYPT_ASSERTION');
|
|
399
|
+
}
|
|
400
|
+
// 通用验证失败
|
|
401
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_SIGNATURE_OR_DECRYPTION');
|
|
394
402
|
}
|
|
395
|
-
|
|
396
|
-
|
|
403
|
+
// 更新samlContent为验证后的版本(可能已解密)
|
|
404
|
+
samlContent = verificationResult.samlContent;
|
|
405
|
+
// 根据验证结果设置extractorFields
|
|
406
|
+
if (verificationResult.assertionContent) {
|
|
407
|
+
extractorFields = getDefaultExtractorFields(parserType, verificationResult.assertionContent);
|
|
397
408
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
extractorFields = getDefaultExtractorFields(parserType, result[1]);
|
|
409
|
+
else {
|
|
410
|
+
// 如果没有断言内容(例如注销请求/响应),使用适当的处理方式
|
|
411
|
+
extractorFields = getDefaultExtractorFields(parserType, null);
|
|
402
412
|
}
|
|
403
413
|
const parseResult = {
|
|
404
414
|
samlContent: samlContent,
|
|
@@ -130,8 +130,6 @@ async function base64LoginResponse(requestInfo = {}, entity, user = {}, customTa
|
|
|
130
130
|
tvalue.InResponseTo = requestInfo?.extract?.request?.id ?? '';
|
|
131
131
|
}
|
|
132
132
|
rawSamlResponse = libsaml.replaceTagsByValue(libsaml.defaultLoginResponseTemplate.context, tvalue);
|
|
133
|
-
console.log(rawSamlResponse);
|
|
134
|
-
console.log("没有加密签名过的------------------------------------");
|
|
135
133
|
}
|
|
136
134
|
const { privateKey, privateKeyPass, requestSignatureAlgorithm: signatureAlgorithm } = idpSetting;
|
|
137
135
|
const config = {
|
package/build/src/flow.js
CHANGED
|
@@ -151,23 +151,149 @@ async function postFlow(options) {
|
|
|
151
151
|
// check status based on different scenarios
|
|
152
152
|
await checkStatus(samlContent, parserType);
|
|
153
153
|
/**检查签名顺序 */
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
154
|
+
/*
|
|
155
|
+
const [verified, verifiedAssertionNode, isDecryptRequired, noSignature] = libsaml.verifySignature(samlContent, verificationOptions);
|
|
156
|
+
decryptRequired = isDecryptRequired
|
|
157
|
+
if (isDecryptRequired && noSignature) {
|
|
158
|
+
|
|
159
|
+
const result = await libsaml.decryptAssertion(self, samlContent);
|
|
160
|
+
samlContent = result[0];
|
|
161
|
+
extractorFields = getDefaultExtractorFields(parserType, result[1]);
|
|
162
|
+
}
|
|
163
|
+
if (!verified && !noSignature && !isDecryptRequired) {
|
|
164
|
+
|
|
165
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_ETS_SIGNATURE');
|
|
166
|
+
}
|
|
167
|
+
if (!isDecryptRequired) {
|
|
168
|
+
|
|
169
|
+
extractorFields = getDefaultExtractorFields(parserType, verifiedAssertionNode);
|
|
170
|
+
}
|
|
171
|
+
if (parserType === 'SAMLResponse' && isDecryptRequired && !noSignature) {
|
|
172
|
+
const result = await libsaml.decryptAssertion(self, samlContent);
|
|
173
|
+
samlContent = result[0];
|
|
174
|
+
extractorFields = getDefaultExtractorFields(parserType, result[1]);
|
|
175
|
+
console.log("走这里来了=========")
|
|
176
|
+
console.log(result[1])
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
const parseResult = {
|
|
181
|
+
samlContent: samlContent,
|
|
182
|
+
extract: extract(samlContent, extractorFields),
|
|
183
|
+
};
|
|
184
|
+
/!**
|
|
185
|
+
* Validation part: validate the context of response after signature is verified and decrypted (optional)
|
|
186
|
+
*!/
|
|
187
|
+
const targetEntityMetadata = from.entityMeta;
|
|
188
|
+
const issuer = targetEntityMetadata.getEntityID();
|
|
189
|
+
const extractedProperties = parseResult.extract;
|
|
190
|
+
// unmatched issuer
|
|
191
|
+
if (
|
|
192
|
+
(parserType === 'LogoutResponse' || parserType === 'SAMLResponse')
|
|
193
|
+
&& extractedProperties
|
|
194
|
+
&& extractedProperties.issuer !== issuer
|
|
195
|
+
) {
|
|
196
|
+
return Promise.reject('ERR_UNMATCH_ISSUER');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// invalid session time
|
|
200
|
+
// only run the verifyTime when `SessionNotOnOrAfter` exists
|
|
201
|
+
if (
|
|
202
|
+
parserType === 'SAMLResponse'
|
|
203
|
+
&& extractedProperties.sessionIndex.sessionNotOnOrAfter
|
|
204
|
+
&& !verifyTime(
|
|
205
|
+
undefined,
|
|
206
|
+
extractedProperties.sessionIndex.sessionNotOnOrAfter,
|
|
207
|
+
self.entitySetting.clockDrifts
|
|
208
|
+
)
|
|
209
|
+
) {
|
|
210
|
+
return Promise.reject('ERR_EXPIRED_SESSION');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// invalid time
|
|
214
|
+
// 2.4.1.2 https://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
|
|
215
|
+
if (
|
|
216
|
+
parserType === 'SAMLResponse'
|
|
217
|
+
&& extractedProperties.conditions
|
|
218
|
+
&& !verifyTime(
|
|
219
|
+
extractedProperties.conditions.notBefore,
|
|
220
|
+
extractedProperties.conditions.notOnOrAfter,
|
|
221
|
+
self.entitySetting.clockDrifts
|
|
222
|
+
)
|
|
223
|
+
) {
|
|
224
|
+
return Promise.reject('ERR_SUBJECT_UNCONFIRMED');
|
|
225
|
+
}
|
|
226
|
+
//valid destination
|
|
227
|
+
//There is no validation of the response here. The upper-layer application
|
|
228
|
+
// should verify the result by itself to see if the destination is equal to the SP acs and
|
|
229
|
+
// whether the response.id is used to prevent replay attacks.
|
|
230
|
+
/!*
|
|
231
|
+
let destination = extractedProperties?.response?.destination
|
|
232
|
+
let isExit = self.entitySetting?.assertionConsumerService?.filter((item) => {
|
|
233
|
+
return item?.Location === destination
|
|
234
|
+
})
|
|
235
|
+
if (isExit?.length === 0) {
|
|
236
|
+
return Promise.reject('ERR_Destination_URL');
|
|
237
|
+
}
|
|
238
|
+
if (parserType === 'SAMLResponse') {
|
|
239
|
+
let destination = extractedProperties?.response?.destination
|
|
240
|
+
let isExit = self.entitySetting?.assertionConsumerService?.filter((item: { Location: any; }) => {
|
|
241
|
+
return item?.Location === destination
|
|
242
|
+
})
|
|
243
|
+
if (isExit?.length === 0) {
|
|
244
|
+
return Promise.reject('ERR_Destination_URL');
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
*!/
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
return Promise.resolve(parseResult);*/
|
|
251
|
+
// 改进的postFlow函数中关于签名验证的部分
|
|
252
|
+
const verificationResult = libsaml.verifySignature(samlContent, verificationOptions, self);
|
|
253
|
+
/* console.log(verificationResult)
|
|
254
|
+
console.log("解析对象")*/
|
|
255
|
+
let resultObject = {
|
|
256
|
+
isMessageSigned: true, //是否有外层的消息签名(Response或者Request 等最外层的签名)
|
|
257
|
+
MessageSignatureStatus: true, //外层的签名是否经过验证
|
|
258
|
+
isAssertionSigned: true, //是否有断言的签名
|
|
259
|
+
AssertionSignatureStatus: true, //断言签名是否经过验证
|
|
260
|
+
encrypted: true, //断言是否加密
|
|
261
|
+
decrypted: true, //断言加密后断言是否解密成功,
|
|
262
|
+
status: true, //是否全部通过验证,
|
|
263
|
+
samlContent: 'xxx', //xxx是通过验证后 解密后的整个响应,
|
|
264
|
+
assertionContent: 'xxx', //xxx是通过验证后 解密后的整个响应中的assertion 断言部分字符串
|
|
265
|
+
};
|
|
266
|
+
// 检查验证结果
|
|
267
|
+
if (!verificationResult.status) {
|
|
268
|
+
// 如果验证失败,根据具体情况返回错误
|
|
269
|
+
/** 需要判断是不是 */
|
|
270
|
+
if (verificationResult.isMessageSigned && !verificationResult.MessageSignatureStatus) {
|
|
271
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_MESSAGE_SIGNATURE');
|
|
272
|
+
}
|
|
273
|
+
if (verificationResult.isAssertionSigned && !verificationResult.AssertionSignatureStatus) {
|
|
274
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_ASSERTION_SIGNATURE');
|
|
275
|
+
}
|
|
276
|
+
if (verificationResult.encrypted && !verificationResult.decrypted) {
|
|
277
|
+
return Promise.reject('ERR_FAIL_TO_DECRYPT_ASSERTION');
|
|
278
|
+
}
|
|
279
|
+
if (!verificationResult.isMessageSigned && verificationResult.type === 'LogoutRequest') {
|
|
280
|
+
return Promise.reject('ERR_LogoutRequest_Need_Signature');
|
|
281
|
+
}
|
|
282
|
+
if (!verificationResult.isMessageSigned && verificationResult.type === 'LogoutResponse') {
|
|
283
|
+
return Promise.reject('ERR_LogoutResponse_Need_Signature');
|
|
284
|
+
}
|
|
285
|
+
// 通用验证失败
|
|
286
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_SIGNATURE_OR_DECRYPTION');
|
|
163
287
|
}
|
|
164
|
-
|
|
165
|
-
|
|
288
|
+
// 更新samlContent为验证后的版本(可能已解密)
|
|
289
|
+
samlContent = verificationResult.samlContent;
|
|
290
|
+
// 根据验证结果设置extractorFields
|
|
291
|
+
if (verificationResult.assertionContent) {
|
|
292
|
+
extractorFields = getDefaultExtractorFields(parserType, verificationResult.assertionContent);
|
|
166
293
|
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
extractorFields = getDefaultExtractorFields(parserType, result[1]);
|
|
294
|
+
else {
|
|
295
|
+
// 如果没有断言内容(例如注销请求/响应),使用适当的处理方式
|
|
296
|
+
extractorFields = getDefaultExtractorFields(parserType, null);
|
|
171
297
|
}
|
|
172
298
|
const parseResult = {
|
|
173
299
|
samlContent: samlContent,
|
|
@@ -245,18 +371,34 @@ async function postArtifactFlow(options) {
|
|
|
245
371
|
// check status based on different scenarios
|
|
246
372
|
await checkStatus(samlContent, parserType);
|
|
247
373
|
/**检查签名顺序 */
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
if (!
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
374
|
+
// 改进的postFlow函数中关于签名验证的部分
|
|
375
|
+
const verificationResult = libsaml.verifySignature(samlContent, verificationOptions, self);
|
|
376
|
+
console.log(verificationResult);
|
|
377
|
+
console.log("最终结果====");
|
|
378
|
+
// 检查验证结果
|
|
379
|
+
if (!verificationResult.status) {
|
|
380
|
+
// 如果验证失败,根据具体情况返回错误
|
|
381
|
+
if (verificationResult.isMessageSigned && !verificationResult.MessageSignatureStatus) {
|
|
382
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_MESSAGE_SIGNATURE');
|
|
383
|
+
}
|
|
384
|
+
if (verificationResult.isAssertionSigned && !verificationResult.AssertionSignatureStatus) {
|
|
385
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_ASSERTION_SIGNATURE');
|
|
386
|
+
}
|
|
387
|
+
if (verificationResult.encrypted && !verificationResult.decrypted) {
|
|
388
|
+
return Promise.reject('ERR_FAIL_TO_DECRYPT_ASSERTION');
|
|
389
|
+
}
|
|
390
|
+
// 通用验证失败
|
|
391
|
+
return Promise.reject('ERR_FAIL_TO_VERIFY_SIGNATURE_OR_DECRYPTION');
|
|
392
|
+
}
|
|
393
|
+
// 更新samlContent为验证后的版本(可能已解密)
|
|
394
|
+
samlContent = verificationResult.samlContent;
|
|
395
|
+
// 根据验证结果设置extractorFields
|
|
396
|
+
if (verificationResult.assertionContent) {
|
|
397
|
+
extractorFields = getDefaultExtractorFields(parserType, verificationResult.assertionContent);
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
// 如果没有断言内容(例如注销请求/响应),使用适当的处理方式
|
|
401
|
+
extractorFields = getDefaultExtractorFields(parserType, null);
|
|
260
402
|
}
|
|
261
403
|
const parseResult = {
|
|
262
404
|
samlContent: samlContent,
|