samlesa 2.16.5 → 2.16.6

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 (44) hide show
  1. package/build/src/binding-redirect.js +97 -2
  2. package/build/src/entity-sp.js +117 -23
  3. package/build/src/extractor.js +13 -0
  4. package/build/src/flow.js +21 -35
  5. package/build/src/libsaml.js +8 -4
  6. package/build/src/metadata-sp.js +2 -0
  7. package/build/src/metadata.js +0 -2
  8. package/build/src/schema/saml-schema-ecp-2.0.xsd +1 -1
  9. package/build/src/schema/saml-schema-metadata-2.0.xsd +3 -3
  10. package/build/src/schema/saml-schema-protocol-2.0.xsd +1 -1
  11. package/build/src/schema/{env.xsd → soap-envelope.xsd} +1 -33
  12. package/build/src/schema/xml.xsd +88 -0
  13. package/build/src/schemaValidator.js +29 -8
  14. package/package.json +1 -1
  15. package/types/src/binding-redirect.d.ts +14 -1
  16. package/types/src/binding-redirect.d.ts.map +1 -1
  17. package/types/src/entity-sp.d.ts +44 -21
  18. package/types/src/entity-sp.d.ts.map +1 -1
  19. package/types/src/extractor.d.ts +5 -0
  20. package/types/src/extractor.d.ts.map +1 -1
  21. package/types/src/flow.d.ts.map +1 -1
  22. package/types/src/libsaml.d.ts +3 -0
  23. package/types/src/libsaml.d.ts.map +1 -1
  24. package/types/src/metadata-sp.d.ts.map +1 -1
  25. package/types/src/metadata.d.ts.map +1 -1
  26. package/types/src/schemaValidator.d.ts.map +1 -1
  27. package/build/index.js.map +0 -1
  28. package/build/src/api.js.map +0 -1
  29. package/build/src/binding-post.js.map +0 -1
  30. package/build/src/binding-redirect.js.map +0 -1
  31. package/build/src/binding-simplesign.js.map +0 -1
  32. package/build/src/entity-idp.js.map +0 -1
  33. package/build/src/entity-sp.js.map +0 -1
  34. package/build/src/entity.js.map +0 -1
  35. package/build/src/extractor.js.map +0 -1
  36. package/build/src/flow.js.map +0 -1
  37. package/build/src/libsaml.js.map +0 -1
  38. package/build/src/metadata-idp.js.map +0 -1
  39. package/build/src/metadata-sp.js.map +0 -1
  40. package/build/src/metadata.js.map +0 -1
  41. package/build/src/types.js.map +0 -1
  42. package/build/src/urn.js.map +0 -1
  43. package/build/src/utility.js.map +0 -1
  44. package/build/src/validator.js.map +0 -1
@@ -5,7 +5,7 @@
5
5
  */
6
6
  import utility, { get } from './utility.js';
7
7
  import libsaml from './libsaml.js';
8
- import { wording, namespace } from './urn.js';
8
+ import { namespace, wording } from './urn.js';
9
9
  const binding = wording.binding;
10
10
  const urlParams = wording.urlParams;
11
11
  /**
@@ -59,8 +59,9 @@ function buildRedirectURL(opts) {
59
59
  * @param {function} customTagReplacement used when developers have their own login response template
60
60
  * @return {string} redirect URL
61
61
  */
62
+ // @ts-ignore
62
63
  function loginRequestRedirectURL(entity, customTagReplacement) {
63
- const metadata = { idp: entity.idp.entityMeta, sp: entity.sp.entityMeta };
64
+ const metadata = { idp: entity.idp.entityMeta, sp: entity.sp.entityMeta, soap: entity.soap ?? false };
64
65
  const spSetting = entity.sp.entitySetting;
65
66
  let id = '';
66
67
  if (metadata && metadata.idp && metadata.sp) {
@@ -100,6 +101,99 @@ function loginRequestRedirectURL(entity, customTagReplacement) {
100
101
  }
101
102
  throw new Error('ERR_GENERATE_REDIRECT_LOGIN_REQUEST_MISSING_METADATA');
102
103
  }
104
+ /**
105
+ * @desc Redirect URL for login request
106
+ * @param {object} entity object includes both idp and sp
107
+ * @param {function} customTagReplacement used when developers have their own login response template
108
+ * @return {string} redirect URL
109
+ */
110
+ // @ts-ignore
111
+ function loginRequestRedirectURLArt(entity, customTagReplacement) {
112
+ const metadata = { idp: entity.idp.entityMeta, sp: entity.sp.entityMeta, inResponse: entity.inResponse ?? false };
113
+ const spSetting = entity.sp.entitySetting;
114
+ let id = '';
115
+ if (metadata && metadata.idp && metadata.sp) {
116
+ const base = metadata.idp.getSingleSignOnService(binding.redirect);
117
+ let rawSamlRequest;
118
+ if (spSetting.loginRequestTemplate && customTagReplacement) {
119
+ const info = customTagReplacement(spSetting.loginRequestTemplate);
120
+ id = get(info, 'id', null);
121
+ rawSamlRequest = get(info, 'context', null);
122
+ }
123
+ else {
124
+ const nameIDFormat = spSetting.nameIDFormat;
125
+ const selectedNameIDFormat = Array.isArray(nameIDFormat) ? nameIDFormat[0] : nameIDFormat;
126
+ id = spSetting.generateID();
127
+ rawSamlRequest = libsaml.replaceTagsByValue(libsaml.defaultLoginRequestTemplate.context, {
128
+ ID: id,
129
+ Destination: base,
130
+ Issuer: metadata.sp.getEntityID(),
131
+ IssueInstant: new Date().toISOString(),
132
+ NameIDFormat: selectedNameIDFormat,
133
+ AssertionConsumerServiceURL: metadata.sp.getAssertionConsumerService(binding.post),
134
+ EntityID: metadata.sp.getEntityID(),
135
+ AllowCreate: spSetting.allowCreate,
136
+ });
137
+ }
138
+ console.log(rawSamlRequest);
139
+ console.log("-----------------这是原始请求模板-------------------");
140
+ const { privateKey, privateKeyPass, requestSignatureAlgorithm: signatureAlgorithm, transformationAlgorithms } = spSetting;
141
+ if (metadata.idp.isWantAuthnRequestsSigned()) {
142
+ let signAuthnRequest = libsaml.constructSAMLSignature({
143
+ referenceTagXPath: "/*[local-name(.)='AuthnRequest']",
144
+ privateKey,
145
+ privateKeyPass,
146
+ signatureAlgorithm,
147
+ transformationAlgorithms,
148
+ isBase64Output: false,
149
+ rawSamlMessage: rawSamlRequest,
150
+ signingCert: metadata.sp.getX509Certificate('signing'),
151
+ signatureConfig: spSetting.signatureConfig || {
152
+ prefix: 'ds',
153
+ location: {
154
+ reference: "/*[local-name(.)='AuthnRequest']/*[local-name(.)='Issuer']",
155
+ action: 'after'
156
+ },
157
+ }
158
+ });
159
+ console.log(signAuthnRequest);
160
+ console.log("签名后的模板");
161
+ rawSamlRequest = signAuthnRequest;
162
+ }
163
+ /* console.log(metadata.idp)
164
+ console.log(entity.idp.getEntitySetting())*/
165
+ let soapTemplate = libsaml.replaceTagsByValue(libsaml.defaultArtAuthnRequestTemplate.context, {
166
+ ID: id,
167
+ IssueInstant: new Date().toISOString(),
168
+ InResponseTo: metadata.inResponse ?? "",
169
+ Issuer: metadata.sp.getEntityID(),
170
+ AuthnRequest: rawSamlRequest
171
+ });
172
+ console.log(soapTemplate);
173
+ console.log("======================最后结果========================");
174
+ console.log("======================开始签名根节点========================");
175
+ let rootSignSoap = libsaml.constructSAMLSignature({
176
+ isMessageSigned: true,
177
+ isBase64Output: false,
178
+ privateKey,
179
+ privateKeyPass,
180
+ signatureAlgorithm,
181
+ transformationAlgorithms,
182
+ rawSamlMessage: soapTemplate,
183
+ signingCert: metadata.sp.getX509Certificate('signing'),
184
+ signatureConfig: {
185
+ prefix: 'ds',
186
+ location: { reference: "//*[local-name()='Header']", action: 'after' },
187
+ }
188
+ });
189
+ console.log(rootSignSoap);
190
+ console.log("======================已经签名========================");
191
+ return {
192
+ authnRequest: rootSignSoap
193
+ };
194
+ }
195
+ throw new Error('ERR_GENERATE_REDIRECT_LOGIN_REQUEST_MISSING_METADATA');
196
+ }
103
197
  /**
104
198
  * @desc Redirect URL for login response
105
199
  * @param {object} requestInfo corresponding request, used to obtain the id
@@ -304,6 +398,7 @@ function logoutResponseRedirectURL(requestInfo, entity, relayState, customTagRep
304
398
  throw new Error('ERR_GENERATE_REDIRECT_LOGOUT_RESPONSE_MISSING_METADATA');
305
399
  }
306
400
  const redirectBinding = {
401
+ loginRequestRedirectURLArt,
307
402
  loginRequestRedirectURL,
308
403
  loginResponseRedirectURL,
309
404
  logoutRequestRedirectURL,
@@ -1,9 +1,10 @@
1
1
  /**
2
- * @file entity-sp.ts
3
- * @author tngan
4
- * @desc Declares the actions taken by service provider
5
- */
2
+ * @file entity-sp.ts
3
+ * @author tngan
4
+ * @desc Declares the actions taken by service provider
5
+ */
6
6
  import Entity from './entity.js';
7
+ import * as crypto from "node:crypto";
7
8
  import { namespace } from './urn.js';
8
9
  import redirectBinding from './binding-redirect.js';
9
10
  import postBinding from './binding-post.js';
@@ -17,15 +18,15 @@ export default function (props) {
17
18
  return new ServiceProvider(props);
18
19
  }
19
20
  /**
20
- * @desc Service provider can be configured using either metadata importing or spSetting
21
- * @param {object} spSettingimport { FlowResult } from '../types/src/flow.d';
21
+ * @desc Service provider can be configured using either metadata importing or spSetting
22
+ * @param {object} spSettingimport { FlowResult } from '../types/src/flow.d';
22
23
 
23
- */
24
+ */
24
25
  export class ServiceProvider extends Entity {
25
26
  /**
26
- * @desc Inherited from Entity
27
- * @param {object} spSetting setting of service provider
28
- */
27
+ * @desc Inherited from Entity
28
+ * @param {object} spSetting setting of service provider
29
+ */
29
30
  constructor(spSetting) {
30
31
  const entitySetting = Object.assign({
31
32
  authnRequestsSigned: false,
@@ -35,11 +36,11 @@ export class ServiceProvider extends Entity {
35
36
  super(entitySetting, 'sp');
36
37
  }
37
38
  /**
38
- * @desc Generates the login request for developers to design their own method
39
- * @param {IdentityProvider} idp object of identity provider
40
- * @param {string} binding protocol binding
41
- * @param {function} customTagReplacement used when developers have their own login response template
42
- */
39
+ * @desc Generates the login request for developers to design their own method
40
+ * @param {IdentityProvider} idp object of identity provider
41
+ * @param {string} binding protocol binding
42
+ * @param {function} customTagReplacement used when developers have their own login response template
43
+ */
43
44
  createLoginRequest(idp, binding = 'redirect', customTagReplacement) {
44
45
  const nsBinding = namespace.binding;
45
46
  const protocol = nsBinding[binding];
@@ -51,14 +52,20 @@ export class ServiceProvider extends Entity {
51
52
  case nsBinding.redirect:
52
53
  return redirectBinding.loginRequestRedirectURL({ idp, sp: this }, customTagReplacement);
53
54
  case nsBinding.post:
54
- context = postBinding.base64LoginRequest("/*[local-name(.)='AuthnRequest']", { idp, sp: this }, customTagReplacement);
55
+ context = postBinding.base64LoginRequest("/*[local-name(.)='AuthnRequest']", {
56
+ idp,
57
+ sp: this
58
+ }, customTagReplacement);
55
59
  break;
56
60
  case nsBinding.simpleSign:
57
61
  // Object context = {id, context, signature, sigAlg}
58
62
  context = simpleSignBinding.base64LoginRequest({ idp, sp: this }, customTagReplacement);
59
63
  break;
60
64
  case nsBinding.artifact:
61
- context = artifactSignBinding.base64LoginRequest("/*[local-name(.)='AuthnRequest']", { idp, sp: this }, customTagReplacement);
65
+ context = artifactSignBinding.base64LoginRequest("/*[local-name(.)='AuthnRequest']", {
66
+ idp,
67
+ sp: this
68
+ }, customTagReplacement);
62
69
  break;
63
70
  default:
64
71
  // Will support artifact in the next release
@@ -72,11 +79,45 @@ export class ServiceProvider extends Entity {
72
79
  };
73
80
  }
74
81
  /**
75
- * @desc Validation of the parsed the URL parameters
76
- * @param {IdentityProvider} idp object of identity provider
77
- * @param {string} binding protocol binding
78
- * @param {request} req request
79
- */
82
+ * @desc Generates the Art login request for developers to design their own method
83
+ * @param {IdentityProvider} idp object of identity provider
84
+ * @param {string} binding protocol binding
85
+ * @param {function} customTagReplacement used when developers have their own login response template
86
+ */
87
+ createLoginRequestArt(idp, binding = 'redirect', customTagReplacement) {
88
+ const nsBinding = namespace.binding;
89
+ const protocol = nsBinding[binding];
90
+ if (this.entityMeta.isAuthnRequestSigned() !== idp.entityMeta.isWantAuthnRequestsSigned()) {
91
+ throw new Error('ERR_METADATA_CONFLICT_REQUEST_SIGNED_FLAG');
92
+ }
93
+ let context = null;
94
+ switch (protocol) {
95
+ case nsBinding.redirect:
96
+ return redirectBinding.loginRequestRedirectURLArt({ idp, sp: this }, customTagReplacement);
97
+ case nsBinding.post:
98
+ context = postBinding.base64LoginRequest("/*[local-name(.)='AuthnRequest']", {
99
+ idp,
100
+ sp: this,
101
+ soap: true
102
+ }, customTagReplacement);
103
+ break;
104
+ default:
105
+ // Will support artifact in the next release
106
+ throw new Error('ERR_SP_LOGIN_REQUEST_UNDEFINED_BINDING');
107
+ }
108
+ return {
109
+ ...context,
110
+ relayState: this.entitySetting.relayState,
111
+ entityEndpoint: idp.entityMeta.getSingleSignOnService(binding),
112
+ type: 'SAMLRequest',
113
+ };
114
+ }
115
+ /**
116
+ * @desc Validation of the parsed the URL parameters
117
+ * @param {IdentityProvider} idp object of identity provider
118
+ * @param {string} binding protocol binding
119
+ * @param {request} req request
120
+ */
80
121
  parseLoginResponse(idp, binding, request) {
81
122
  const self = this;
82
123
  return flow({
@@ -95,7 +136,7 @@ export class ServiceProvider extends Entity {
95
136
  * @param {string} binding protocol binding
96
137
  * @param {request} req request
97
138
  */
98
- artifactResolveResponse(idp, binding, request) {
139
+ parseLoginResponseArt(idp, binding, request) {
99
140
  const self = this;
100
141
  return flow({
101
142
  soap: true,
@@ -108,4 +149,57 @@ export class ServiceProvider extends Entity {
108
149
  request: request
109
150
  });
110
151
  }
152
+ /**
153
+ * @desc generate Art id
154
+ *
155
+ * @param entityIDString
156
+ */
157
+ createArt(entityIDString, endpointIndex = 0) {
158
+ let sourceEntityId = entityIDString ? entityIDString : this.entityMeta.getEntityID();
159
+ console.log(sourceEntityId);
160
+ console.log("0000000000000000000000000000000000000000");
161
+ // 1. 固定类型代码 (0x0004 - 2字节)
162
+ const typeCode = Buffer.from([0x00, 0x04]);
163
+ // 2. 端点索引 (2字节,大端序)
164
+ if (endpointIndex < 0 || endpointIndex > 65535) {
165
+ throw new Error('Endpoint index must be between 0 and 65535');
166
+ }
167
+ const endpointBuf = Buffer.alloc(2);
168
+ endpointBuf.writeUInt16BE(endpointIndex);
169
+ // 3. Source ID - 实体ID的SHA-1哈希 (20字节)
170
+ const sourceId = crypto.createHash('sha1')
171
+ .update(sourceEntityId)
172
+ .digest();
173
+ // 4. Message Handler - 20字节随机值
174
+ const messageHandler = crypto.randomBytes(20);
175
+ // 组合所有组件 (2+2+20+20 = 44字节)
176
+ const artifact = Buffer.concat([typeCode, endpointBuf, sourceId, messageHandler]);
177
+ // 返回Base64编码的Artifact
178
+ return artifact.toString('base64');
179
+ }
180
+ /**
181
+ * @desc generate Art id
182
+ * @param artifact
183
+ */
184
+ parseArt(artifact) {
185
+ // 解码 Base64
186
+ const decoded = Buffer.from(artifact, 'base64');
187
+ // 确保长度正确(SAML 工件固定为 44 字节)
188
+ if (decoded.length !== 44) {
189
+ throw new Error(`Invalid artifact length: ${decoded.length}, expected 44 bytes`);
190
+ }
191
+ // 读取前 4 字节(TypeCode + EndpointIndex)
192
+ const typeCode = decoded.readUInt16BE(0);
193
+ const endpointIndex = decoded.readUInt16BE(2);
194
+ // 使用 Buffer.from() 替代 slice()
195
+ const sourceId = Buffer.from(decoded.buffer, // 底层 ArrayBuffer
196
+ decoded.byteOffset + 4, // 起始偏移量
197
+ 20 // 长度
198
+ ).toString('hex');
199
+ const messageHandle = Buffer.from(decoded.buffer, // 底层 ArrayBuffer
200
+ decoded.byteOffset + 24, // 起始偏移量
201
+ 20 // 长度
202
+ ).toString('hex');
203
+ return { typeCode, endpointIndex, sourceId, messageHandle };
204
+ }
111
205
  }
@@ -68,6 +68,19 @@ export const loginResponseStatusFields = [
68
68
  }
69
69
  ];
70
70
  // support two-tiers status code
71
+ export const loginArtifactResponseStatusFields = [
72
+ {
73
+ key: 'top',
74
+ localPath: ['Envelope', 'Body', 'ArtifactResponse', 'Status', 'StatusCode'],
75
+ attributes: ['Value'],
76
+ },
77
+ {
78
+ key: 'second',
79
+ localPath: ['Envelope', 'Body', 'ArtifactResponse', 'Status', 'StatusCode', 'StatusCode'],
80
+ attributes: ['Value'],
81
+ }
82
+ ];
83
+ // support two-tiers status code
71
84
  export const logoutResponseStatusFields = [
72
85
  {
73
86
  key: 'top',
package/build/src/flow.js CHANGED
@@ -5,8 +5,8 @@ import * as uuid from 'uuid';
5
5
  import { select } from 'xpath';
6
6
  import { DOMParser } from '@xmldom/xmldom';
7
7
  import { sendArtifactResolve } from "./soap.js";
8
- import { extract, loginRequestFields, loginResponseFields, logoutRequestFields, logoutResponseFields, logoutResponseStatusFields, loginResponseStatusFields } from './extractor.js';
9
- import { BindingNamespace, ParserType, wording, StatusCode } from './urn.js';
8
+ import { extract, loginRequestFields, loginResponseFields, loginResponseStatusFields, loginArtifactResponseStatusFields, logoutRequestFields, logoutResponseFields, logoutResponseStatusFields } from './extractor.js';
9
+ import { BindingNamespace, ParserType, StatusCode, wording } from './urn.js';
10
10
  const bindDict = wording.binding;
11
11
  const urlParams = wording.urlParams;
12
12
  // get the default extractor fields based on the parserType
@@ -146,12 +146,15 @@ async function postFlow(options) {
146
146
  let ID = '_' + uuid.v4();
147
147
  let url = metadata.idp.getArtifactResolutionService(bindDict.soap);
148
148
  let samlSoapRaw = libsaml.replaceTagsByValue(libsaml.defaultArtifactResolveTemplate.context, {
149
- ID: request?.messageHandle,
149
+ ID: ID,
150
150
  Destination: url,
151
151
  Issuer: metadata.sp.getEntityID(),
152
152
  IssueInstant: new Date().toISOString(),
153
153
  Art: request.Art
154
154
  });
155
+ if (!metadata.idp.isWantAuthnRequestsSigned()) {
156
+ samlContent = await sendArtifactResolve(url, samlSoapRaw);
157
+ }
155
158
  if (metadata.idp.isWantAuthnRequestsSigned()) {
156
159
  const { privateKey, privateKeyPass, requestSignatureAlgorithm: signatureAlgorithm, transformationAlgorithms } = spSetting;
157
160
  let signatureSoap = libsaml.constructSAMLSignature({
@@ -172,14 +175,8 @@ async function postFlow(options) {
172
175
  }
173
176
  }
174
177
  });
175
- let data = await sendArtifactResolve(url, signatureSoap);
176
- /* console.log(signatureSoap)
177
- console.log("签过名的")*/
178
- console.log(data);
179
- console.log("keycloak数据----------------------");
180
- samlContent = data;
178
+ samlContent = await sendArtifactResolve(url, signatureSoap);
181
179
  }
182
- // No need to embeded XML signature
183
180
  }
184
181
  const verificationOptions = {
185
182
  metadata: from.entityMeta,
@@ -189,23 +186,17 @@ async function postFlow(options) {
189
186
  let decryptRequired = from.entitySetting.isAssertionEncrypted;
190
187
  let extractorFields = [];
191
188
  // validate the xml first
192
- /* let res = await libsaml.isValidXml(samlContent).catch((error)=>{
193
- console.log(error);
194
- console.log("验证和结果-----------------------")
195
- console.log("验证和结果-----------------------")
196
- console.log("验证和结果-----------------------")
197
- console.log("验证和结果-----------------------")
198
- console.log("验证和结果-----------------------")
199
- console.log("验证和结果-----------------------")
200
- console.log("验证和结果-----------------------")
201
- });
202
- console.log(res);
203
- console.log("验证和结果-----------------------")*/
189
+ let res = await libsaml.isValidXml(samlContent).catch((error) => {
190
+ return Promise.reject('ERR_EXCEPTION_VALIDATE_XML');
191
+ });
192
+ if (res !== true) {
193
+ return Promise.reject('ERR_EXCEPTION_VALIDATE_XML');
194
+ }
204
195
  if (parserType !== urlParams.samlResponse) {
205
196
  extractorFields = getDefaultExtractorFields(parserType, null);
206
197
  }
207
198
  // check status based on different scenarios
208
- /* await checkStatus(samlContent, parserType);*/
199
+ await checkStatus(samlContent, parserType, soap);
209
200
  /**检查签名顺序 */
210
201
  /* if (
211
202
  checkSignature &&
@@ -230,14 +221,11 @@ async function postFlow(options) {
230
221
  return Promise.reject('ERR_FAIL_TO_VERIFY_ETS_SIGNATURE');
231
222
  }
232
223
  if (!decryptRequired) {
233
- console.log("-------------------走到了这里----------------------");
234
224
  extractorFields = getDefaultExtractorFields(parserType, verifiedAssertionNode);
235
225
  }
236
226
  if (parserType === 'SAMLResponse' && decryptRequired) {
237
227
  // 1. 解密断言
238
228
  const [decryptedSAML, decryptedAssertion] = await libsaml.decryptAssertionSoap(self, samlContent);
239
- console.log(decryptedAssertion);
240
- console.log("解密数据-----------------------------");
241
229
  // 2. 检查解密后的断言是否包含签名
242
230
  const assertionDoc = new DOMParser().parseFromString(decryptedAssertion, 'text/xml');
243
231
  const assertionSignatureNodes = select("./*[local-name()='Signature']", assertionDoc.documentElement);
@@ -250,9 +238,6 @@ async function postFlow(options) {
250
238
  };
251
239
  // 3.2 验证断言签名
252
240
  const [assertionVerified, result] = libsaml.verifySignatureSoap(decryptedAssertion, assertionVerificationOptions);
253
- console.log(assertionVerified);
254
- console.log(result);
255
- console.log("验证机结果--------------");
256
241
  if (!assertionVerified) {
257
242
  console.error("解密后的断言签名验证失败");
258
243
  return Promise.reject('ERR_FAIL_TO_VERIFY_ASSERTION_SIGNATURE');
@@ -307,10 +292,6 @@ async function postFlow(options) {
307
292
  const targetEntityMetadata = from.entityMeta;
308
293
  const issuer = targetEntityMetadata.getEntityID();
309
294
  const extractedProperties = parseResult.extract;
310
- console.log(extractedProperties);
311
- console.log(parseResult);
312
- console.log("解析结果----------------------------------");
313
- console.log("签发这-----------");
314
295
  // unmatched issuer
315
296
  if ((parserType === 'LogoutResponse' || parserType === 'SAMLResponse')
316
297
  && extractedProperties
@@ -565,14 +546,19 @@ async function postSimpleSignFlow(options) {
565
546
  }
566
547
  return Promise.resolve(parseResult);
567
548
  }
568
- function checkStatus(content, parserType) {
549
+ function checkStatus(content, parserType, soap) {
569
550
  // only check response parser
570
551
  if (parserType !== urlParams.samlResponse && parserType !== urlParams.logoutResponse) {
571
552
  return Promise.resolve('SKIPPED');
572
553
  }
573
- const fields = parserType === urlParams.samlResponse
554
+ let fields = parserType === urlParams.samlResponse
574
555
  ? loginResponseStatusFields
575
556
  : logoutResponseStatusFields;
557
+ if (soap === true) {
558
+ fields = parserType === urlParams.samlResponse
559
+ ? loginArtifactResponseStatusFields
560
+ : logoutResponseStatusFields;
561
+ }
576
562
  const { top, second } = extract(content, fields);
577
563
  // only resolve when top-tier status code is success
578
564
  if (top === StatusCode.Success) {
@@ -70,19 +70,22 @@ const libSaml = () => {
70
70
  context: '<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{ID}" Version="2.0" IssueInstant="{IssueInstant}" Destination="{Destination}" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="{AssertionConsumerServiceURL}"><saml:Issuer>{Issuer}</saml:Issuer><samlp:NameIDPolicy Format="{NameIDFormat}" AllowCreate="{AllowCreate}"/></samlp:AuthnRequest>',
71
71
  };
72
72
  /**
73
- * @desc Default art request template
73
+ * @desc Default logout request template
74
74
  * @type {LogoutRequestTemplate}
75
75
  */
76
76
  const defaultLogoutRequestTemplate = {
77
77
  context: '<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="{ID}" Version="2.0" IssueInstant="{IssueInstant}" Destination="{Destination}"><saml:Issuer>{Issuer}</saml:Issuer><saml:NameID Format="{NameIDFormat}">{NameID}</saml:NameID></samlp:LogoutRequest>',
78
78
  };
79
79
  /**
80
- * @desc Default logout request template
80
+ * @desc Default art request template
81
81
  * @type {LogoutRequestTemplate}
82
82
  */
83
83
  const defaultArtifactResolveTemplate = {
84
84
  context: `<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><saml2p:ArtifactResolve xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="{ID}" Version="2.0" IssueInstant="{IssueInstant}" Destination="{Destination}"><saml2:Issuer>{Issuer}</saml2:Issuer><saml2p:Artifact>{Art}</saml2p:Artifact></saml2p:ArtifactResolve></SOAP-ENV:Body></SOAP-ENV:Envelope>`,
85
85
  };
86
+ const defaultArtAuthnRequestTemplate = {
87
+ context: `<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header></SOAP-ENV:Header><samlp:ArtifactResponse xmlns="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}" InResponseTo="{InResponseTo}" Version="2.0" IssueInstant="{IssueInstant}"><saml:Issuer>{Issuer}</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status>{AuthnRequest}</samlp:ArtifactResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>`,
88
+ };
86
89
  /**
87
90
  * @desc Default AttributeStatement template
88
91
  * @type {AttributeStatementTemplate}
@@ -209,6 +212,7 @@ const libSaml = () => {
209
212
  createXPath,
210
213
  getQueryParamByType,
211
214
  defaultLoginRequestTemplate,
215
+ defaultArtAuthnRequestTemplate,
212
216
  defaultArtifactResolveTemplate,
213
217
  defaultLoginResponseTemplate,
214
218
  defaultAttributeStatementTemplate,
@@ -453,7 +457,7 @@ const libSaml = () => {
453
457
  assertionNode = node[0].toString();
454
458
  }
455
459
  }
456
-
460
+
457
461
  if (assertionSignatureNode.length === 1) {
458
462
  const verifiedAssertionInfo = extract(assertionSignatureNode[0].toString(), [{
459
463
  key: 'refURI',
@@ -485,7 +489,7 @@ const libSaml = () => {
485
489
  }]);
486
490
  assertionNode = verifiedDoc.assertion.toString();
487
491
  }
488
-
492
+
489
493
  return [verified, assertionNode];*/
490
494
  },
491
495
  verifySignatureSoap(xml, opts) {
@@ -71,8 +71,10 @@ export class SpMetadata extends Metadata {
71
71
  });
72
72
  }
73
73
  if (isNonEmptyArray(artifactResolutionService)) {
74
+ let indexCount = 0;
74
75
  artifactResolutionService.forEach(a => {
75
76
  const attr = {
77
+ index: String(indexCount++),
76
78
  Binding: a.Binding,
77
79
  Location: a.Location,
78
80
  };
@@ -128,8 +128,6 @@ export default class Metadata {
128
128
  getArtifactResolutionService(binding) {
129
129
  if (binding && isString(binding)) {
130
130
  const bindType = namespace.binding[binding];
131
- console.log(this.meta);
132
- console.log("看一下---------------------");
133
131
  let artifactResolutionService = this.meta.artifactResolutionService;
134
132
  if (!(artifactResolutionService instanceof Array)) {
135
133
  artifactResolutionService = [artifactResolutionService];
@@ -15,7 +15,7 @@
15
15
  <import namespace="urn:oasis:names:tc:SAML:2.0:assertion"
16
16
  schemaLocation="saml-schema-assertion-2.0.xsd"/>
17
17
  <import namespace="http://schemas.xmlsoap.org/soap/envelope/"
18
- schemaLocation="http://schemas.xmlsoap.org/soap/envelope/"/>
18
+ schemaLocation="soap-envelope.xsd"/>
19
19
  <annotation>
20
20
  <documentation>
21
21
  Document identifier: saml-schema-ecp-2.0
@@ -11,13 +11,13 @@
11
11
  blockDefault="substitution"
12
12
  version="2.0">
13
13
  <import namespace="http://www.w3.org/2000/09/xmldsig#"
14
- schemaLocation="http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd"/>
14
+ schemaLocation="xmldsig-core-schema.xsd"/>
15
15
  <import namespace="http://www.w3.org/2001/04/xmlenc#"
16
- schemaLocation="http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/xenc-schema.xsd"/>
16
+ schemaLocation="xenc-schema.xsd"/>
17
17
  <import namespace="urn:oasis:names:tc:SAML:2.0:assertion"
18
18
  schemaLocation="saml-schema-assertion-2.0.xsd"/>
19
19
  <import namespace="http://www.w3.org/XML/1998/namespace"
20
- schemaLocation="http://www.w3.org/2001/xml.xsd"/>
20
+ schemaLocation="xml.xsd"/>
21
21
  <annotation>
22
22
  <documentation>
23
23
  Document identifier: saml-schema-metadata-2.0
@@ -12,7 +12,7 @@
12
12
  <import namespace="urn:oasis:names:tc:SAML:2.0:assertion"
13
13
  schemaLocation="saml-schema-assertion-2.0.xsd"/>
14
14
  <import namespace="http://www.w3.org/2000/09/xmldsig#"
15
- schemaLocation="http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd"/>
15
+ schemaLocation="xmldsig-core-schema.xsd"/>
16
16
  <annotation>
17
17
  <documentation>
18
18
  Document identifier: saml-schema-protocol-2.0
@@ -1,36 +1,4 @@
1
-
2
- <!-- Schema for the SOAP/1.1 envelope
3
-
4
- Portions © 2001 DevelopMentor.
5
- © 2001 W3C (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved.
6
-
7
- This document is governed by the W3C Software License [1] as described in the FAQ [2].
8
- [1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
9
- [2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
10
- By obtaining, using and/or copying this work, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:
11
-
12
- Permission to use, copy, modify, and distribute this software and its documentation, with or without modification, for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the software and documentation or portions thereof, including modifications, that you make:
13
-
14
- 1. The full text of this NOTICE in a location viewable to users of the redistributed or derivative work.
15
-
16
- 2. Any pre-existing intellectual property disclaimers, notices, or terms and conditions. If none exist, a short notice of the following form (hypertext is preferred, text is permitted) should be used within the body of any redistributed or derivative code: "Copyright © 2001 World Wide Web Consortium, (Massachusetts Institute of Technology, Institut National de Recherche en Informatique et en Automatique, Keio University). All Rights Reserved. http://www.w3.org/Consortium/Legal/"
17
-
18
- 3. Notice of any changes or modifications to the W3C files, including the date changes were made. (We recommend you provide URIs to the location from which the code is derived.)
19
-
20
- Original W3C files; http://www.w3.org/2001/06/soap-envelope
21
- Changes made:
22
- - reverted namespace to http://schemas.xmlsoap.org/soap/envelope/
23
- - reverted mustUnderstand to only allow 0 and 1 as lexical values
24
- - made encodingStyle a global attribute 20020825
25
- - removed default value from mustUnderstand attribute declaration
26
-
27
- THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
28
-
29
- COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
30
-
31
- The name and trademarks of copyright holders may NOT be used in advertising or publicity pertaining to the software without specific, written prior permission. Title to copyright in this software and any associated documentation will at all times remain with copyright holders.
32
-
33
- -->
1
+ <?xml version="1.0" encoding="utf-8"?>
34
2
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.xmlsoap.org/soap/envelope/" targetNamespace="http://schemas.xmlsoap.org/soap/envelope/">
35
3
  <!-- Envelope, header and body -->
36
4
  <xs:element name="Envelope" type="tns:Envelope"/>