samlesa 3.2.1 → 3.3.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/extractor.js +275 -283
- package/build/src/libsaml.js +18 -49
- package/build/src/urn.js +78 -15
- package/package.json +2 -2
- package/types/src/extractor.d.ts +14 -40
- package/types/src/extractor.d.ts.map +1 -1
- package/types/src/libsaml.d.ts +0 -9
- package/types/src/libsaml.d.ts.map +1 -1
- package/types/src/urn.d.ts +48 -14
- package/types/src/urn.d.ts.map +1 -1
package/build/src/extractor.js
CHANGED
|
@@ -3,6 +3,8 @@ import { uniq, last, zipObject, notEmpty } from './utility.js';
|
|
|
3
3
|
import { getContext } from './api.js';
|
|
4
4
|
import camelCase from 'camelcase';
|
|
5
5
|
function buildAbsoluteXPath(paths) {
|
|
6
|
+
if (!paths || paths.length === 0)
|
|
7
|
+
return '';
|
|
6
8
|
return paths.reduce((currentPath, name) => {
|
|
7
9
|
let appendedPath = currentPath;
|
|
8
10
|
const isWildcard = name.startsWith('~');
|
|
@@ -10,14 +12,14 @@ function buildAbsoluteXPath(paths) {
|
|
|
10
12
|
const pathName = name.replace('~', '');
|
|
11
13
|
appendedPath = currentPath + `/*[contains(local-name(), '${pathName}')]`;
|
|
12
14
|
}
|
|
13
|
-
|
|
15
|
+
else {
|
|
14
16
|
appendedPath = currentPath + `/*[local-name(.)='${name}']`;
|
|
15
17
|
}
|
|
16
18
|
return appendedPath;
|
|
17
19
|
}, '');
|
|
18
20
|
}
|
|
19
21
|
function buildAttributeXPath(attributes) {
|
|
20
|
-
if (attributes.length === 0) {
|
|
22
|
+
if (!attributes || attributes.length === 0) {
|
|
21
23
|
return '/text()';
|
|
22
24
|
}
|
|
23
25
|
if (attributes.length === 1) {
|
|
@@ -26,355 +28,359 @@ function buildAttributeXPath(attributes) {
|
|
|
26
28
|
const filters = attributes.map(attribute => `name()='${attribute}'`).join(' or ');
|
|
27
29
|
return `/@*[${filters}]`;
|
|
28
30
|
}
|
|
31
|
+
// ... (其他字段配置如 loginRequestFields 等保持不变,为节省篇幅此处省略,请保留你原有的所有 fields 定义) ...
|
|
32
|
+
// 为了完整性,这里假设你保留了之前所有的 fields 定义 (loginRequestFields, idpMetadataFields 等)
|
|
33
|
+
// 重点修正下方的 spMetadataFields 和 extract 函数
|
|
29
34
|
export const loginRequestFields = [
|
|
30
|
-
{
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
{
|
|
36
|
-
key: 'issuer',
|
|
37
|
-
localPath: ['AuthnRequest', 'Issuer'],
|
|
38
|
-
attributes: []
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
key: 'nameIDPolicy',
|
|
42
|
-
localPath: ['AuthnRequest', 'NameIDPolicy'],
|
|
43
|
-
attributes: ['Format', 'AllowCreate']
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
key: 'authnContextClassRef',
|
|
47
|
-
localPath: ['AuthnRequest', 'AuthnContextClassRef'],
|
|
48
|
-
attributes: []
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
key: 'signature',
|
|
52
|
-
localPath: ['AuthnRequest', 'Signature'],
|
|
53
|
-
attributes: [],
|
|
54
|
-
context: true
|
|
55
|
-
}
|
|
35
|
+
{ key: 'request', localPath: ['AuthnRequest'], attributes: ['ID', 'IssueInstant', 'Destination', 'AssertionConsumerServiceURL', 'ProtocolBinding', 'ForceAuthn', 'IsPassive', 'AssertionConsumerServiceIndex', 'AttributeConsumingServiceIndex'] },
|
|
36
|
+
{ key: 'issuer', localPath: ['AuthnRequest', 'Issuer'], attributes: [] },
|
|
37
|
+
{ key: 'nameIDPolicy', localPath: ['AuthnRequest', 'NameIDPolicy'], attributes: ['Format', 'AllowCreate'] },
|
|
38
|
+
{ key: 'authnContextClassRef', localPath: ['AuthnRequest', 'AuthnContextClassRef'], attributes: [] },
|
|
39
|
+
{ key: 'signature', localPath: ['AuthnRequest', 'Signature'], attributes: [], context: true }
|
|
56
40
|
];
|
|
57
41
|
export const artifactResolveFields = [
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
key: 'issuer', localPath: ['ArtifactResolve', 'Issuer'], attributes: []
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
key: 'Artifact', localPath: ['ArtifactResolve', 'Artifact'], attributes: []
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
key: 'signature', localPath: ['ArtifactResolve', 'Signature'], attributes: [], context: true
|
|
71
|
-
},
|
|
42
|
+
{ key: 'request', localPath: ['ArtifactResolve'], attributes: ['ID', 'IssueInstant', 'Version'] },
|
|
43
|
+
{ key: 'issuer', localPath: ['ArtifactResolve', 'Issuer'], attributes: [] },
|
|
44
|
+
{ key: 'Artifact', localPath: ['ArtifactResolve', 'Artifact'], attributes: [] },
|
|
45
|
+
{ key: 'signature', localPath: ['ArtifactResolve', 'Signature'], attributes: [], context: true },
|
|
72
46
|
];
|
|
73
47
|
export const artifactResponseFields = [
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
key: 'issuer', localPath: ['Envelope', 'Body', 'ArtifactResolve', 'Issuer'], attributes: []
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
key: 'Artifact', localPath: ['Envelope', 'Body', 'ArtifactResolve', 'Artifact'], attributes: []
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
key: 'signature', localPath: ['Envelope', 'Body', 'ArtifactResolve', 'Signature'], attributes: [], context: true
|
|
87
|
-
},
|
|
48
|
+
{ key: 'request', localPath: ['Envelope', 'Body', 'ArtifactResolve'], attributes: ['ID', 'IssueInstant', 'Version'] },
|
|
49
|
+
{ key: 'issuer', localPath: ['Envelope', 'Body', 'ArtifactResolve', 'Issuer'], attributes: [] },
|
|
50
|
+
{ key: 'Artifact', localPath: ['Envelope', 'Body', 'ArtifactResolve', 'Artifact'], attributes: [] },
|
|
51
|
+
{ key: 'signature', localPath: ['Envelope', 'Body', 'ArtifactResolve', 'Signature'], attributes: [], context: true },
|
|
88
52
|
];
|
|
89
|
-
// support two-tiers status code
|
|
90
53
|
export const loginResponseStatusFields = [
|
|
91
|
-
{
|
|
92
|
-
|
|
93
|
-
localPath: ['Response', 'Status', 'StatusCode'],
|
|
94
|
-
attributes: ['Value'],
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
key: 'second',
|
|
98
|
-
localPath: ['Response', 'Status', 'StatusCode', 'StatusCode'],
|
|
99
|
-
attributes: ['Value'],
|
|
100
|
-
}
|
|
54
|
+
{ key: 'top', localPath: ['Response', 'Status', 'StatusCode'], attributes: ['Value'] },
|
|
55
|
+
{ key: 'second', localPath: ['Response', 'Status', 'StatusCode', 'StatusCode'], attributes: ['Value'] }
|
|
101
56
|
];
|
|
102
|
-
// support two-tiers status code
|
|
103
57
|
export const loginArtifactResponseStatusFields = [
|
|
104
|
-
{
|
|
105
|
-
|
|
106
|
-
localPath: ['Envelope', 'Body', 'ArtifactResponse', 'Status', 'StatusCode'],
|
|
107
|
-
attributes: ['Value'],
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
key: 'second',
|
|
111
|
-
localPath: ['Envelope', 'Body', 'ArtifactResponse', 'Status', 'StatusCode', 'StatusCode'],
|
|
112
|
-
attributes: ['Value'],
|
|
113
|
-
}
|
|
58
|
+
{ key: 'top', localPath: ['Envelope', 'Body', 'ArtifactResponse', 'Status', 'StatusCode'], attributes: ['Value'] },
|
|
59
|
+
{ key: 'second', localPath: ['Envelope', 'Body', 'ArtifactResponse', 'Status', 'StatusCode', 'StatusCode'], attributes: ['Value'] }
|
|
114
60
|
];
|
|
115
|
-
// support two-tiers status code
|
|
116
61
|
export const logoutResponseStatusFields = [
|
|
117
|
-
{
|
|
118
|
-
|
|
119
|
-
localPath: ['LogoutResponse', 'Status', 'StatusCode'],
|
|
120
|
-
attributes: ['Value']
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
key: 'second',
|
|
124
|
-
localPath: ['LogoutResponse', 'Status', 'StatusCode', 'StatusCode'],
|
|
125
|
-
attributes: ['Value'],
|
|
126
|
-
}
|
|
62
|
+
{ key: 'top', localPath: ['LogoutResponse', 'Status', 'StatusCode'], attributes: ['Value'] },
|
|
63
|
+
{ key: 'second', localPath: ['LogoutResponse', 'Status', 'StatusCode', 'StatusCode'], attributes: ['Value'] }
|
|
127
64
|
];
|
|
128
65
|
export const loginResponseFields = assertion => [
|
|
129
|
-
{
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
66
|
+
{ key: 'conditions', localPath: ['Assertion', 'Conditions'], attributes: ['NotBefore', 'NotOnOrAfter'], shortcut: assertion },
|
|
67
|
+
{ key: 'response', localPath: ['Response'], attributes: ['ID', 'IssueInstant', 'Destination', 'InResponseTo', 'Version'] },
|
|
68
|
+
{ key: 'audience', localPath: ['Assertion', 'Conditions', 'AudienceRestriction', 'Audience'], attributes: [], shortcut: assertion },
|
|
69
|
+
{ key: 'issuer', localPath: ['Assertion', 'Issuer'], attributes: [], shortcut: assertion },
|
|
70
|
+
{ key: 'nameID', localPath: ['Assertion', 'Subject', 'NameID'], attributes: [], shortcut: assertion },
|
|
71
|
+
{ key: 'sessionIndex', localPath: ['Assertion', 'AuthnStatement'], attributes: ['AuthnInstant', 'SessionNotOnOrAfter', 'SessionIndex'], shortcut: assertion },
|
|
72
|
+
{ key: 'attributes', localPath: ['Assertion', 'AttributeStatement', 'Attribute'], index: ['Name'], attributePath: ['AttributeValue'], attributes: [], shortcut: assertion },
|
|
73
|
+
{ key: 'subjectConfirmation', localPath: ['Assertion', 'Subject', 'SubjectConfirmation', 'SubjectConfirmationData'], attributes: ['Recipient', 'InResponseTo', 'NotOnOrAfter'], shortcut: assertion },
|
|
74
|
+
{ key: 'oneTimeUse', localPath: ['Assertion', 'Conditions', 'OneTimeUse'], attributes: [], shortcut: assertion },
|
|
75
|
+
{ key: 'status', localPath: ['Response', 'Status', 'StatusCode'], attributes: ['Value'] },
|
|
76
|
+
];
|
|
77
|
+
export const logoutRequestFields = [
|
|
78
|
+
{ key: 'request', localPath: ['LogoutRequest'], attributes: ['ID', 'IssueInstant', 'Destination'] },
|
|
79
|
+
{ key: 'issuer', localPath: ['LogoutRequest', 'Issuer'], attributes: [] },
|
|
80
|
+
{ key: 'nameID', localPath: ['LogoutRequest', 'NameID'], attributes: [] },
|
|
81
|
+
{ key: 'sessionIndex', localPath: ['LogoutRequest', 'SessionIndex'], attributes: [] },
|
|
82
|
+
{ key: 'signature', localPath: ['LogoutRequest', 'Signature'], attributes: [], context: true }
|
|
83
|
+
];
|
|
84
|
+
export const logoutResponseFields = [
|
|
85
|
+
{ key: 'response', localPath: ['LogoutResponse'], attributes: ['ID', 'Destination', 'InResponseTo'] },
|
|
86
|
+
{ key: 'issuer', localPath: ['LogoutResponse', 'Issuer'], attributes: [] },
|
|
87
|
+
{ key: 'signature', localPath: ['LogoutResponse', 'Signature'], attributes: [], context: true }
|
|
88
|
+
];
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// 增强版:IdP 元数据提取字段配置
|
|
91
|
+
// ============================================================================
|
|
92
|
+
export const idpMetadataFields = [
|
|
93
|
+
// --- 1. 基础标识 ---
|
|
94
|
+
{
|
|
95
|
+
key: 'entityID',
|
|
96
|
+
localPath: ['EntityDescriptor'],
|
|
97
|
+
attributes: ['entityID']
|
|
134
98
|
},
|
|
135
99
|
{
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
100
|
+
// 可选:提取整个 EntityDescriptor 的 validUntil 和 cacheDuration
|
|
101
|
+
key: 'entityDescriptor',
|
|
102
|
+
localPath: ['EntityDescriptor'],
|
|
103
|
+
attributes: ['validUntil', 'cacheDuration']
|
|
139
104
|
},
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
105
|
+
// --- 2. IDPSSODescriptor 核心属性 ---
|
|
106
|
+
{
|
|
107
|
+
key: 'idpSSODescriptor',
|
|
108
|
+
localPath: ['EntityDescriptor', 'IDPSSODescriptor'],
|
|
109
|
+
attributes: [
|
|
110
|
+
'protocolSupportEnumeration',
|
|
111
|
+
'WantAuthnRequestsSigned', // IdP 是否希望 SP 对请求签名
|
|
112
|
+
'cacheDuration'
|
|
113
|
+
]
|
|
145
114
|
},
|
|
146
|
-
//
|
|
147
|
-
// key: 'issuer',
|
|
148
|
-
// localPath: ['Response', 'Issuer'],
|
|
149
|
-
// attributes: []
|
|
150
|
-
// },
|
|
115
|
+
// --- 3. 服务端点列表 (Endpoints) ---
|
|
151
116
|
{
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
117
|
+
// 单点登录服务 (SSO) - 核心
|
|
118
|
+
key: 'singleSignOnService',
|
|
119
|
+
localPath: ['EntityDescriptor', 'IDPSSODescriptor', 'SingleSignOnService'],
|
|
120
|
+
attributes: ['Binding', 'Location', 'ResponseLocation'], // ResponseLocation 用于某些绑定
|
|
121
|
+
listMode: true
|
|
156
122
|
},
|
|
157
123
|
{
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
124
|
+
// 单点注销服务 (SLO)
|
|
125
|
+
key: 'singleLogoutService',
|
|
126
|
+
localPath: ['EntityDescriptor', 'IDPSSODescriptor', 'SingleLogoutService'],
|
|
127
|
+
attributes: ['Binding', 'Location'],
|
|
128
|
+
listMode: true
|
|
162
129
|
},
|
|
163
130
|
{
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
131
|
+
// Artifact 解析服务 (如果使用 Artifact 绑定)
|
|
132
|
+
key: 'artifactResolutionService',
|
|
133
|
+
localPath: ['EntityDescriptor', 'IDPSSODescriptor', 'ArtifactResolutionService'],
|
|
134
|
+
attributes: ['Binding', 'Location', 'index', 'isDefault'],
|
|
135
|
+
listMode: true
|
|
168
136
|
},
|
|
169
137
|
{
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
shortcut: assertion
|
|
138
|
+
// ManageNameID 服务
|
|
139
|
+
key: 'manageNameIDService',
|
|
140
|
+
localPath: ['EntityDescriptor', 'IDPSSODescriptor', 'ManageNameIDService'],
|
|
141
|
+
attributes: ['Binding', 'Location'],
|
|
142
|
+
listMode: true
|
|
176
143
|
},
|
|
144
|
+
// --- 4. 名称 ID 格式 (NameID Formats) ---
|
|
177
145
|
{
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
146
|
+
// 提取所有支持的 NameID 格式 (文本内容)
|
|
147
|
+
key: 'nameIDFormat',
|
|
148
|
+
localPath: ['EntityDescriptor', 'IDPSSODescriptor', 'NameIDFormat'],
|
|
149
|
+
attributes: []
|
|
150
|
+
// 注意:如果 extract 函数未完全支持 text() 的 listMode,这里可能只返回第一个。
|
|
151
|
+
// 如果需要数组,需确保 extract 逻辑完善,或者此处暂时只取主要的一个。
|
|
182
152
|
},
|
|
183
153
|
{
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
154
|
+
// 获取主要的 NameID Policy 格式 (如果有显式声明)
|
|
155
|
+
key: 'nameIDPolicyFormat',
|
|
156
|
+
localPath: ['EntityDescriptor', 'IDPSSODescriptor', 'NameIDPolicy'],
|
|
157
|
+
attributes: ['Format']
|
|
188
158
|
},
|
|
159
|
+
// --- 5. 组织信息 (Organization) ---
|
|
189
160
|
{
|
|
190
|
-
key: '
|
|
191
|
-
localPath: ['
|
|
192
|
-
attributes: [
|
|
161
|
+
key: 'organizationName',
|
|
162
|
+
localPath: ['EntityDescriptor', 'Organization', 'OrganizationName'],
|
|
163
|
+
attributes: [] // 取文本内容
|
|
193
164
|
},
|
|
194
|
-
];
|
|
195
|
-
export const logoutRequestFields = [
|
|
196
165
|
{
|
|
197
|
-
key: '
|
|
198
|
-
localPath: ['
|
|
199
|
-
attributes: [
|
|
166
|
+
key: 'organizationDisplayName',
|
|
167
|
+
localPath: ['EntityDescriptor', 'Organization', 'OrganizationDisplayName'],
|
|
168
|
+
attributes: []
|
|
200
169
|
},
|
|
201
170
|
{
|
|
202
|
-
key: '
|
|
203
|
-
localPath: ['
|
|
171
|
+
key: 'organizationURL',
|
|
172
|
+
localPath: ['EntityDescriptor', 'Organization', 'OrganizationURL'],
|
|
204
173
|
attributes: []
|
|
205
174
|
},
|
|
175
|
+
// --- 6. 联系人信息 (ContactPerson) ---
|
|
206
176
|
{
|
|
207
|
-
key: '
|
|
208
|
-
localPath: ['
|
|
209
|
-
attributes: []
|
|
177
|
+
key: 'contactPerson',
|
|
178
|
+
localPath: ['EntityDescriptor', 'ContactPerson'],
|
|
179
|
+
attributes: ['contactType'],
|
|
180
|
+
listMode: true
|
|
181
|
+
// 局限:目前只能提取 contactType。如需提取 Email/GivenName,需扩展 extract 逻辑。
|
|
210
182
|
},
|
|
183
|
+
// --- 7. 证书与密钥信息 (Certificates & Keys) ---
|
|
184
|
+
// 这些 key 会触发 extract 函数内部的硬编码逻辑,自动查找对应 @use 的证书
|
|
185
|
+
// 7.1 签名证书 (IdP 用来签名响应/断言)
|
|
211
186
|
{
|
|
212
|
-
key: '
|
|
213
|
-
localPath
|
|
214
|
-
attributes: []
|
|
187
|
+
key: 'signingCert'
|
|
188
|
+
// localPath 和 attributes 将被内部逻辑忽略
|
|
215
189
|
},
|
|
190
|
+
// 7.2 加密证书 (IdP 用来加密断言中的敏感信息,如果有)
|
|
216
191
|
{
|
|
217
|
-
key: '
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
context: true
|
|
221
|
-
}
|
|
222
|
-
];
|
|
223
|
-
export const logoutResponseFields = [
|
|
192
|
+
key: 'encryptCert'
|
|
193
|
+
},
|
|
194
|
+
// 7.3 签名密钥名称 (KeyName)
|
|
224
195
|
{
|
|
225
|
-
key: '
|
|
226
|
-
localPath: ['LogoutResponse'],
|
|
227
|
-
attributes: ['ID', 'Destination', 'InResponseTo']
|
|
196
|
+
key: 'signingKeyName'
|
|
228
197
|
},
|
|
198
|
+
// 7.4 加密密钥名称 (KeyName)
|
|
229
199
|
{
|
|
230
|
-
key: '
|
|
231
|
-
localPath: ['LogoutResponse', 'Issuer'],
|
|
232
|
-
attributes: []
|
|
200
|
+
key: 'encryptionKeyName'
|
|
233
201
|
},
|
|
202
|
+
// --- 8. 其他扩展属性 (可选) ---
|
|
234
203
|
{
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
204
|
+
// 提取 AttributeConsumingService (如果 IdP 声明了它需要的属性)
|
|
205
|
+
key: 'attributeConsumingService',
|
|
206
|
+
localPath: ['EntityDescriptor', 'IDPSSODescriptor', 'AttributeConsumingService'],
|
|
207
|
+
attributes: ['index', 'isDefault'],
|
|
208
|
+
listMode: true
|
|
239
209
|
}
|
|
240
210
|
];
|
|
211
|
+
// ============================================================================
|
|
212
|
+
// 修正后的 SP 元数据提取字段配置
|
|
213
|
+
// ============================================================================
|
|
214
|
+
export const spMetadataFields = [
|
|
215
|
+
{ key: 'entityID', localPath: ['EntityDescriptor'], attributes: ['entityID'] },
|
|
216
|
+
{ key: 'spSSODescriptor', localPath: ['EntityDescriptor', 'SPSSODescriptor'], attributes: ['protocolSupportEnumeration', 'AuthnRequestsSigned', 'WantAssertionsSigned'] },
|
|
217
|
+
{ key: 'assertionConsumerService', localPath: ['EntityDescriptor', 'SPSSODescriptor', 'AssertionConsumerService'], attributes: ['Binding', 'Location', 'index', 'isDefault'], listMode: true },
|
|
218
|
+
{ key: 'singleLogoutService', localPath: ['EntityDescriptor', 'SPSSODescriptor', 'SingleLogoutService'], attributes: ['Binding', 'Location'], listMode: true },
|
|
219
|
+
{ key: 'artifactResolutionService', localPath: ['EntityDescriptor', 'SPSSODescriptor', 'ArtifactResolutionService'], attributes: ['Binding', 'Location', 'index', 'isDefault'], listMode: true },
|
|
220
|
+
{ key: 'manageNameIDService', localPath: ['EntityDescriptor', 'SPSSODescriptor', 'ManageNameIDService'], attributes: ['Binding', 'Location'], listMode: true },
|
|
221
|
+
{ key: 'nameIDFormat', localPath: ['EntityDescriptor', 'SPSSODescriptor', 'NameIDFormat'], attributes: [] },
|
|
222
|
+
{ key: 'organizationName', localPath: ['EntityDescriptor', 'Organization', 'OrganizationName'], attributes: [] },
|
|
223
|
+
{ key: 'organizationDisplayName', localPath: ['EntityDescriptor', 'Organization', 'OrganizationDisplayName'], attributes: [] },
|
|
224
|
+
{ key: 'organizationURL', localPath: ['EntityDescriptor', 'Organization', 'OrganizationURL'], attributes: [] },
|
|
225
|
+
{ key: 'contactPerson', localPath: ['EntityDescriptor', 'ContactPerson'], attributes: ['contactType'], listMode: true },
|
|
226
|
+
// 特殊字段:触发 extract 内部的硬编码逻辑
|
|
227
|
+
// localPath 和 attributes 在这里不起作用,仅作为占位符
|
|
228
|
+
{ key: 'signingCert' },
|
|
229
|
+
{ key: 'encryptCert' },
|
|
230
|
+
{ key: 'signingKeyName' },
|
|
231
|
+
{ key: 'encryptionKeyName' }
|
|
232
|
+
];
|
|
241
233
|
export function extract(context, fields) {
|
|
242
234
|
const { dom } = getContext();
|
|
243
235
|
const rootDoc = dom.parseFromString(context, 'application/xml');
|
|
244
236
|
return fields.reduce((result, field) => {
|
|
245
|
-
// get essential fields
|
|
246
237
|
const key = field.key;
|
|
247
|
-
|
|
248
|
-
const
|
|
238
|
+
// 安全解构,防止 undefined
|
|
239
|
+
const localPath = field.localPath || [];
|
|
240
|
+
const attributes = field.attributes || [];
|
|
249
241
|
const isEntire = field.context;
|
|
250
242
|
const shortcut = field.shortcut;
|
|
251
|
-
// get optional fields
|
|
252
243
|
const index = field.index;
|
|
253
244
|
const attributePath = field.attributePath;
|
|
254
|
-
|
|
245
|
+
const listMode = field.listMode;
|
|
255
246
|
let targetDoc = rootDoc;
|
|
256
|
-
// if shortcut is used, then replace the doc
|
|
257
|
-
// it's a design for overriding the doc used during runtime
|
|
258
247
|
if (shortcut) {
|
|
259
248
|
targetDoc = dom.parseFromString(shortcut, 'application/xml');
|
|
260
249
|
}
|
|
261
|
-
//
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
.
|
|
250
|
+
// ==========================================================================
|
|
251
|
+
// 【核心修复】特殊处理:证书和 KeyName 提取 (Hardcoded logic)
|
|
252
|
+
// 不再硬编码 IDPSSODescriptor 或 SPSSODescriptor,而是全局搜索 @use 属性
|
|
253
|
+
// ==========================================================================
|
|
254
|
+
if (key === 'signingCert' || key === 'encryptCert' || key === 'signingKeyName' || key === 'encryptionKeyName') {
|
|
255
|
+
const isSigning = key.startsWith('signing');
|
|
256
|
+
const useType = isSigning ? 'signing' : 'encryption';
|
|
257
|
+
const isKeyName = key.endsWith('KeyName');
|
|
258
|
+
// 通用 XPath:查找任意层级下符合 @use 条件的 KeyDescriptor
|
|
259
|
+
const kdXPath = `//*[local-name(.)='KeyDescriptor' and @use='${useType}']`;
|
|
260
|
+
let fullXPath = '';
|
|
261
|
+
if (isKeyName) {
|
|
262
|
+
// 提取 KeyName 文本
|
|
263
|
+
fullXPath = `${kdXPath}/*[local-name(.)='KeyInfo']/*[local-name(.)='KeyName']/text()`;
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
// 提取 X509Certificate 文本
|
|
267
|
+
fullXPath = `${kdXPath}/*[local-name(.)='KeyInfo']/*[local-name(.)='X509Data']/*[local-name(.)='X509Certificate']/text()`;
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
// @ts-ignore
|
|
271
|
+
const nodes = select(fullXPath, targetDoc);
|
|
272
|
+
if (isKeyName) {
|
|
273
|
+
const keyNames = nodes.map((n) => n.nodeValue).filter(notEmpty);
|
|
274
|
+
return {
|
|
275
|
+
...result,
|
|
276
|
+
[key]: keyNames.length > 0 ? keyNames[0] : null
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
const certs = nodes.map((n) => {
|
|
281
|
+
const val = n.nodeValue || n.value;
|
|
282
|
+
return val ? val.replace(/\r\n|\r|\n/g, '') : null;
|
|
283
|
+
}).filter(notEmpty);
|
|
284
|
+
return {
|
|
285
|
+
...result,
|
|
286
|
+
[key]: certs.length > 0 ? certs[0] : null
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
catch (e) {
|
|
291
|
+
console.error(`Error extracting ${key}:`, e);
|
|
292
|
+
return { ...result, [key]: null };
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// 特殊 case: 多路径 (原有逻辑)
|
|
296
|
+
if (Array.isArray(localPath) && localPath.length > 0 && Array.isArray(localPath[0])) {
|
|
297
|
+
const multiXPaths = localPath.map(path => `${buildAbsoluteXPath(path)}/text()`).join(' | ');
|
|
298
|
+
// @ts-ignore
|
|
299
|
+
const nodes = select(multiXPaths, targetDoc);
|
|
300
|
+
return {
|
|
301
|
+
...result,
|
|
302
|
+
[key]: uniq(nodes.map((n) => n.nodeValue).filter(notEmpty))
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
// 此时 localPath 必然是 string[]
|
|
306
|
+
const currentLocalPath = localPath;
|
|
307
|
+
// 如果 localPath 为空数组(如特殊字段未定义 path),且未命中上面的特殊逻辑,则跳过
|
|
308
|
+
if (currentLocalPath.length === 0 && !isEntire) {
|
|
309
|
+
// 对于没有 path 且不是特殊处理的字段,返回 null 或跳过
|
|
310
|
+
return { ...result, [key]: null };
|
|
311
|
+
}
|
|
312
|
+
const baseXPath = buildAbsoluteXPath(currentLocalPath);
|
|
313
|
+
// --- 新增:列表模式处理 (用于 SSO Service, ACS 等) ---
|
|
314
|
+
if (listMode && attributes.length > 0) {
|
|
315
|
+
// @ts-ignore
|
|
316
|
+
const nodes = select(baseXPath, targetDoc);
|
|
317
|
+
const resultList = nodes.map((node) => {
|
|
318
|
+
const attrResult = {};
|
|
319
|
+
attributes.forEach(attr => {
|
|
320
|
+
if (node.getAttribute) {
|
|
321
|
+
const val = node.getAttribute(attr);
|
|
322
|
+
if (val) {
|
|
323
|
+
attrResult[camelCase(attr, { locale: 'en-us' })] = val;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
return attrResult;
|
|
328
|
+
});
|
|
279
329
|
return {
|
|
280
330
|
...result,
|
|
281
|
-
|
|
282
|
-
[key]: uniq(select(multiXPaths, targetDoc).map((n) => n.nodeValue).filter(notEmpty))
|
|
331
|
+
[key]: resultList
|
|
283
332
|
};
|
|
284
333
|
}
|
|
285
|
-
// eo special case: multiple path
|
|
286
|
-
const baseXPath = buildAbsoluteXPath(localPath);
|
|
287
334
|
const attributeXPath = buildAttributeXPath(attributes);
|
|
288
|
-
//
|
|
289
|
-
/*
|
|
290
|
-
{
|
|
291
|
-
key: 'attributes',
|
|
292
|
-
localPath: ['Response', 'Assertion', 'AttributeStatement', 'Attribute'],
|
|
293
|
-
index: ['Name'],
|
|
294
|
-
attributePath: ['AttributeValue'],
|
|
295
|
-
attributes: []
|
|
296
|
-
}
|
|
297
|
-
*/
|
|
335
|
+
// 特殊 case: 属性聚合 (原有逻辑 - Attributes with index)
|
|
298
336
|
if (index && attributePath) {
|
|
299
|
-
// find the index in localpath
|
|
300
337
|
const indexPath = buildAttributeXPath(index);
|
|
301
338
|
const fullLocalXPath = `${baseXPath}${indexPath}`;
|
|
302
|
-
// @ts-
|
|
339
|
+
// @ts-ignore
|
|
303
340
|
const parentNodes = select(baseXPath, targetDoc);
|
|
304
|
-
//
|
|
305
|
-
// @ts-expect-error misssing Node properties are not needed
|
|
341
|
+
// @ts-ignore
|
|
306
342
|
const parentAttributes = select(fullLocalXPath, targetDoc).map((n) => n.value);
|
|
307
|
-
|
|
308
|
-
const childXPath = buildAbsoluteXPath([last(localPath)].concat(attributePath));
|
|
343
|
+
const childXPath = buildAbsoluteXPath([last(currentLocalPath)].concat(attributePath));
|
|
309
344
|
const childAttributeXPath = buildAttributeXPath(attributes);
|
|
310
345
|
const fullChildXPath = `${childXPath}${childAttributeXPath}`;
|
|
311
|
-
|
|
312
|
-
const childAttributes = parentNodes.map(node => {
|
|
346
|
+
const childAttributes = parentNodes.map((node) => {
|
|
313
347
|
const nodeDoc = dom.parseFromString(node.toString(), 'application/xml');
|
|
314
348
|
if (attributes.length === 0) {
|
|
315
349
|
// @ts-ignore
|
|
316
350
|
const childValues = select(fullChildXPath, nodeDoc).map((n) => n.nodeValue);
|
|
317
|
-
|
|
318
|
-
return childValues[0];
|
|
319
|
-
}
|
|
320
|
-
return childValues;
|
|
351
|
+
return childValues.length === 1 ? childValues[0] : childValues;
|
|
321
352
|
}
|
|
322
353
|
if (attributes.length > 0) {
|
|
323
354
|
// @ts-ignore
|
|
324
355
|
const childValues = select(fullChildXPath, nodeDoc).map((n) => n.value);
|
|
325
|
-
|
|
326
|
-
return childValues[0];
|
|
327
|
-
}
|
|
328
|
-
return childValues;
|
|
356
|
+
return childValues.length === 1 ? childValues[0] : childValues;
|
|
329
357
|
}
|
|
330
358
|
return null;
|
|
331
359
|
});
|
|
332
|
-
// aggregation
|
|
333
360
|
const obj = zipObject(parentAttributes, childAttributes, false);
|
|
334
|
-
return {
|
|
335
|
-
...result,
|
|
336
|
-
[key]: obj
|
|
337
|
-
};
|
|
361
|
+
return { ...result, [key]: obj };
|
|
338
362
|
}
|
|
339
|
-
// case:
|
|
340
|
-
/*
|
|
341
|
-
{
|
|
342
|
-
key: 'signature',
|
|
343
|
-
localPath: ['AuthnRequest', 'Signature'],
|
|
344
|
-
attributes: [],
|
|
345
|
-
context: true
|
|
346
|
-
}
|
|
347
|
-
*/
|
|
363
|
+
// 特殊 case: 获取整个节点内容 (原有逻辑)
|
|
348
364
|
if (isEntire) {
|
|
349
|
-
// @ts-
|
|
365
|
+
// @ts-ignore
|
|
350
366
|
const node = select(baseXPath, targetDoc);
|
|
351
367
|
let value = null;
|
|
352
368
|
if (node.length === 1) {
|
|
353
369
|
value = node[0].toString();
|
|
354
370
|
}
|
|
355
371
|
if (node.length > 1) {
|
|
356
|
-
value = node.map(n => n.toString());
|
|
372
|
+
value = node.map((n) => n.toString());
|
|
357
373
|
}
|
|
358
|
-
return {
|
|
359
|
-
...result,
|
|
360
|
-
[key]: value
|
|
361
|
-
};
|
|
374
|
+
return { ...result, [key]: value };
|
|
362
375
|
}
|
|
363
|
-
// case:
|
|
364
|
-
|
|
365
|
-
{
|
|
366
|
-
key: 'nameIDPolicy',
|
|
367
|
-
localPath: ['AuthnRequest', 'NameIDPolicy'],
|
|
368
|
-
attributes: ['Format', 'AllowCreate']
|
|
369
|
-
}
|
|
370
|
-
*/
|
|
371
|
-
if (attributes.length > 1) {
|
|
376
|
+
// 特殊 case: 多属性对象 (原有逻辑,非 listMode)
|
|
377
|
+
if (attributes.length > 1 && !listMode) {
|
|
372
378
|
// @ts-ignore
|
|
373
|
-
const baseNode = select(baseXPath, targetDoc).map(n => n.toString());
|
|
374
|
-
const childXPath = `${buildAbsoluteXPath([last(
|
|
375
|
-
const attributeValues = baseNode.map((
|
|
379
|
+
const baseNode = select(baseXPath, targetDoc).map((n) => n.toString());
|
|
380
|
+
const childXPath = `${buildAbsoluteXPath([last(currentLocalPath)])}${attributeXPath}`;
|
|
381
|
+
const attributeValues = baseNode.map((nodeStr) => {
|
|
376
382
|
// @ts-ignore
|
|
377
|
-
const nodeDoc = dom.parseFromString(
|
|
383
|
+
const nodeDoc = dom.parseFromString(nodeStr, 'application/xml');
|
|
378
384
|
// @ts-ignore
|
|
379
385
|
const values = select(childXPath, nodeDoc).reduce((r, n) => {
|
|
380
386
|
r[camelCase(n.name, { locale: 'en-us' })] = n.value;
|
|
@@ -387,49 +393,35 @@ export function extract(context, fields) {
|
|
|
387
393
|
[key]: attributeValues.length === 1 ? attributeValues[0] : attributeValues
|
|
388
394
|
};
|
|
389
395
|
}
|
|
390
|
-
// case:
|
|
391
|
-
|
|
392
|
-
{
|
|
393
|
-
key: 'statusCode',
|
|
394
|
-
localPath: ['Response', 'Status', 'StatusCode'],
|
|
395
|
-
attributes: ['Value'],
|
|
396
|
-
}
|
|
397
|
-
*/
|
|
398
|
-
if (attributes.length === 1) {
|
|
396
|
+
// 特殊 case: 单个属性 (原有逻辑)
|
|
397
|
+
if (attributes.length === 1 && !listMode) {
|
|
399
398
|
const fullPath = `${baseXPath}${attributeXPath}`;
|
|
400
399
|
// @ts-ignore
|
|
401
400
|
const attributeValues = select(fullPath, targetDoc).map((n) => n.value);
|
|
402
|
-
return {
|
|
403
|
-
...result,
|
|
404
|
-
[key]: attributeValues[0]
|
|
405
|
-
};
|
|
401
|
+
return { ...result, [key]: attributeValues[0] };
|
|
406
402
|
}
|
|
407
|
-
// case:
|
|
408
|
-
|
|
409
|
-
{
|
|
410
|
-
key: 'issuer',
|
|
411
|
-
localPath: ['AuthnRequest', 'Issuer'],
|
|
412
|
-
attributes: []
|
|
413
|
-
}
|
|
414
|
-
*/
|
|
415
|
-
if (attributes.length === 0) {
|
|
403
|
+
// 特殊 case: 无属性/文本内容 (原有逻辑)
|
|
404
|
+
if (attributes.length === 0 && !listMode) {
|
|
416
405
|
let attributeValue = null;
|
|
417
|
-
// @ts-
|
|
406
|
+
// @ts-ignore
|
|
418
407
|
const node = select(baseXPath, targetDoc);
|
|
419
408
|
if (node.length === 1) {
|
|
420
409
|
const fullPath = `string(${baseXPath}${attributeXPath})`;
|
|
421
|
-
// @ts-
|
|
410
|
+
// @ts-ignore
|
|
422
411
|
attributeValue = select(fullPath, targetDoc);
|
|
423
412
|
}
|
|
424
413
|
if (node.length > 1) {
|
|
425
414
|
attributeValue = node.filter((n) => n.firstChild)
|
|
426
|
-
.map((n) => n.firstChild
|
|
415
|
+
.map((n) => n.firstChild?.nodeValue);
|
|
427
416
|
}
|
|
428
|
-
return {
|
|
429
|
-
...result,
|
|
430
|
-
[key]: attributeValue
|
|
431
|
-
};
|
|
417
|
+
return { ...result, [key]: attributeValue };
|
|
432
418
|
}
|
|
433
419
|
return result;
|
|
434
420
|
}, {});
|
|
435
421
|
}
|
|
422
|
+
export function extractIdp(context) {
|
|
423
|
+
return extract(context, idpMetadataFields);
|
|
424
|
+
}
|
|
425
|
+
export function extractSp(context) {
|
|
426
|
+
return extract(context, spMetadataFields);
|
|
427
|
+
}
|
package/build/src/libsaml.js
CHANGED
|
@@ -17,7 +17,7 @@ import xmlEscape from 'xml-escape';
|
|
|
17
17
|
import * as fs from 'fs';
|
|
18
18
|
import { DOMParser } from '@xmldom/xmldom';
|
|
19
19
|
const signatureAlgorithms = algorithms.signature;
|
|
20
|
-
const digestAlgorithms = algorithms.
|
|
20
|
+
const digestAlgorithms = algorithms.signatureToDigestMap;
|
|
21
21
|
const certUse = wording.certUse;
|
|
22
22
|
const urlParams = wording.urlParams;
|
|
23
23
|
const libSaml = () => {
|
|
@@ -328,7 +328,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
|
|
|
328
328
|
* @return {string} base64 encoded string
|
|
329
329
|
*/
|
|
330
330
|
constructSAMLSignature(opts) {
|
|
331
|
-
const { rawSamlMessage, referenceTagXPath, privateKey, privateKeyPass, signatureAlgorithm = signatureAlgorithms.
|
|
331
|
+
const { rawSamlMessage, referenceTagXPath, privateKey, privateKeyPass, signatureAlgorithm = signatureAlgorithms.RSA_SHA256, transformationAlgorithms = [
|
|
332
332
|
'http://www.w3.org/2000/09/xmldsig#enveloped-signature',
|
|
333
333
|
'http://www.w3.org/2001/10/xml-exc-c14n#',
|
|
334
334
|
], signingCert, signatureConfig, isBase64Output = true, isMessageSigned = false, } = opts;
|
|
@@ -926,7 +926,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
|
|
|
926
926
|
verifier.update(octetString);
|
|
927
927
|
const isValid = verifier.verify(utility.getPublicKeyPemFromCertificate(signCert), Buffer.isBuffer(signature) ? signature : Buffer.from(signature, 'base64'));
|
|
928
928
|
return isValid
|
|
929
|
-
|
|
929
|
+
|
|
930
930
|
},*/
|
|
931
931
|
/**
|
|
932
932
|
* @desc Verifies message signature
|
|
@@ -994,9 +994,11 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
|
|
|
994
994
|
pem: Buffer.from(`-----BEGIN CERTIFICATE-----${targetEntityMetadata.getX509Certificate(certUse.encrypt)}-----END CERTIFICATE-----`),
|
|
995
995
|
encryptionAlgorithm: sourceEntitySetting.dataEncryptionAlgorithm,
|
|
996
996
|
keyEncryptionAlgorithm: sourceEntitySetting.keyEncryptionAlgorithm,
|
|
997
|
-
keyEncryptionDigest: sourceEntitySetting.keyEncryptionDigest ?? '
|
|
997
|
+
keyEncryptionDigest: sourceEntitySetting.keyEncryptionDigest ?? 'sha1', //default sha256
|
|
998
998
|
keyEncryptionMgf1: sourceEntitySetting.keyEncryptionMgf1 ?? 'sha256',
|
|
999
|
-
disallowEncryptionWithInsecureAlgorithm:
|
|
999
|
+
disallowEncryptionWithInsecureAlgorithm: sourceEntitySetting.disallowEncryptionWithInsecureAlgorithm, // 禁止使用rsa-1_5 tripledes-cbc
|
|
1000
|
+
disallowInsecureEncryption: sourceEntitySetting.disallowInsecureEncryption, //禁aes cbc系列加密算法
|
|
1001
|
+
disallowInsecureHash: sourceEntitySetting.disallowInsecureHash, //禁止使用不安全的签名hash算法,不包括mgf1
|
|
1000
1002
|
warnInsecureAlgorithm: true
|
|
1001
1003
|
}, (err, res) => {
|
|
1002
1004
|
if (err) {
|
|
@@ -1017,49 +1019,6 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
|
|
|
1017
1019
|
}
|
|
1018
1020
|
});
|
|
1019
1021
|
},
|
|
1020
|
-
/**
|
|
1021
|
-
* @desc Decrypt the assertion section in Response
|
|
1022
|
-
* @param {string} type only accept SAMLResponse to proceed decryption
|
|
1023
|
-
* @param {Entity} here this entity
|
|
1024
|
-
* @param {Entity} from from the entity where the message is sent
|
|
1025
|
-
* @param {string} entireXML response in xml string format
|
|
1026
|
-
* @return {function} a promise to get back the entire xml with decrypted assertion
|
|
1027
|
-
*/
|
|
1028
|
-
decryptAssertion(here, entireXML) {
|
|
1029
|
-
return new Promise((resolve, reject) => {
|
|
1030
|
-
// Implement decryption first then check the signature
|
|
1031
|
-
if (!entireXML) {
|
|
1032
|
-
return reject(new Error('ERR_UNDEFINED_ASSERTION'));
|
|
1033
|
-
}
|
|
1034
|
-
// Perform encryption depends on the setting of where the message is sent, default is false
|
|
1035
|
-
const hereSetting = here.entitySetting;
|
|
1036
|
-
const { dom } = getContext();
|
|
1037
|
-
const doc = dom.parseFromString(entireXML, 'application/xml');
|
|
1038
|
-
// @ts-expect-error misssing Node properties are not needed
|
|
1039
|
-
const encryptedAssertions = select("/*[contains(local-name(), 'Response')]/*[local-name(.)='EncryptedAssertion']", doc);
|
|
1040
|
-
if (!Array.isArray(encryptedAssertions) || encryptedAssertions.length === 0) {
|
|
1041
|
-
throw new Error('ERR_UNDEFINED_ENCRYPTED_ASSERTION');
|
|
1042
|
-
}
|
|
1043
|
-
if (encryptedAssertions.length > 1) {
|
|
1044
|
-
throw new Error('ERR_MULTIPLE_ASSERTION');
|
|
1045
|
-
}
|
|
1046
|
-
const encAssertionNode = encryptedAssertions[0];
|
|
1047
|
-
return xmlenc.decrypt(encAssertionNode.toString(), {
|
|
1048
|
-
key: utility.readPrivateKey(hereSetting.encPrivateKey, hereSetting.encPrivateKeyPass),
|
|
1049
|
-
}, (err, res) => {
|
|
1050
|
-
if (err) {
|
|
1051
|
-
return reject(new Error('ERR_EXCEPTION_OF_ASSERTION_DECRYPTION'));
|
|
1052
|
-
}
|
|
1053
|
-
if (!res) {
|
|
1054
|
-
return reject(new Error('ERR_UNDEFINED_ENCRYPTED_ASSERTION'));
|
|
1055
|
-
}
|
|
1056
|
-
const rawAssertionDoc = dom.parseFromString(res, 'application/xml');
|
|
1057
|
-
// @ts-ignore
|
|
1058
|
-
doc.documentElement.replaceChild(rawAssertionDoc.documentElement, encAssertionNode);
|
|
1059
|
-
return resolve([doc.toString(), res]);
|
|
1060
|
-
});
|
|
1061
|
-
});
|
|
1062
|
-
},
|
|
1063
1022
|
/**
|
|
1064
1023
|
* 同步版本的断言解密函数
|
|
1065
1024
|
*/
|
|
@@ -1084,6 +1043,10 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
|
|
|
1084
1043
|
// 使用同步方式处理解密
|
|
1085
1044
|
xmlenc.decrypt(encAssertionNode.toString(), {
|
|
1086
1045
|
key: utility.readPrivateKey(hereSetting.encPrivateKey, hereSetting.encPrivateKeyPass),
|
|
1046
|
+
/* disallowInsecureEncryption:hereSetting.disallowInsecureEncryption,//开启会禁止解密使用aes cbc系列加密算法的xml
|
|
1047
|
+
disallowDecryptionWithInsecureAlgorithm: hereSetting.disallowDecryptionWithInsecureAlgorithm,//开启会禁止解密使用rsa-1_5 tripledes-cbc加密算法的xml
|
|
1048
|
+
disallowInsecureHash: hereSetting.disallowInsecureHash,//开启会禁止解密使用 hsa1系列 hash算法的xml*/
|
|
1049
|
+
warnInsecureAlgorithm: true,
|
|
1087
1050
|
}, (err, res) => {
|
|
1088
1051
|
if (err) {
|
|
1089
1052
|
throw new Error(err.message);
|
|
@@ -1178,6 +1141,7 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
|
|
|
1178
1141
|
* @returns [解密后的完整 SOAP XML, 解密后的断言 XML]
|
|
1179
1142
|
*/
|
|
1180
1143
|
async decryptAssertionSoap(self, entireXML) {
|
|
1144
|
+
let hereSetting = self.entitySetting;
|
|
1181
1145
|
const { dom } = getContext();
|
|
1182
1146
|
try {
|
|
1183
1147
|
// 1. 解析 XML
|
|
@@ -1200,7 +1164,12 @@ xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="{ID}"
|
|
|
1200
1164
|
const privateKey = utility.readPrivateKey(self.entitySetting.encPrivateKey, self.entitySetting.encPrivateKeyPass);
|
|
1201
1165
|
// 4. 解密断言
|
|
1202
1166
|
const decryptedAssertion = await new Promise((resolve, reject) => {
|
|
1203
|
-
xmlenc.decrypt(encAssertionNode.toString(), { key: privateKey
|
|
1167
|
+
xmlenc.decrypt(encAssertionNode.toString(), { key: privateKey,
|
|
1168
|
+
disallowInsecureEncryption: hereSetting.disallowInsecureEncryption, //开启会禁止解密使用aes cbc系列加密算法的xml
|
|
1169
|
+
disallowDecryptionWithInsecureAlgorithm: hereSetting.disallowDecryptionWithInsecureAlgorithm, //开启会禁止解密使用rsa-1_5 tripledes-cbc加密算法的xml
|
|
1170
|
+
disallowInsecureHash: hereSetting.disallowInsecureHash, //开启会禁止解密使用 hsa1系列 hash算法的xml
|
|
1171
|
+
warnInsecureAlgorithm: true,
|
|
1172
|
+
}, (err, result) => {
|
|
1204
1173
|
if (err) {
|
|
1205
1174
|
return reject(err);
|
|
1206
1175
|
}
|
package/build/src/urn.js
CHANGED
|
@@ -139,35 +139,98 @@ const messageConfigurations = {
|
|
|
139
139
|
},
|
|
140
140
|
};
|
|
141
141
|
const algorithms = {
|
|
142
|
+
// 1. 签名算法定义 (SignatureMethod)
|
|
142
143
|
signature: {
|
|
144
|
+
// ❌ 原文错误修正:ECDSA 不能用 rsa-sha256 的 URI
|
|
145
|
+
ECDSA_SHA256: 'http://www.w3.org/2007/05/xmldsig-more#ecdsa-sha256',
|
|
146
|
+
ECDSA_SHA384: 'http://www.w3.org/2007/05/xmldsig-more#ecdsa-sha384',
|
|
147
|
+
ECDSA_SHA512: 'http://www.w3.org/2007/05/xmldsig-more#ecdsa-sha512',
|
|
148
|
+
DSA_SHA1: 'http://www.w3.org/2000/09/xmldsig#dsa-sha1',
|
|
143
149
|
RSA_SHA1: 'http://www.w3.org/2000/09/xmldsig#rsa-sha1',
|
|
144
|
-
|
|
150
|
+
RSA_SHA224: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha224',
|
|
151
|
+
RSA_SHA256: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256', // 推荐
|
|
152
|
+
RSA_SHA384: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384',
|
|
145
153
|
RSA_SHA512: 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512',
|
|
154
|
+
// XML Signature 1.1 PSS 填充 (更安全)
|
|
155
|
+
RSA_PSS_SHA256: 'http://www.w3.org/2007/05/xmldsig-more#rsa-pss-sha256',
|
|
156
|
+
// EdDSA (Ed25519)
|
|
157
|
+
EDDSA_ED25519: 'http://www.w3.org/2007/05/xmldsig-more#eddsa-ed25519'
|
|
158
|
+
},
|
|
159
|
+
// 2. 摘要算法定义 (DigestMethod)
|
|
160
|
+
// 注意:这里直接使用标准推荐的 URI,SHA-2xx 系列推荐使用 xmlenc 命名空间
|
|
161
|
+
digest: {
|
|
162
|
+
SHA1: 'http://www.w3.org/2000/09/xmldsig#sha1',
|
|
163
|
+
SHA224: 'http://www.w3.org/2001/04/xmldsig-more#sha224', // 较少见,有时也用 xmlenc 但 xmldsig-more 更准确对应
|
|
164
|
+
SHA256: 'http://www.w3.org/2001/04/xmlenc#sha256', // ✅ 标准推荐
|
|
165
|
+
SHA384: 'http://www.w3.org/2001/04/xmlenc#sha384', // ✅ 标准推荐
|
|
166
|
+
SHA512: 'http://www.w3.org/2001/04/xmlenc#sha512' // ✅ 标准推荐
|
|
167
|
+
},
|
|
168
|
+
// 3. 映射关系表:给定一个签名算法 URI,它应该配合哪个摘要算法 URI?
|
|
169
|
+
// 这修复了你原代码中 digest 字段作为 "Map" 的意图
|
|
170
|
+
signatureToDigestMap: {
|
|
171
|
+
'http://www.w3.org/2000/09/xmldsig#rsa-sha1': 'http://www.w3.org/2000/09/xmldsig#sha1',
|
|
172
|
+
'http://www.w3.org/2000/09/xmldsig#dsa-sha1': 'http://www.w3.org/2000/09/xmldsig#sha1',
|
|
173
|
+
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha224': 'http://www.w3.org/2001/04/xmldsig-more#sha224',
|
|
174
|
+
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256': 'http://www.w3.org/2001/04/xmlenc#sha256',
|
|
175
|
+
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384': 'http://www.w3.org/2001/04/xmlenc#sha384',
|
|
176
|
+
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512': 'http://www.w3.org/2001/04/xmlenc#sha512',
|
|
177
|
+
'http://www.w3.org/2007/05/xmldsig-more#ecdsa-sha256': 'http://www.w3.org/2001/04/xmlenc#sha256',
|
|
178
|
+
'http://www.w3.org/2007/05/xmldsig-more#ecdsa-sha384': 'http://www.w3.org/2001/04/xmlenc#sha384',
|
|
179
|
+
'http://www.w3.org/2007/05/xmldsig-more#ecdsa-sha512': 'http://www.w3.org/2001/04/xmlenc#sha512',
|
|
180
|
+
'http://www.w3.org/2007/05/xmldsig-more#rsa-pss-sha256': 'http://www.w3.org/2001/04/xmlenc#sha256',
|
|
181
|
+
// EdDSA 比较特殊,它内部硬编码了 SHA-512,但在 XML 结构中如果需要显式声明 DigestMethod,通常指向 SHA-512
|
|
182
|
+
'http://www.w3.org/2007/05/xmldsig-more#eddsa-ed25519': 'http://www.w3.org/2001/04/xmlenc#sha512'
|
|
146
183
|
},
|
|
147
184
|
encryption: {
|
|
148
185
|
data: {
|
|
149
|
-
|
|
150
|
-
|
|
186
|
+
// --- CBC 模式 (XML Enc 1.0 - 兼容性最好) ---
|
|
187
|
+
AES_128_CBC: 'http://www.w3.org/2001/04/xmlenc#aes128-cbc',
|
|
188
|
+
AES_192_CBC: 'http://www.w3.org/2001/04/xmlenc#aes192-cbc',
|
|
189
|
+
AES_256_CBC: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc',
|
|
190
|
+
// --- GCM 模式 (XML Enc 1.1 - 推荐,提供完整性保护) ---
|
|
191
|
+
AES_128_GCM: 'http://www.w3.org/2009/xmlenc11#aes128-gcm',
|
|
192
|
+
AES_192_GCM: 'http://www.w3.org/2009/xmlenc11#aes192-gcm',
|
|
151
193
|
AES_256_GCM: 'http://www.w3.org/2009/xmlenc11#aes256-gcm',
|
|
152
|
-
|
|
153
|
-
|
|
194
|
+
// --- CTR 模式 (XML Enc 1.1) ---
|
|
195
|
+
AES_128_CTR: 'http://www.w3.org/2009/xmlenc11#aes128-ctr',
|
|
196
|
+
AES_192_CTR: 'http://www.w3.org/2009/xmlenc11#aes192-ctr',
|
|
197
|
+
AES_256_CTR: 'http://www.w3.org/2009/xmlenc11#aes256-ctr',
|
|
198
|
+
// --- 旧算法 (不推荐,仅用于遗留系统) ---
|
|
199
|
+
TRIPLE_DES: 'http://www.w3.org/2001/04/xmlenc#tripledes-cbc'
|
|
154
200
|
},
|
|
201
|
+
/**
|
|
202
|
+
* 密钥加密算法 (用于加密生成的 AES 会话密钥)
|
|
203
|
+
* 这里包含了 RSA-OAEP 和 AES Key Wrap
|
|
204
|
+
*/
|
|
155
205
|
key: {
|
|
206
|
+
// --- RSA OAEP (推荐) ---
|
|
207
|
+
// 默认使用 SHA-1 的 OAEP (XML Enc 1.0)
|
|
156
208
|
RSA_OAEP_MGF1P: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p',
|
|
209
|
+
// XML Enc 1.1 的通用 OAEP (通常配合 DigestMethod 参数使用 SHA-256)
|
|
210
|
+
RSA_OAEP: 'http://www.w3.org/2009/xmlenc11#rsa-oaep',
|
|
211
|
+
// --- RSA PKCS#1 v1.5 (旧标准,不推荐,但广泛存在) ---
|
|
157
212
|
RSA_1_5: 'http://www.w3.org/2001/04/xmlenc#rsa-1_5',
|
|
213
|
+
// --- AES Key Wrap (用于对称密钥加密对称密钥的场景) ---
|
|
214
|
+
AES_128_KW: 'http://www.w3.org/2001/04/xmlenc#kw-aes128',
|
|
215
|
+
AES_192_KW: 'http://www.w3.org/2001/04/xmlenc#kw-aes192',
|
|
216
|
+
AES_256_KW: 'http://www.w3.org/2001/04/xmlenc#kw-aes256',
|
|
217
|
+
// --- AES GCM Key Wrap (XML Enc 1.1) ---
|
|
218
|
+
AES_128_GCM_KW: 'http://www.w3.org/2009/xmlenc11#aes128-gcmkw',
|
|
219
|
+
AES_192_GCM_KW: 'http://www.w3.org/2009/xmlenc11#aes192-gcmkw',
|
|
220
|
+
AES_256_GCM_KW: 'http://www.w3.org/2009/xmlenc11#aes256-gcmkw',
|
|
158
221
|
},
|
|
159
222
|
},
|
|
160
|
-
digest: {
|
|
161
|
-
'http://www.w3.org/2000/09/xmldsig#rsa-sha1': 'http://www.w3.org/2000/09/xmldsig#sha1',
|
|
162
|
-
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256': 'http://www.w3.org/2001/04/xmlenc#sha256',
|
|
163
|
-
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384': 'http://www.w3.org/2001/04/xmlenc#sha384',
|
|
164
|
-
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512': 'http://www.w3.org/2001/04/xmlenc#sha512', // support hashing algorithm sha512 in xml-crypto after 0.8.0
|
|
165
|
-
'http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1': 'http://www.w3.org/2001/04/xmlenc#sha256',
|
|
166
|
-
'http://www.w3.org/2007/05/xmldsig-more#sha384-rsa-MGF1': 'http://www.w3.org/2001/04/xmlenc#sha384',
|
|
167
|
-
'http://www.w3.org/2007/05/xmldsig-more#sha512-rsa-MGF1': 'http://www.w3.org/2001/04/xmlenc#sha512', // support hashing algorithm sha512 in xml-crypto after 0.8.0
|
|
168
|
-
'http://www.w3.org/2007/05/xmldsig-more#eddsa-ed25519': 'http://www.w3.org/2001/04/xmlenc#sha512'
|
|
169
|
-
},
|
|
170
223
|
};
|
|
224
|
+
// 使用示例:
|
|
225
|
+
// 如果你选择了 RSA_SHA256 签名
|
|
226
|
+
const selectedSigAlg = algorithms.signature.RSA_SHA256;
|
|
227
|
+
// 自动获取对应的摘要算法
|
|
228
|
+
const requiredDigestAlg = algorithms.signatureToDigestMap[selectedSigAlg];
|
|
229
|
+
console.log(`Signature: ${selectedSigAlg}`);
|
|
230
|
+
console.log(`Required Digest: ${requiredDigestAlg}`);
|
|
231
|
+
// 输出:
|
|
232
|
+
// Signature: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
|
|
233
|
+
// Required Digest: http://www.w3.org/2001/04/xmlenc#sha256
|
|
171
234
|
export var ParserType;
|
|
172
235
|
(function (ParserType) {
|
|
173
236
|
ParserType["SAMLRequest"] = "SAMLRequest";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "samlesa",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "High-level API for Single Sign On (SAML 2.0) baseed on samlify ",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"keywords": [
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"xml": "^1.0.1",
|
|
56
56
|
"xml-crypto-next": "^7.0.0",
|
|
57
57
|
"xml-crypto": "^6.1.2",
|
|
58
|
-
"xml-encryption-next": "^4.
|
|
58
|
+
"xml-encryption-next": "^4.6.0",
|
|
59
59
|
"xml-escape": "^1.1.0",
|
|
60
60
|
"xml2js": "^0.6.2",
|
|
61
61
|
"xmllint-wasm": "^5.1.0",
|
package/types/src/extractor.d.ts
CHANGED
|
@@ -1,53 +1,27 @@
|
|
|
1
1
|
interface ExtractorField {
|
|
2
2
|
key: string;
|
|
3
|
-
localPath
|
|
4
|
-
attributes
|
|
3
|
+
localPath?: string[] | string[][];
|
|
4
|
+
attributes?: string[];
|
|
5
5
|
index?: string[];
|
|
6
6
|
attributePath?: string[];
|
|
7
7
|
context?: boolean;
|
|
8
|
+
listMode?: boolean;
|
|
9
|
+
shortcut?: string;
|
|
8
10
|
}
|
|
9
11
|
export type ExtractorFields = ExtractorField[];
|
|
10
12
|
export declare const loginRequestFields: ExtractorFields;
|
|
11
|
-
export declare const artifactResolveFields:
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
} | {
|
|
17
|
-
key: string;
|
|
18
|
-
localPath: string[];
|
|
19
|
-
attributes: never[];
|
|
20
|
-
context: boolean;
|
|
21
|
-
})[];
|
|
22
|
-
export declare const artifactResponseFields: ({
|
|
23
|
-
key: string;
|
|
24
|
-
localPath: string[];
|
|
25
|
-
attributes: string[];
|
|
26
|
-
context?: undefined;
|
|
27
|
-
} | {
|
|
28
|
-
key: string;
|
|
29
|
-
localPath: string[];
|
|
30
|
-
attributes: never[];
|
|
31
|
-
context: boolean;
|
|
32
|
-
})[];
|
|
33
|
-
export declare const loginResponseStatusFields: {
|
|
34
|
-
key: string;
|
|
35
|
-
localPath: string[];
|
|
36
|
-
attributes: string[];
|
|
37
|
-
}[];
|
|
38
|
-
export declare const loginArtifactResponseStatusFields: {
|
|
39
|
-
key: string;
|
|
40
|
-
localPath: string[];
|
|
41
|
-
attributes: string[];
|
|
42
|
-
}[];
|
|
43
|
-
export declare const logoutResponseStatusFields: {
|
|
44
|
-
key: string;
|
|
45
|
-
localPath: string[];
|
|
46
|
-
attributes: string[];
|
|
47
|
-
}[];
|
|
13
|
+
export declare const artifactResolveFields: ExtractorFields;
|
|
14
|
+
export declare const artifactResponseFields: ExtractorFields;
|
|
15
|
+
export declare const loginResponseStatusFields: ExtractorFields;
|
|
16
|
+
export declare const loginArtifactResponseStatusFields: ExtractorFields;
|
|
17
|
+
export declare const logoutResponseStatusFields: ExtractorFields;
|
|
48
18
|
export declare const loginResponseFields: ((assertion: any) => ExtractorFields);
|
|
49
19
|
export declare const logoutRequestFields: ExtractorFields;
|
|
50
20
|
export declare const logoutResponseFields: ExtractorFields;
|
|
51
|
-
export declare
|
|
21
|
+
export declare const idpMetadataFields: ExtractorFields;
|
|
22
|
+
export declare const spMetadataFields: ExtractorFields;
|
|
23
|
+
export declare function extract(context: string, fields: ExtractorFields): any;
|
|
24
|
+
export declare function extractIdp(context: string): any;
|
|
25
|
+
export declare function extractSp(context: string): any;
|
|
52
26
|
export {};
|
|
53
27
|
//# sourceMappingURL=extractor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/extractor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"extractor.d.ts","sourceRoot":"","sources":["../../src/extractor.ts"],"names":[],"mappings":"AAMA,UAAU,cAAc;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,EAAE,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,eAAe,GAAG,cAAc,EAAE,CAAC;AAgC/C,eAAO,MAAM,kBAAkB,EAAE,eAMhC,CAAC;AAEF,eAAO,MAAM,qBAAqB,EAAE,eAKnC,CAAC;AAEF,eAAO,MAAM,sBAAsB,EAAE,eAKpC,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,eAGvC,CAAC;AAEF,eAAO,MAAM,iCAAiC,EAAE,eAG/C,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,eAGxC,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,CAAC,CAAC,SAAS,EAAE,GAAG,KAAK,eAAe,CAWrE,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,eAMjC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,eAIlC,CAAC;AAKF,eAAO,MAAM,iBAAiB,EAAE,eAiI/B,CAAC;AAQF,eAAO,MAAM,gBAAgB,EAAE,eAmB9B,CAAC;AAEF,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,OAiN/D;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,OAEzC;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,OAExC"}
|
package/types/src/libsaml.d.ts
CHANGED
|
@@ -257,15 +257,6 @@ declare const _default: {
|
|
|
257
257
|
* @return {Promise} a promise to resolve the finalized xml
|
|
258
258
|
*/
|
|
259
259
|
encryptAssertion(sourceEntity: any, targetEntity: any, xml?: string): Promise<string>;
|
|
260
|
-
/**
|
|
261
|
-
* @desc Decrypt the assertion section in Response
|
|
262
|
-
* @param {string} type only accept SAMLResponse to proceed decryption
|
|
263
|
-
* @param {Entity} here this entity
|
|
264
|
-
* @param {Entity} from from the entity where the message is sent
|
|
265
|
-
* @param {string} entireXML response in xml string format
|
|
266
|
-
* @return {function} a promise to get back the entire xml with decrypted assertion
|
|
267
|
-
*/
|
|
268
|
-
decryptAssertion(here: any, entireXML: string): Promise<[string, any]>;
|
|
269
260
|
/**
|
|
270
261
|
* 同步版本的断言解密函数
|
|
271
262
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"libsaml.d.ts","sourceRoot":"","sources":["../../src/libsaml.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AAerD;;;;GAIG;AAGH,MAAM,WAAW,oBAAoB;
|
|
1
|
+
{"version":3,"file":"libsaml.d.ts","sourceRoot":"","sources":["../../src/libsaml.ts"],"names":[],"mappings":"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"}
|
package/types/src/urn.d.ts
CHANGED
|
@@ -133,33 +133,67 @@ declare const messageConfigurations: {
|
|
|
133
133
|
};
|
|
134
134
|
declare const algorithms: {
|
|
135
135
|
signature: {
|
|
136
|
+
ECDSA_SHA256: string;
|
|
137
|
+
ECDSA_SHA384: string;
|
|
138
|
+
ECDSA_SHA512: string;
|
|
139
|
+
DSA_SHA1: string;
|
|
136
140
|
RSA_SHA1: string;
|
|
141
|
+
RSA_SHA224: string;
|
|
137
142
|
RSA_SHA256: string;
|
|
143
|
+
RSA_SHA384: string;
|
|
138
144
|
RSA_SHA512: string;
|
|
145
|
+
RSA_PSS_SHA256: string;
|
|
146
|
+
EDDSA_ED25519: string;
|
|
147
|
+
};
|
|
148
|
+
digest: {
|
|
149
|
+
SHA1: string;
|
|
150
|
+
SHA224: string;
|
|
151
|
+
SHA256: string;
|
|
152
|
+
SHA384: string;
|
|
153
|
+
SHA512: string;
|
|
154
|
+
};
|
|
155
|
+
signatureToDigestMap: {
|
|
156
|
+
'http://www.w3.org/2000/09/xmldsig#rsa-sha1': string;
|
|
157
|
+
'http://www.w3.org/2000/09/xmldsig#dsa-sha1': string;
|
|
158
|
+
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha224': string;
|
|
159
|
+
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256': string;
|
|
160
|
+
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384': string;
|
|
161
|
+
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512': string;
|
|
162
|
+
'http://www.w3.org/2007/05/xmldsig-more#ecdsa-sha256': string;
|
|
163
|
+
'http://www.w3.org/2007/05/xmldsig-more#ecdsa-sha384': string;
|
|
164
|
+
'http://www.w3.org/2007/05/xmldsig-more#ecdsa-sha512': string;
|
|
165
|
+
'http://www.w3.org/2007/05/xmldsig-more#rsa-pss-sha256': string;
|
|
166
|
+
'http://www.w3.org/2007/05/xmldsig-more#eddsa-ed25519': string;
|
|
139
167
|
};
|
|
140
168
|
encryption: {
|
|
141
169
|
data: {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
TRI_DEC: string;
|
|
170
|
+
AES_128_CBC: string;
|
|
171
|
+
AES_192_CBC: string;
|
|
172
|
+
AES_256_CBC: string;
|
|
146
173
|
AES_128_GCM: string;
|
|
174
|
+
AES_192_GCM: string;
|
|
175
|
+
AES_256_GCM: string;
|
|
176
|
+
AES_128_CTR: string;
|
|
177
|
+
AES_192_CTR: string;
|
|
178
|
+
AES_256_CTR: string;
|
|
179
|
+
TRIPLE_DES: string;
|
|
147
180
|
};
|
|
181
|
+
/**
|
|
182
|
+
* 密钥加密算法 (用于加密生成的 AES 会话密钥)
|
|
183
|
+
* 这里包含了 RSA-OAEP 和 AES Key Wrap
|
|
184
|
+
*/
|
|
148
185
|
key: {
|
|
149
186
|
RSA_OAEP_MGF1P: string;
|
|
187
|
+
RSA_OAEP: string;
|
|
150
188
|
RSA_1_5: string;
|
|
189
|
+
AES_128_KW: string;
|
|
190
|
+
AES_192_KW: string;
|
|
191
|
+
AES_256_KW: string;
|
|
192
|
+
AES_128_GCM_KW: string;
|
|
193
|
+
AES_192_GCM_KW: string;
|
|
194
|
+
AES_256_GCM_KW: string;
|
|
151
195
|
};
|
|
152
196
|
};
|
|
153
|
-
digest: {
|
|
154
|
-
'http://www.w3.org/2000/09/xmldsig#rsa-sha1': string;
|
|
155
|
-
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256': string;
|
|
156
|
-
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha384': string;
|
|
157
|
-
'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512': string;
|
|
158
|
-
'http://www.w3.org/2007/05/xmldsig-more#sha256-rsa-MGF1': string;
|
|
159
|
-
'http://www.w3.org/2007/05/xmldsig-more#sha384-rsa-MGF1': string;
|
|
160
|
-
'http://www.w3.org/2007/05/xmldsig-more#sha512-rsa-MGF1': string;
|
|
161
|
-
'http://www.w3.org/2007/05/xmldsig-more#eddsa-ed25519': string;
|
|
162
|
-
};
|
|
163
197
|
};
|
|
164
198
|
export declare enum ParserType {
|
|
165
199
|
SAMLRequest = "SAMLRequest",
|
package/types/src/urn.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urn.d.ts","sourceRoot":"","sources":["../../src/urn.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,oBAAY,gBAAgB;
|
|
1
|
+
{"version":3,"file":"urn.d.ts","sourceRoot":"","sources":["../../src/urn.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,oBAAY,gBAAgB;IAC1B,QAAQ,uDAAuD;IAC/D,IAAI,mDAAmD;IACvD,UAAU,8DAA8D;IACxE,QAAQ,uDAAuD;CAChE;AAED,oBAAY,qBAAqB;IAC/B,GAAG,sBAAsB;IACzB,GAAG,sBAAsB;CAC1B;AAED,oBAAY,UAAU;IAEpB,OAAO,+CAA+C;IACtD,SAAS,iDAAiD;IAC1D,SAAS,iDAAiD;IAC1D,eAAe,uDAAuD;IAEtE,UAAU,mDAAmD;IAC7D,sBAAsB,8DAA8D;IACpF,mBAAmB,2DAA2D;IAC9E,cAAc,sDAAsD;IACpE,cAAc,sDAAsD;IACpE,SAAS,iDAAiD;IAC1D,cAAc,sDAAsD;IACpE,aAAa,qDAAqD;IAClE,kBAAkB,0DAA0D;IAC5E,aAAa,qDAAqD;IAClE,kBAAkB,0DAA0D;IAC5E,wBAAwB,gEAAgE;IACxF,qBAAqB,6DAA6D;IAClF,oBAAoB,4DAA4D;IAChF,qBAAqB,6DAA6D;IAClF,gBAAgB,wDAAwD;IACxE,kBAAkB,0DAA0D;IAC5E,gBAAgB,wDAAwD;IACxE,kBAAkB,0DAA0D;CAC7E;AAED,QAAA,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwDd,CAAC;AAEF,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BT,CAAC;AAEF,QAAA,MAAM,qBAAqB;;;;;CAK1B,CAAC;AAEF,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA2EZ;;;WAGG;;;;;;;;;;;;;CAwBN,CAAC;AAcF,oBAAY,UAAU;IACpB,WAAW,gBAAgB;IAC3B,YAAY,iBAAiB;IAC7B,aAAa,kBAAkB;IAC/B,cAAc,mBAAmB;CAClC;AAED,QAAA,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;CAyBZ,CAAC;AAIF,QAAA,MAAM,aAAa;;;;CAIlB,CAAC;AAEF,OAAO,EAAC,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAC,CAAC"}
|