samlesa 2.12.3 → 2.12.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.

Potentially problematic release.


This version of samlesa might be problematic. Click here for more details.

Files changed (66) hide show
  1. package/build/index.js +54 -64
  2. package/build/index.js.map +1 -1
  3. package/build/src/api.js +24 -23
  4. package/build/src/api.js.map +1 -1
  5. package/build/src/binding-post.js +358 -368
  6. package/build/src/binding-post.js.map +1 -1
  7. package/build/src/binding-redirect.js +333 -332
  8. package/build/src/binding-redirect.js.map +1 -1
  9. package/build/src/binding-simplesign.js +222 -232
  10. package/build/src/binding-simplesign.js.map +1 -1
  11. package/build/src/entity-idp.js +132 -130
  12. package/build/src/entity-idp.js.map +1 -1
  13. package/build/src/entity-sp.js +96 -96
  14. package/build/src/entity-sp.js.map +1 -1
  15. package/build/src/entity.js +225 -235
  16. package/build/src/entity.js.map +1 -1
  17. package/build/src/extractor.js +369 -369
  18. package/build/src/extractor.js.map +1 -1
  19. package/build/src/flow.js +320 -319
  20. package/build/src/flow.js.map +1 -1
  21. package/build/src/libsaml.js +660 -641
  22. package/build/src/libsaml.js.map +1 -1
  23. package/build/src/metadata-idp.js +127 -127
  24. package/build/src/metadata-idp.js.map +1 -1
  25. package/build/src/metadata-sp.js +231 -231
  26. package/build/src/metadata-sp.js.map +1 -1
  27. package/build/src/metadata.js +166 -176
  28. package/build/src/metadata.js.map +1 -1
  29. package/build/src/types.js +11 -11
  30. package/build/src/urn.js +212 -212
  31. package/build/src/urn.js.map +1 -1
  32. package/build/src/utility.js +292 -248
  33. package/build/src/utility.js.map +1 -1
  34. package/build/src/validator.js +27 -26
  35. package/build/src/validator.js.map +1 -1
  36. package/index.d.ts +10 -10
  37. package/index.js +18 -18
  38. package/package.json +1 -5
  39. package/qodana.yaml +29 -29
  40. package/src/binding-post.ts +1 -1
  41. package/src/binding-redirect.ts +83 -64
  42. package/src/entity-idp.ts +26 -20
  43. package/src/libsaml.ts +79 -48
  44. package/src/utility.ts +147 -76
  45. package/types/index.d.ts +10 -10
  46. package/types/src/api.d.ts +13 -13
  47. package/types/src/binding-post.d.ts +46 -46
  48. package/types/src/binding-redirect.d.ts +52 -52
  49. package/types/src/binding-simplesign.d.ts +39 -39
  50. package/types/src/entity-idp.d.ts +35 -42
  51. package/types/src/entity-sp.d.ts +36 -36
  52. package/types/src/entity.d.ts +101 -99
  53. package/types/src/extractor.d.ts +25 -25
  54. package/types/src/flow.d.ts +6 -6
  55. package/types/src/libsaml.d.ts +200 -210
  56. package/types/src/metadata-idp.d.ts +24 -24
  57. package/types/src/metadata-sp.d.ts +36 -36
  58. package/types/src/metadata.d.ts +59 -57
  59. package/types/src/types.d.ts +129 -127
  60. package/types/src/urn.d.ts +194 -194
  61. package/types/src/utility.d.ts +134 -134
  62. package/types/src/validator.d.ts +3 -3
  63. package/.idea/compiler.xml +0 -6
  64. package/.idea/deployment.xml +0 -14
  65. package/.idea/jsLibraryMappings.xml +0 -6
  66. package/build/.idea/workspace.xml +0 -58
@@ -1 +1 @@
1
- {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/validator.ts"],"names":[],"mappings":";;AA0CE,gCAAU;AAvCZ,SAAS,UAAU,CACjB,YAAgC,EAChC,eAAmC,EACnC,QAAwB,CAAC,CAAC,EAAE,CAAC,CAAC;IAG9B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,IAAI,CAAC,YAAY,IAAI,CAAC,eAAe,EAAE,CAAC;QACtC,kHAAkH;QAClH,OAAO,CAAC,IAAI,CAAC,2FAA2F,CAAC,CAAC;QAC1G,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,cAAc,GAAgB,IAAI,CAAC;IACvC,IAAI,iBAAiB,GAAgB,IAAI,CAAC;IAE1C,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,KAAK,CAAC;IAElD,IAAI,YAAY,IAAI,CAAC,eAAe,EAAE,CAAC;QACrC,cAAc,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC;QACxC,OAAO,CAAC,cAAc,GAAG,cAAc,IAAI,CAAC,GAAG,CAAC;IAClD,CAAC;IACD,IAAI,CAAC,YAAY,IAAI,eAAe,EAAE,CAAC;QACrC,iBAAiB,GAAG,IAAI,IAAI,CAAC,eAAe,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,GAAG,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;IACvD,CAAC;IAED,cAAc,GAAG,IAAI,IAAI,CAAC,YAAa,CAAC,CAAC;IACzC,iBAAiB,GAAG,IAAI,IAAI,CAAC,eAAgB,CAAC,CAAC;IAE/C,OAAO,CACL,CAAC,cAAc,GAAG,cAAc,IAAI,CAAC,GAAG;QACxC,CAAC,GAAG,GAAG,CAAC,iBAAiB,GAAG,iBAAiB,CAC9C,CAAC;AAEJ,CAAC"}
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/validator.ts"],"names":[],"mappings":";;;AAGA,SAAS,UAAU,CACjB,YAAgC,EAChC,eAAmC,EACnC,QAAwB,CAAC,CAAC,EAAE,CAAC,CAAC;IAG9B,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IAEvB,IAAI,CAAC,YAAY,IAAI,CAAC,eAAe,EAAE;QACrC,kHAAkH;QAClH,OAAO,CAAC,IAAI,CAAC,2FAA2F,CAAC,CAAC;QAC1G,OAAO,IAAI,CAAC;KACb;IAED,IAAI,cAAc,GAAgB,IAAI,CAAC;IACvC,IAAI,iBAAiB,GAAgB,IAAI,CAAC;IAE1C,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,KAAK,CAAC;IAElD,IAAI,YAAY,IAAI,CAAC,eAAe,EAAE;QACpC,cAAc,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC;QACxC,OAAO,CAAC,cAAc,GAAG,cAAc,IAAI,CAAC,GAAG,CAAC;KACjD;IACD,IAAI,CAAC,YAAY,IAAI,eAAe,EAAE;QACpC,iBAAiB,GAAG,IAAI,IAAI,CAAC,eAAe,CAAC,CAAC;QAC9C,OAAO,CAAC,GAAG,GAAG,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;KACtD;IAED,cAAc,GAAG,IAAI,IAAI,CAAC,YAAa,CAAC,CAAC;IACzC,iBAAiB,GAAG,IAAI,IAAI,CAAC,eAAgB,CAAC,CAAC;IAE/C,OAAO,CACL,CAAC,cAAc,GAAG,cAAc,IAAI,CAAC,GAAG;QACxC,CAAC,GAAG,GAAG,CAAC,iBAAiB,GAAG,iBAAiB,CAC9C,CAAC;AAEJ,CAAC;AAGC,gCAAU"}
package/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- import IdentityProvider, { IdentityProvider as IdentityProviderInstance } from './src/entity-idp';
2
- import ServiceProvider, { ServiceProvider as ServiceProviderInstance } from './src/entity-sp';
3
- export { default as IdPMetadata } from './src/metadata-idp';
4
- export { default as SPMetadata } from './src/metadata-sp';
5
- export { default as Utility } from './src/utility';
6
- export { default as SamlLib } from './src/libsaml';
7
- import * as Constants from './src/urn';
8
- import * as Extractor from './src/extractor';
9
- import { setSchemaValidator, setDOMParserOptions } from './src/api';
10
- export { Constants, Extractor, IdentityProvider, IdentityProviderInstance, ServiceProvider, ServiceProviderInstance, setSchemaValidator, setDOMParserOptions };
1
+ import IdentityProvider, { IdentityProvider as IdentityProviderInstance } from './src/entity-idp';
2
+ import ServiceProvider, { ServiceProvider as ServiceProviderInstance } from './src/entity-sp';
3
+ export { default as IdPMetadata } from './src/metadata-idp';
4
+ export { default as SPMetadata } from './src/metadata-sp';
5
+ export { default as Utility } from './src/utility';
6
+ export { default as SamlLib } from './src/libsaml';
7
+ import * as Constants from './src/urn';
8
+ import * as Extractor from './src/extractor';
9
+ import { setSchemaValidator, setDOMParserOptions } from './src/api';
10
+ export { Constants, Extractor, IdentityProvider, IdentityProviderInstance, ServiceProvider, ServiceProviderInstance, setSchemaValidator, setDOMParserOptions };
package/index.js CHANGED
@@ -1,19 +1,19 @@
1
- // version <= 1.25
2
- import IdentityProvider, { IdentityProvider as IdentityProviderInstance } from './src/entity-idp';
3
- import ServiceProvider, { ServiceProvider as ServiceProviderInstance } from './src/entity-sp';
4
- export { default as IdPMetadata } from './src/metadata-idp';
5
- export { default as SPMetadata } from './src/metadata-sp';
6
- export { default as Utility } from './src/utility';
7
- export { default as SamlLib } from './src/libsaml';
8
- // roadmap
9
- // new name convention in version >= 3.0
10
- import * as Constants from './src/urn';
11
- import * as Extractor from './src/extractor';
12
- // exposed methods for customizing samlify
13
- import { setSchemaValidator, setDOMParserOptions } from './src/api';
14
- export { Constants, Extractor,
15
- // temp: resolve the conflict after version >= 3.0
16
- IdentityProvider, IdentityProviderInstance, ServiceProvider, ServiceProviderInstance,
17
- // set context
18
- setSchemaValidator, setDOMParserOptions };
1
+ // version <= 1.25
2
+ import IdentityProvider, { IdentityProvider as IdentityProviderInstance } from './src/entity-idp';
3
+ import ServiceProvider, { ServiceProvider as ServiceProviderInstance } from './src/entity-sp';
4
+ export { default as IdPMetadata } from './src/metadata-idp';
5
+ export { default as SPMetadata } from './src/metadata-sp';
6
+ export { default as Utility } from './src/utility';
7
+ export { default as SamlLib } from './src/libsaml';
8
+ // roadmap
9
+ // new name convention in version >= 3.0
10
+ import * as Constants from './src/urn';
11
+ import * as Extractor from './src/extractor';
12
+ // exposed methods for customizing samlify
13
+ import { setSchemaValidator, setDOMParserOptions } from './src/api';
14
+ export { Constants, Extractor,
15
+ // temp: resolve the conflict after version >= 3.0
16
+ IdentityProvider, IdentityProviderInstance, ServiceProvider, ServiceProviderInstance,
17
+ // set context
18
+ setSchemaValidator, setDOMParserOptions };
19
19
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "samlesa",
3
- "version": "2.12.3",
3
+ "version": "2.12.6",
4
4
  "description": "High-level API for Single Sign On (SAML 2.0) 维护分支:修复原项目samlify的一些问题 ",
5
5
  "main": "build/index.js",
6
6
  "keywords": [
@@ -35,8 +35,6 @@
35
35
  "xml-encryption": "^3.0.1",
36
36
  "@xmldom/xmldom": "^0.8.6",
37
37
  "camelcase": "^6.2.0",
38
- "node-forge": "^1.3.0",
39
- "node-rsa": "^1.1.1",
40
38
  "pako": "^1.0.10",
41
39
  "uuid": "^10.0.0",
42
40
  "xml": "^1.0.1",
@@ -47,8 +45,6 @@
47
45
  "devDependencies": {
48
46
  "@ava/typescript": "^1.1.1",
49
47
  "@types/node": "^22.15.17",
50
- "@types/node-forge": "^1.0.1",
51
- "@types/node-rsa": "^1.1.1",
52
48
  "@types/pako": "^1.0.1",
53
49
  "@types/uuid": "^10.0.0",
54
50
  "@types/xmldom": "^0.1.31",
package/qodana.yaml CHANGED
@@ -1,29 +1,29 @@
1
- #-------------------------------------------------------------------------------#
2
- # Qodana analysis is configured by qodana.yaml file #
3
- # https://www.jetbrains.com/help/qodana/qodana-yaml.html #
4
- #-------------------------------------------------------------------------------#
5
- version: "1.0"
6
-
7
- #Specify inspection profile for code analysis
8
- profile:
9
- name: qodana.starter
10
-
11
- #Enable inspections
12
- #include:
13
- # - name: <SomeEnabledInspectionId>
14
-
15
- #Disable inspections
16
- #exclude:
17
- # - name: <SomeDisabledInspectionId>
18
- # paths:
19
- # - <path/where/not/run/inspection>
20
-
21
- #Execute shell command before Qodana execution (Applied in CI/CD pipeline)
22
- #bootstrap: sh ./prepare-qodana.sh
23
-
24
- #Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
25
- #plugins:
26
- # - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
27
-
28
- #Specify Qodana linter for analysis (Applied in CI/CD pipeline)
29
- linter: jetbrains/qodana-js:2025.1
1
+ #-------------------------------------------------------------------------------#
2
+ # Qodana analysis is configured by qodana.yaml file #
3
+ # https://www.jetbrains.com/help/qodana/qodana-yaml.html #
4
+ #-------------------------------------------------------------------------------#
5
+ version: "1.0"
6
+
7
+ #Specify inspection profile for code analysis
8
+ profile:
9
+ name: qodana.starter
10
+
11
+ #Enable inspections
12
+ #include:
13
+ # - name: <SomeEnabledInspectionId>
14
+
15
+ #Disable inspections
16
+ #exclude:
17
+ # - name: <SomeDisabledInspectionId>
18
+ # paths:
19
+ # - <path/where/not/run/inspection>
20
+
21
+ #Execute shell command before Qodana execution (Applied in CI/CD pipeline)
22
+ #bootstrap: sh ./prepare-qodana.sh
23
+
24
+ #Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
25
+ #plugins:
26
+ # - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
27
+
28
+ #Specify Qodana linter for analysis (Applied in CI/CD pipeline)
29
+ linter: jetbrains/qodana-js:2025.1
@@ -168,7 +168,7 @@ async function base64LoginResponse(requestInfo: any = {}, entity: any, user: any
168
168
  },
169
169
  });
170
170
  console.log(rawSamlResponse);
171
- console.log("这他妈是什么------------------")
171
+ console.log('这他妈是什么------------------')
172
172
  }
173
173
 
174
174
  // console.debug('after message signed', rawSamlResponse);
@@ -1,15 +1,15 @@
1
1
  /**
2
- * @file binding-redirect.ts
3
- * @author tngan
4
- * @desc Binding-level API, declare the functions using Redirect binding
5
- */
6
- import utility, { get } from './utility.js';
2
+ * @file binding-redirect.ts
3
+ * @author tngan
4
+ * @desc Binding-level API, declare the functions using Redirect binding
5
+ */
6
+ import utility, {get} from './utility.js';
7
7
  import libsaml from './libsaml.js';
8
- import { BindingContext } from './entity.js';
9
- import { IdentityProvider as Idp } from './entity-idp.js';
10
- import { ServiceProvider as Sp } from './entity-sp.js';
11
- import * as url from 'url';
12
- import { wording, namespace } from './urn.js';
8
+ import {BindingContext} from './entity.js';
9
+ import {IdentityProvider as Idp} from './entity-idp.js';
10
+ import {ServiceProvider as Sp} from './entity-sp.js';
11
+
12
+ import {wording, namespace} from './urn.js';
13
13
 
14
14
  const binding = wording.binding;
15
15
  const urlParams = wording.urlParams;
@@ -24,25 +24,26 @@ export interface BuildRedirectConfig {
24
24
  }
25
25
 
26
26
  /**
27
- * @private
28
- * @desc Helper of generating URL param/value pair
29
- * @param {string} param key
30
- * @param {string} value value of key
31
- * @param {boolean} first determine whether the param is the starting one in order to add query header '?'
32
- * @return {string}
33
- */
27
+ * @private
28
+ * @desc Helper of generating URL param/value pair
29
+ * @param {string} param key
30
+ * @param {string} value value of key
31
+ * @param {boolean} first determine whether the param is the starting one in order to add query header '?'
32
+ * @return {string}
33
+ */
34
34
  function pvPair(param: string, value: string, first?: boolean): string {
35
35
  return (first === true ? '?' : '&') + param + '=' + value;
36
36
  }
37
+
37
38
  /**
38
- * @private
39
- * @desc Refractored part of URL generation for login/logout request
40
- * @param {string} type
41
- * @param {boolean} isSigned
42
- * @param {string} rawSamlRequest
43
- * @param {object} entitySetting
44
- * @return {string}
45
- */
39
+ * @private
40
+ * @desc Refractored part of URL generation for login/logout request
41
+ * @param {string} type
42
+ * @param {boolean} isSigned
43
+ * @param {string} rawSamlRequest
44
+ * @param {object} entitySetting
45
+ * @return {string}
46
+ */
46
47
  function buildRedirectURL(opts: BuildRedirectConfig) {
47
48
  const {
48
49
  baseUrl,
@@ -51,8 +52,14 @@ function buildRedirectURL(opts: BuildRedirectConfig) {
51
52
  context,
52
53
  entitySetting,
53
54
  } = opts;
54
- let { relayState = '' } = opts;
55
- const noParams = (url.parse(baseUrl).query || []).length === 0;
55
+ let {relayState = ''} = opts;
56
+ let noParams = true
57
+ try {
58
+ noParams = new URL(baseUrl)?.searchParams?.size === 0
59
+ } catch {
60
+ noParams = true
61
+ }
62
+
56
63
  const queryParam = libsaml.getQueryParamByType(type);
57
64
  // In general, this xmlstring is required to do deflate -> base64 -> urlencode
58
65
  const samlRequest = encodeURIComponent(utility.base64Encode(utility.deflateString(context)));
@@ -65,27 +72,31 @@ function buildRedirectURL(opts: BuildRedirectConfig) {
65
72
  return baseUrl
66
73
  + pvPair(queryParam, octetString, noParams)
67
74
  + pvPair(urlParams.signature, encodeURIComponent(
68
- libsaml.constructMessageSignature(
69
- queryParam + '=' + octetString,
70
- entitySetting.privateKey,
71
- entitySetting.privateKeyPass,
72
- undefined,
73
- entitySetting.requestSignatureAlgorithm
74
- ).toString()
75
- )
75
+ libsaml.constructMessageSignature(
76
+ queryParam + '=' + octetString,
77
+ entitySetting.privateKey,
78
+ entitySetting.privateKeyPass,
79
+ undefined,
80
+ entitySetting.requestSignatureAlgorithm
81
+ ).toString()
82
+ )
76
83
  );
77
84
  }
78
85
  return baseUrl + pvPair(queryParam, samlRequest + relayState, noParams);
79
86
  }
87
+
80
88
  /**
81
- * @desc Redirect URL for login request
82
- * @param {object} entity object includes both idp and sp
83
- * @param {function} customTagReplacement used when developers have their own login response template
84
- * @return {string} redirect URL
85
- */
86
- function loginRequestRedirectURL(entity: { idp: Idp, sp: Sp }, customTagReplacement?: (template: string) => BindingContext): BindingContext {
89
+ * @desc Redirect URL for login request
90
+ * @param {object} entity object includes both idp and sp
91
+ * @param {function} customTagReplacement used when developers have their own login response template
92
+ * @return {string} redirect URL
93
+ */
94
+ function loginRequestRedirectURL(entity: {
95
+ idp: Idp,
96
+ sp: Sp
97
+ }, customTagReplacement?: (template: string) => BindingContext): BindingContext {
87
98
 
88
- const metadata: any = { idp: entity.idp.entityMeta, sp: entity.sp.entityMeta };
99
+ const metadata: any = {idp: entity.idp.entityMeta, sp: entity.sp.entityMeta};
89
100
  const spSetting: any = entity.sp.entitySetting;
90
101
  let id: string = '';
91
102
 
@@ -127,13 +138,13 @@ function loginRequestRedirectURL(entity: { idp: Idp, sp: Sp }, customTagReplacem
127
138
  }
128
139
 
129
140
  /**
130
- * @desc Redirect URL for login response
131
- * @param {object} requestInfo corresponding request, used to obtain the id
132
- * @param {object} entity object includes both idp and sp
133
- * @param {object} user current logged user (e.g. req.user)
134
- * @param {String} relayState the relaystate sent by sp corresponding request
135
- * @param {function} customTagReplacement used when developers have their own login response template
136
- */
141
+ * @desc Redirect URL for login response
142
+ * @param {object} requestInfo corresponding request, used to obtain the id
143
+ * @param {object} entity object includes both idp and sp
144
+ * @param {object} user current logged user (e.g. req.user)
145
+ * @param {String} relayState the relaystate sent by sp corresponding request
146
+ * @param {function} customTagReplacement used when developers have their own login response template
147
+ */
137
148
  function loginResponseRedirectURL(requestInfo: any, entity: any, user: any = {}, relayState?: string, customTagReplacement?: (template: string) => BindingContext): BindingContext {
138
149
  const idpSetting = entity.idp.entitySetting;
139
150
  const spSetting = entity.sp.entitySetting;
@@ -144,7 +155,11 @@ function loginResponseRedirectURL(requestInfo: any, entity: any, user: any = {},
144
155
 
145
156
  let id: string = idpSetting.generateID();
146
157
  if (metadata && metadata.idp && metadata.sp) {
147
- const base = metadata.sp.getAssertionConsumerService(binding.redirect);
158
+ const base = metadata.sp.getAssertionConsumerService(binding.redirect) ?? 'https://signin.volcengine.com/saml/sso';
159
+ if(!base){
160
+ throw new Error('dont have a base url');
161
+ }
162
+
148
163
  let rawSamlResponse: string;
149
164
  //
150
165
  const nameIDFormat = idpSetting.nameIDFormat;
@@ -186,7 +201,7 @@ function loginResponseRedirectURL(requestInfo: any, entity: any, user: any = {},
186
201
  rawSamlResponse = libsaml.replaceTagsByValue(libsaml.defaultLoginResponseTemplate.context, tvalue);
187
202
  }
188
203
 
189
- const { privateKey, privateKeyPass, requestSignatureAlgorithm: signatureAlgorithm } = idpSetting;
204
+ const {privateKey, privateKeyPass, requestSignatureAlgorithm: signatureAlgorithm} = idpSetting;
190
205
  const config = {
191
206
  privateKey,
192
207
  privateKeyPass,
@@ -203,7 +218,10 @@ function loginResponseRedirectURL(requestInfo: any, entity: any, user: any = {},
203
218
  referenceTagXPath: "/*[local-name(.)='Response']/*[local-name(.)='Assertion']",
204
219
  signatureConfig: {
205
220
  prefix: 'ds',
206
- location: { reference: "/*[local-name(.)='Response']/*[local-name(.)='Assertion']/*[local-name(.)='Issuer']", action: 'after' },
221
+ location: {
222
+ reference: "/*[local-name(.)='Response']/*[local-name(.)='Assertion']/*[local-name(.)='Issuer']",
223
+ action: 'after'
224
+ },
207
225
  },
208
226
  });
209
227
  }
@@ -225,14 +243,14 @@ function loginResponseRedirectURL(requestInfo: any, entity: any, user: any = {},
225
243
  }
226
244
 
227
245
  /**
228
- * @desc Redirect URL for logout request
229
- * @param {object} user current logged user (e.g. req.user)
230
- * @param {object} entity object includes both idp and sp
231
- * @param {function} customTagReplacement used when developers have their own login response template
232
- * @return {string} redirect URL
233
- */
246
+ * @desc Redirect URL for logout request
247
+ * @param {object} user current logged user (e.g. req.user)
248
+ * @param {object} entity object includes both idp and sp
249
+ * @param {function} customTagReplacement used when developers have their own login response template
250
+ * @return {string} redirect URL
251
+ */
234
252
  function logoutRequestRedirectURL(user, entity, relayState?: string, customTagReplacement?: (template: string, tags: object) => BindingContext): BindingContext {
235
- const metadata = { init: entity.init.entityMeta, target: entity.target.entityMeta };
253
+ const metadata = {init: entity.init.entityMeta, target: entity.target.entityMeta};
236
254
  const initSetting = entity.init.entitySetting;
237
255
  let id: string = initSetting.generateID();
238
256
  const nameIDFormat = initSetting.nameIDFormat;
@@ -272,12 +290,13 @@ function logoutRequestRedirectURL(user, entity, relayState?: string, customTagRe
272
290
  }
273
291
  throw new Error('ERR_GENERATE_REDIRECT_LOGOUT_REQUEST_MISSING_METADATA');
274
292
  }
293
+
275
294
  /**
276
- * @desc Redirect URL for logout response
277
- * @param {object} requescorresponding request, used to obtain the id
278
- * @param {object} entity object includes both idp and sp
279
- * @param {function} customTagReplacement used when developers have their own login response template
280
- */
295
+ * @desc Redirect URL for logout response
296
+ * @param {object} requescorresponding request, used to obtain the id
297
+ * @param {object} entity object includes both idp and sp
298
+ * @param {function} customTagReplacement used when developers have their own login response template
299
+ */
281
300
  function logoutResponseRedirectURL(requestInfo: any, entity: any, relayState?: string, customTagReplacement?: (template: string) => BindingContext): BindingContext {
282
301
  const metadata = {
283
302
  init: entity.init.entityMeta,
package/src/entity-idp.ts CHANGED
@@ -3,12 +3,19 @@
3
3
  * @author tngan
4
4
  * @desc Declares the actions taken by identity provider
5
5
  */
6
+ import {
7
+ wording,
8
+ } from './urn.js';
9
+ const binding = wording.binding
10
+
11
+
12
+
6
13
  import Entity, { ESamlHttpRequest } from './entity.js';
7
14
  import {
8
15
  ServiceProviderConstructor as ServiceProvider,
9
16
  ServiceProviderMetadata,
10
17
  IdentityProviderMetadata,
11
- IdentityProviderSettings,
18
+ IdentityProviderSettings
12
19
  } from './types.js';
13
20
  import libsaml from './libsaml.js';
14
21
  import { namespace } from './urn.js';
@@ -71,25 +78,21 @@ export class IdentityProvider extends Entity {
71
78
  }
72
79
 
73
80
  /**
74
- * @desc Generates the login response for developers to design their own method
75
- * @param sp object of service provider
76
- * @param requestInfo corresponding request, used to obtain the id
77
- * @param binding protocol binding
78
- * @param user current logged user (e.g. req.user)
79
- * @param customTagReplacement used when developers have their own login response template
80
- * @param encryptThenSign whether or not to encrypt then sign first (if signing)
81
- * @param relayState the relayState from corresponding request
82
- */
83
- public async createLoginResponse(
84
- sp: ServiceProvider,
85
- requestInfo: { [key: string]: any },
86
- binding: string,
87
- user: { [key: string]: any },
81
+ * @desc Generates the login response for developers to design their own method
82
+ * @param params
83
+ */
84
+ public async createLoginResponse(params:{
85
+ sp: ServiceProvider;
86
+ requestInfo: Record<string, any>;
87
+ binding?: string; // 可选参数,带默认值
88
+ user: Record<string, any>;
88
89
  customTagReplacement?: (template: string) => BindingContext,
89
90
  encryptThenSign?: boolean,
90
91
  relayState?: string,
91
- ) {
92
- const protocol = namespace.binding[binding];
92
+ }) {
93
+ const bindType = params?.binding ?? 'post';
94
+ const { sp,requestInfo ={}, user = {},customTagReplacement,encryptThenSign = false ,relayState=''} = params
95
+ const protocol = namespace.binding[bindType];
93
96
  // can support post, redirect and post simple sign bindings for login response
94
97
  let context: any = null;
95
98
  switch (protocol) {
@@ -111,15 +114,18 @@ export class IdentityProvider extends Entity {
111
114
  idp: this,
112
115
  sp,
113
116
  }, user, relayState, customTagReplacement);
114
-
115
117
  default:
116
- throw new Error('ERR_CREATE_RESPONSE_UNDEFINED_BINDING');
118
+ context = await postBinding.base64LoginResponse(requestInfo, {
119
+ idp: this,
120
+ sp,
121
+ }, user, customTagReplacement, encryptThenSign);
122
+ /* throw new Error('ERR_CREATE_RESPONSE_UNDEFINED_BINDING');*/
117
123
  }
118
124
 
119
125
  return {
120
126
  ...context,
121
127
  relayState,
122
- entityEndpoint: (sp.entityMeta as ServiceProviderMetadata).getAssertionConsumerService(binding) as string,
128
+ entityEndpoint: (sp.entityMeta as ServiceProviderMetadata).getAssertionConsumerService(bindType ?? 'post') as string,
123
129
  type: 'SAMLResponse'
124
130
  };
125
131
  }
package/src/libsaml.ts CHANGED
@@ -3,12 +3,12 @@
3
3
  * @author tngan
4
4
  * @desc A simple library including some common functions
5
5
  */
6
-
6
+ import { createSign, createPrivateKey,createVerify } from 'node:crypto';
7
7
  import utility, { flattenDeep, isString } from './utility.js';
8
8
  import { algorithms, wording, namespace } from './urn.js';
9
9
  import { select } from 'xpath';
10
10
  import { MetadataInterface } from './metadata.js';
11
- import nrsa, { SigningSchemeHash } from 'node-rsa';
11
+
12
12
  import { SignedXml } from 'xml-crypto';
13
13
  import * as xmlenc from 'xml-encryption';
14
14
  import { extract } from './extractor.js';
@@ -22,7 +22,22 @@ const signatureAlgorithms = algorithms.signature;
22
22
  const digestAlgorithms = algorithms.digest;
23
23
  const certUse = wording.certUse;
24
24
  const urlParams = wording.urlParams;
25
+ /**
26
+ * 算法名称映射表 (兼容 X.509 和 SAML 规范)
27
+ */
28
+ function mapSignAlgorithm(algorithm: string): string {
29
+ const algorithmMap = {
30
+ 'rsa-sha1': 'RSA-SHA1',
31
+ 'rsa-sha256': 'RSA-SHA256',
32
+ 'rsa-sha384': 'RSA-SHA384',
33
+ 'rsa-sha512': 'RSA-SHA512',
34
+ 'ecdsa-sha256': 'ECDSA-SHA256',
35
+ 'ecdsa-sha384': 'ECDSA-SHA384',
36
+ 'ecdsa-sha512': 'ECDSA-SHA512'
37
+ };
25
38
 
39
+ return algorithmMap[algorithm.toLowerCase()] || algorithm;
40
+ }
26
41
  export interface SignatureConstructor {
27
42
  rawSamlMessage: string;
28
43
  referenceTagXPath?: string;
@@ -139,6 +154,11 @@ const libSaml = () => {
139
154
  'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256': 'pkcs1-sha256',
140
155
  'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512': 'pkcs1-sha512',
141
156
  };
157
+ const nrsaAliasMappingForNode = {
158
+ 'http://www.w3.org/2000/09/xmldsig#rsa-sha1': 'RSA-SHA1',
159
+ 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256': 'RSA-SHA256',
160
+ 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512': 'RSA-SHA512',
161
+ };
142
162
  /**
143
163
  * @desc Default login request template
144
164
  * @type {LoginRequestTemplate}
@@ -189,20 +209,15 @@ const libSaml = () => {
189
209
  const defaultLogoutResponseTemplate = {
190
210
  context: '<samlp:LogoutResponse 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}" InResponseTo="{InResponseTo}"><saml:Issuer>{Issuer}</saml:Issuer><samlp:Status><samlp:StatusCode Value="{StatusCode}"/></samlp:Status></samlp:LogoutResponse>',
191
211
  };
192
- /**
193
- * @private
194
- * @desc Get the signing scheme alias by signature algorithms, used by the node-rsa module
195
- * @param {string} sigAlg signature algorithm
196
- * @return {string/null} signing algorithm short-hand for the module node-rsa
197
- */
198
- function getSigningScheme(sigAlg?: string): SigningSchemeHash {
212
+
213
+ function getSigningSchemeForNode(sigAlg?: string){
199
214
  if (sigAlg) {
200
- const algAlias = nrsaAliasMapping[sigAlg];
215
+ const algAlias = nrsaAliasMappingForNode[sigAlg];
201
216
  if (!(algAlias === undefined)) {
202
217
  return algAlias;
203
218
  }
204
219
  }
205
- return nrsaAliasMapping[signatureAlgorithms.RSA_SHA1];
220
+ return nrsaAliasMappingForNode[signatureAlgorithms.RSA_SHA256];
206
221
  }
207
222
  /**
208
223
  * @private
@@ -587,42 +602,51 @@ const libSaml = () => {
587
602
  }],
588
603
  };
589
604
  },
605
+
590
606
  /**
591
- * @desc Constructs SAML message
592
- * @param {string} octetString see "Bindings for the OASIS Security Assertion Markup Language (SAML V2.0)" P.17/46
593
- * @param {string} key declares the pem-formatted private key
594
- * @param {string} passphrase passphrase of private key [optional]
595
- * @param {string} signingAlgorithm signing algorithm
596
- * @return {string} message signature
597
- */
607
+ * SAML 消息签名 (符合 SAML V2.0 绑定规范)
608
+ * @param octetString - 要签名的原始数据 (OCTET STRING)
609
+ * @param key - PEM 格式私钥
610
+ * @param passphrase - 私钥密码 (如果有加密)
611
+ * @param isBase64 - 是否返回 base64 编码 (默认 true)
612
+ * @param signingAlgorithm - 签名算法 (默认 'rsa-sha256')
613
+ * @returns 消息签名
614
+ */
615
+
598
616
  constructMessageSignature(
599
- octetString: string,
600
- key: string,
601
- passphrase?: string,
602
- isBase64?: boolean,
603
- signingAlgorithm?: string
604
- ) {
605
- // Default returning base64 encoded signature
606
- // Embed with node-rsa module
607
- const decryptedKey = new nrsa(
608
- utility.readPrivateKey(key, passphrase),
609
- undefined,
610
- {
611
- signingScheme: getSigningScheme(signingAlgorithm),
612
- }
613
- );
614
- const signature = decryptedKey.sign(octetString);
615
- // Use private key to sign data
616
- return isBase64 !== false ? signature.toString('base64') : signature;
617
- },
618
- /**
619
- * @desc Verifies message signature
620
- * @param {Metadata} metadata metadata object of identity provider or service provider
621
- * @param {string} octetString see "Bindings for the OASIS Security Assertion Markup Language (SAML V2.0)" P.17/46
622
- * @param {string} signature context of XML signature
623
- * @param {string} verifyAlgorithm algorithm used to verify
624
- * @return {boolean} verification result
625
- */
617
+ octetString: string | Buffer,
618
+ key: string | Buffer,
619
+ passphrase?: string,
620
+ isBase64: boolean = true,
621
+ signingAlgorithm: string = nrsaAliasMappingForNode[signatureAlgorithms.RSA_SHA256]
622
+ ): string | Buffer {
623
+ try {
624
+ // 1. 标准化输入数据
625
+ const inputData = Buffer.isBuffer(octetString)
626
+ ? octetString
627
+ : Buffer.from(octetString, 'utf8');
628
+ // 2. 创建签名器并设置算
629
+ const signingAlgorithmValue = getSigningSchemeForNode(signingAlgorithm)
630
+ const signer = createSign(signingAlgorithmValue)
631
+
632
+ // 3. 加载私钥
633
+ const privateKey = createPrivateKey({
634
+ key: key,
635
+ format: 'pem',
636
+ passphrase: passphrase,
637
+ encoding: 'utf8'
638
+ });
639
+ signer.write(octetString);
640
+ signer.end();
641
+ const signature = signer.sign(privateKey, 'base64');
642
+ console.log(signature.toString());
643
+ console.log('dayingyixia')
644
+ // 5. 处理编码输出
645
+ return isBase64 ? signature.toString() : signature;
646
+ } catch (error) {
647
+ throw new Error(`SAML 签名失败: ${error.message}`);
648
+ }
649
+ },
626
650
  verifyMessageSignature(
627
651
  metadata,
628
652
  octetString: string,
@@ -630,10 +654,17 @@ const libSaml = () => {
630
654
  verifyAlgorithm?: string
631
655
  ) {
632
656
  const signCert = metadata.getX509Certificate(certUse.signing);
633
- const signingScheme = getSigningScheme(verifyAlgorithm);
634
- const key = new nrsa(utility.getPublicKeyPemFromCertificate(signCert), 'public', { signingScheme });
635
- return key.verify(Buffer.from(octetString), Buffer.from(signature));
657
+ const signingScheme = getSigningSchemeForNode(verifyAlgorithm);
658
+ const verifier = createVerify(signingScheme);
659
+ verifier.update(octetString);
660
+ const isValid = verifier.verify(utility.getPublicKeyPemFromCertificate(signCert), Buffer.isBuffer(signature) ? signature : Buffer.from(signature, 'base64'));
661
+ console.log(isValid);
662
+ console.log('验证结果-------------')
663
+ return isValid
664
+
636
665
  },
666
+
667
+
637
668
  /**
638
669
  * @desc Get the public key in string format
639
670
  * @param {string} x509Certificate certificate