samlesa 2.12.3

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 (99) hide show
  1. package/.editorconfig +19 -0
  2. package/.github/FUNDING.yml +1 -0
  3. package/.idea/compiler.xml +6 -0
  4. package/.idea/deployment.xml +14 -0
  5. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  6. package/.idea/jsLibraryMappings.xml +6 -0
  7. package/.idea/modules.xml +8 -0
  8. package/.idea/samlify.iml +12 -0
  9. package/.idea/vcs.xml +6 -0
  10. package/.pre-commit.sh +15 -0
  11. package/.snyk +8 -0
  12. package/.travis.yml +29 -0
  13. package/LICENSE +22 -0
  14. package/Makefile +25 -0
  15. package/README.md +84 -0
  16. package/build/.idea/workspace.xml +58 -0
  17. package/build/index.js +65 -0
  18. package/build/index.js.map +1 -0
  19. package/build/src/api.js +24 -0
  20. package/build/src/api.js.map +1 -0
  21. package/build/src/binding-post.js +369 -0
  22. package/build/src/binding-post.js.map +1 -0
  23. package/build/src/binding-redirect.js +333 -0
  24. package/build/src/binding-redirect.js.map +1 -0
  25. package/build/src/binding-simplesign.js +233 -0
  26. package/build/src/binding-simplesign.js.map +1 -0
  27. package/build/src/entity-idp.js +131 -0
  28. package/build/src/entity-idp.js.map +1 -0
  29. package/build/src/entity-sp.js +97 -0
  30. package/build/src/entity-sp.js.map +1 -0
  31. package/build/src/entity.js +236 -0
  32. package/build/src/entity.js.map +1 -0
  33. package/build/src/extractor.js +370 -0
  34. package/build/src/extractor.js.map +1 -0
  35. package/build/src/flow.js +320 -0
  36. package/build/src/flow.js.map +1 -0
  37. package/build/src/libsaml.js +642 -0
  38. package/build/src/libsaml.js.map +1 -0
  39. package/build/src/metadata-idp.js +128 -0
  40. package/build/src/metadata-idp.js.map +1 -0
  41. package/build/src/metadata-sp.js +232 -0
  42. package/build/src/metadata-sp.js.map +1 -0
  43. package/build/src/metadata.js +177 -0
  44. package/build/src/metadata.js.map +1 -0
  45. package/build/src/types.js +12 -0
  46. package/build/src/types.js.map +1 -0
  47. package/build/src/urn.js +213 -0
  48. package/build/src/urn.js.map +1 -0
  49. package/build/src/utility.js +249 -0
  50. package/build/src/utility.js.map +1 -0
  51. package/build/src/validator.js +27 -0
  52. package/build/src/validator.js.map +1 -0
  53. package/index.d.ts +10 -0
  54. package/index.js +19 -0
  55. package/index.js.map +1 -0
  56. package/index.ts +28 -0
  57. package/package.json +74 -0
  58. package/qodana.yaml +29 -0
  59. package/src/.idea/modules.xml +8 -0
  60. package/src/.idea/src.iml +12 -0
  61. package/src/.idea/vcs.xml +6 -0
  62. package/src/api.ts +36 -0
  63. package/src/binding-post.ts +338 -0
  64. package/src/binding-redirect.ts +331 -0
  65. package/src/binding-simplesign.ts +231 -0
  66. package/src/entity-idp.ts +145 -0
  67. package/src/entity-sp.ts +114 -0
  68. package/src/entity.ts +243 -0
  69. package/src/extractor.ts +392 -0
  70. package/src/flow.ts +467 -0
  71. package/src/libsaml.ts +786 -0
  72. package/src/metadata-idp.ts +146 -0
  73. package/src/metadata-sp.ts +268 -0
  74. package/src/metadata.ts +166 -0
  75. package/src/types.ts +153 -0
  76. package/src/urn.ts +211 -0
  77. package/src/utility.ts +248 -0
  78. package/src/validator.ts +44 -0
  79. package/tsconfig.json +38 -0
  80. package/tslint.json +35 -0
  81. package/types/index.d.ts +10 -0
  82. package/types/src/api.d.ts +13 -0
  83. package/types/src/binding-post.d.ts +46 -0
  84. package/types/src/binding-redirect.d.ts +52 -0
  85. package/types/src/binding-simplesign.d.ts +39 -0
  86. package/types/src/entity-idp.d.ts +42 -0
  87. package/types/src/entity-sp.d.ts +36 -0
  88. package/types/src/entity.d.ts +99 -0
  89. package/types/src/extractor.d.ts +25 -0
  90. package/types/src/flow.d.ts +6 -0
  91. package/types/src/libsaml.d.ts +210 -0
  92. package/types/src/metadata-idp.d.ts +24 -0
  93. package/types/src/metadata-sp.d.ts +36 -0
  94. package/types/src/metadata.d.ts +57 -0
  95. package/types/src/types.d.ts +127 -0
  96. package/types/src/urn.d.ts +194 -0
  97. package/types/src/utility.d.ts +134 -0
  98. package/types/src/validator.d.ts +3 -0
  99. package/types.d.ts +2 -0
@@ -0,0 +1,146 @@
1
+ /**
2
+ * @file metadata-idp.ts
3
+ * @author tngan
4
+ * @desc Metadata of identity provider
5
+ */
6
+ import Metadata, { MetadataInterface } from './metadata.js';
7
+ import { MetadataIdpOptions, MetadataIdpConstructor } from './types.js';
8
+ import { namespace } from './urn.js';
9
+ import libsaml from './libsaml.js';
10
+ import { castArrayOpt, isNonEmptyArray, isString } from './utility.js';
11
+ import xml from 'xml';
12
+
13
+ export interface IdpMetadataInterface extends MetadataInterface {
14
+
15
+ }
16
+
17
+ /*
18
+ * @desc interface function
19
+ */
20
+ export default function(meta: MetadataIdpConstructor) {
21
+ return new IdpMetadata(meta);
22
+ }
23
+
24
+ export class IdpMetadata extends Metadata {
25
+
26
+ constructor(meta: MetadataIdpConstructor) {
27
+
28
+ const isFile = isString(meta) || meta instanceof Buffer;
29
+
30
+ if (!isFile) {
31
+
32
+ const {
33
+ entityID,
34
+ signingCert,
35
+ encryptCert,
36
+ wantAuthnRequestsSigned = false,
37
+ nameIDFormat = [],
38
+ singleSignOnService = [],
39
+ singleLogoutService = [],
40
+ } = meta as MetadataIdpOptions;
41
+
42
+ const IDPSSODescriptor: any[] = [{
43
+ _attr: {
44
+ WantAuthnRequestsSigned: String(wantAuthnRequestsSigned),
45
+ protocolSupportEnumeration: namespace.names.protocol,
46
+ },
47
+ }];
48
+
49
+ for(const cert of castArrayOpt(signingCert)) {
50
+ IDPSSODescriptor.push(libsaml.createKeySection('signing', cert));
51
+ }
52
+
53
+ for(const cert of castArrayOpt(encryptCert)) {
54
+ IDPSSODescriptor.push(libsaml.createKeySection('encryption', cert));
55
+ }
56
+
57
+ if (isNonEmptyArray(nameIDFormat)) {
58
+ nameIDFormat.forEach(f => IDPSSODescriptor.push({ NameIDFormat: f }));
59
+ }
60
+
61
+ if (isNonEmptyArray(singleSignOnService)) {
62
+ singleSignOnService.forEach((a, indexCount) => {
63
+ const attr: any = {
64
+ Binding: a.Binding,
65
+ Location: a.Location,
66
+ };
67
+ if (a.isDefault) {
68
+ attr.isDefault = true;
69
+ }
70
+ IDPSSODescriptor.push({ SingleSignOnService: [{ _attr: attr }] });
71
+ });
72
+ } else {
73
+ throw new Error('ERR_IDP_METADATA_MISSING_SINGLE_SIGN_ON_SERVICE');
74
+ }
75
+
76
+ if (isNonEmptyArray(singleLogoutService)) {
77
+ singleLogoutService.forEach((a, indexCount) => {
78
+ const attr: any = {};
79
+ if (a.isDefault) {
80
+ attr.isDefault = true;
81
+ }
82
+ attr.Binding = a.Binding;
83
+ attr.Location = a.Location;
84
+ IDPSSODescriptor.push({ SingleLogoutService: [{ _attr: attr }] });
85
+ });
86
+ } else {
87
+ console.warn('Construct identity provider - missing endpoint of SingleLogoutService');
88
+ }
89
+ // Create a new metadata by setting
90
+ meta = xml([{
91
+ EntityDescriptor: [{
92
+ _attr: {
93
+ 'xmlns': namespace.names.metadata,
94
+ 'xmlns:assertion': namespace.names.assertion,
95
+ 'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
96
+ entityID,
97
+ },
98
+ }, { IDPSSODescriptor }],
99
+ }]);
100
+ }
101
+
102
+ super(meta as string | Buffer, [
103
+ {
104
+ key: 'wantAuthnRequestsSigned',
105
+ localPath: ['EntityDescriptor', 'IDPSSODescriptor'],
106
+ attributes: ['WantAuthnRequestsSigned'],
107
+ },
108
+ {
109
+ key: 'singleSignOnService',
110
+ localPath: ['EntityDescriptor', 'IDPSSODescriptor', 'SingleSignOnService'],
111
+ index: ['Binding'],
112
+ attributePath: [],
113
+ attributes: ['Location']
114
+ },
115
+ ]);
116
+
117
+ }
118
+
119
+ /**
120
+ * @desc Get the preference whether it wants a signed request
121
+ * @return {boolean} WantAuthnRequestsSigned
122
+ */
123
+ isWantAuthnRequestsSigned(): boolean {
124
+ const was = this.meta.wantAuthnRequestsSigned;
125
+ if (was === undefined) {
126
+ return false;
127
+ }
128
+ return String(was) === 'true';
129
+ }
130
+
131
+ /**
132
+ * @desc Get the entity endpoint for single sign on service
133
+ * @param {string} binding protocol binding (e.g. redirect, post)
134
+ * @return {string/object} location
135
+ */
136
+ getSingleSignOnService(binding: string): string | object {
137
+ if (isString(binding)) {
138
+ const bindName = namespace.binding[binding];
139
+ const service = this.meta.singleSignOnService[bindName];
140
+ if (service) {
141
+ return service;
142
+ }
143
+ }
144
+ return this.meta.singleSignOnService;
145
+ }
146
+ }
@@ -0,0 +1,268 @@
1
+ /**
2
+ * @file metadata-sp.ts
3
+ * @author tngan
4
+ * @desc Metadata of service provider
5
+ */
6
+ import Metadata, { MetadataInterface } from './metadata.js';
7
+ import { MetadataSpConstructor, MetadataSpOptions } from './types.js';
8
+ import { namespace, elementsOrder as order } from './urn.js';
9
+ import libsaml from './libsaml.js';
10
+ import { castArrayOpt, isNonEmptyArray, isString } from './utility.js';
11
+ import xml from 'xml';
12
+ import {AttrService,ServiceName,RequestedAttribute,AttributeConsumingService} from './types.js'
13
+ export interface SpMetadataInterface extends MetadataInterface {
14
+
15
+ }
16
+
17
+ // https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf (P.16, 18)
18
+ interface MetaElement {
19
+ KeyDescriptor?: any[];
20
+ NameIDFormat?: any[];
21
+ SingleLogoutService?: any[];
22
+ AssertionConsumerService?: any[];
23
+ AttributeConsumingService?: any[];
24
+ }
25
+
26
+ /*
27
+ * @desc interface function
28
+ */
29
+ export default function(meta: MetadataSpConstructor) {
30
+ return new SpMetadata(meta);
31
+ }
32
+
33
+ /**
34
+ * @desc SP Metadata is for creating Service Provider, provides a set of API to manage the actions in SP.
35
+ */
36
+ export class SpMetadata extends Metadata {
37
+
38
+ /**
39
+ * @param {object/string} meta (either xml string or configuration in object)
40
+ * @return {object} prototypes including public functions
41
+ */
42
+ constructor(meta: MetadataSpConstructor) {
43
+
44
+ const isFile = isString(meta) || meta instanceof Buffer;
45
+
46
+ // use object configuration instead of importing metadata file directly
47
+ if (!isFile) {
48
+
49
+ const {
50
+ elementsOrder = order.default,
51
+ entityID,
52
+ signingCert,
53
+ encryptCert,
54
+ authnRequestsSigned = false,
55
+ wantAssertionsSigned = false,
56
+ wantMessageSigned = false,
57
+ signatureConfig,
58
+ nameIDFormat = [],
59
+ singleLogoutService = [],
60
+ assertionConsumerService = [],
61
+ attributeConsumingService = []
62
+ } = meta as MetadataSpOptions;
63
+
64
+ const descriptors: MetaElement = {
65
+ KeyDescriptor: [],
66
+ NameIDFormat: [],
67
+ SingleLogoutService: [],
68
+ AssertionConsumerService: [],
69
+ AttributeConsumingService: [],
70
+ };
71
+
72
+ const SPSSODescriptor: any[] = [{
73
+ _attr: {
74
+ AuthnRequestsSigned: String(authnRequestsSigned),
75
+ WantAssertionsSigned: String(wantAssertionsSigned),
76
+ protocolSupportEnumeration: namespace.names.protocol,
77
+ },
78
+ }];
79
+
80
+ if (wantMessageSigned && signatureConfig === undefined) {
81
+ console.warn('Construct service provider - missing signatureConfig');
82
+ }
83
+
84
+ for(const cert of castArrayOpt(signingCert)) {
85
+ descriptors.KeyDescriptor!.push(libsaml.createKeySection('signing', cert).KeyDescriptor);
86
+ }
87
+
88
+ for(const cert of castArrayOpt(encryptCert)) {
89
+ descriptors.KeyDescriptor!.push(libsaml.createKeySection('encryption', cert).KeyDescriptor);
90
+ }
91
+
92
+ if (isNonEmptyArray(nameIDFormat)) {
93
+ nameIDFormat.forEach(f => descriptors.NameIDFormat!.push(f));
94
+ } else {
95
+ // default value
96
+ descriptors.NameIDFormat!.push(namespace.format.emailAddress);
97
+ }
98
+
99
+ if (isNonEmptyArray(singleLogoutService)) {
100
+ singleLogoutService.forEach(a => {
101
+ const attr: any = {
102
+ Binding: a.Binding,
103
+ Location: a.Location,
104
+ };
105
+ if (a.isDefault) {
106
+ attr.isDefault = true;
107
+ }
108
+ descriptors.SingleLogoutService!.push([{ _attr: attr }]);
109
+ });
110
+ }
111
+
112
+ if (isNonEmptyArray(assertionConsumerService)) {
113
+ let indexCount = 0;
114
+ assertionConsumerService.forEach(a => {
115
+ const attr: any = {
116
+ index: String(indexCount++),
117
+ Binding: a.Binding,
118
+ Location: a.Location,
119
+ };
120
+ if (a.isDefault) {
121
+ attr.isDefault = true;
122
+ }
123
+ descriptors.AssertionConsumerService!.push([{ _attr: attr }]);
124
+ });
125
+ } else {
126
+ console.warn('Missing endpoint of AssertionConsumerService');
127
+ }
128
+ // 修改原有处理逻辑
129
+ if (isNonEmptyArray(attributeConsumingService)) {
130
+ attributeConsumingService.forEach((service,index)=> {
131
+ // 1. 构建AttributeConsumingService主元素
132
+ let indexCount = 0;
133
+ let attrConsumingService: any[] = [{
134
+ _attr: {
135
+ index: String(index + 1),
136
+ }
137
+ }];
138
+ if (service.isDefault) {
139
+ attrConsumingService[0]._attr.isDefault = true;
140
+ }
141
+ // 2. 添加ServiceName子元素
142
+ if (isNonEmptyArray( service.serviceName)){
143
+ service.serviceName.forEach(({ value, lang }) => {
144
+ attrConsumingService.push({
145
+ ServiceName: [
146
+ {
147
+ _attr: lang ? { 'xml:lang': lang } : {},
148
+ },
149
+ value
150
+ ]
151
+ });
152
+ });
153
+ }
154
+
155
+ if (isNonEmptyArray( service.serviceDescription)){
156
+ service.serviceDescription.forEach(({ value, lang }) => {
157
+ attrConsumingService.push({
158
+ ServiceDescription: [
159
+ {
160
+ _attr: lang ? { 'xml:lang': lang } : {},
161
+ },
162
+ value
163
+ ]
164
+ });
165
+ });
166
+ }
167
+ // 3. 添加RequestedAttribute子元素
168
+ if (isNonEmptyArray(service.requestedAttributes)) {
169
+ service.requestedAttributes.forEach(attr => {
170
+ const requestedAttr: any = {
171
+ _attr: {
172
+ ...(attr.isRequired && { isRequired: String(attr.isRequired) }),
173
+ Name: attr.name,
174
+ ...(attr.friendlyName && { FriendlyName: attr.friendlyName }),
175
+ }
176
+ };
177
+ /* // 处理属性值白名单
178
+ if (isNonEmptyArray(attr.attributeValue)) {
179
+ requestedAttr[namespace.tags.attributeValue] = attr.attributeValue.map(val => ({
180
+ _: val
181
+ }));
182
+ }*/
183
+ attrConsumingService.push({
184
+ RequestedAttribute: [requestedAttr]
185
+ });
186
+ });
187
+ }
188
+
189
+ // 4. 将完整元素加入描述符
190
+ descriptors.AttributeConsumingService!.push(attrConsumingService);
191
+ });
192
+ }
193
+
194
+ // handle element order
195
+ const existedElements = elementsOrder.filter(name => isNonEmptyArray(descriptors[name]));
196
+ existedElements.forEach(name => {
197
+ descriptors[name].forEach(e => SPSSODescriptor.push({ [name]: e }));
198
+ });
199
+ // Re-assign the meta reference as a XML string|Buffer for use with the parent constructor
200
+ meta = xml([{
201
+ EntityDescriptor: [{
202
+ _attr: {
203
+ entityID,
204
+ 'xmlns': namespace.names.metadata,
205
+ 'xmlns:assertion': namespace.names.assertion,
206
+ 'xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
207
+ },
208
+ }, { SPSSODescriptor }],
209
+ }]);
210
+
211
+ }
212
+
213
+ // Use the re-assigned meta object reference here
214
+ super(meta as string | Buffer, [
215
+ {
216
+ key: 'spSSODescriptor',
217
+ localPath: ['EntityDescriptor', 'SPSSODescriptor'],
218
+ attributes: ['WantAssertionsSigned', 'AuthnRequestsSigned'],
219
+ },
220
+ {
221
+ key: 'assertionConsumerService',
222
+ localPath: ['EntityDescriptor', 'SPSSODescriptor', 'AssertionConsumerService'],
223
+ attributes: ['Binding', 'Location', 'isDefault', 'index'],
224
+ }
225
+ ]);
226
+
227
+ }
228
+
229
+ /**
230
+ * @desc Get the preference whether it wants a signed assertion response
231
+ * @return {boolean} Wantassertionssigned
232
+ */
233
+ public isWantAssertionsSigned(): boolean {
234
+ return this.meta.spSSODescriptor.wantAssertionsSigned === 'true';
235
+ }
236
+ /**
237
+ * @desc Get the preference whether it signs request
238
+ * @return {boolean} Authnrequestssigned
239
+ */
240
+ public isAuthnRequestSigned(): boolean {
241
+ return this.meta.spSSODescriptor.authnRequestsSigned === 'true';
242
+ }
243
+ /**
244
+ * @desc Get the entity endpoint for assertion consumer service
245
+ * @param {string} binding protocol binding (e.g. redirect, post)
246
+ * @return {string/[string]} URL of endpoint(s)
247
+ */
248
+ public getAssertionConsumerService(binding: string): string | string[] {
249
+ if (isString(binding)) {
250
+ let location;
251
+ const bindName = namespace.binding[binding];
252
+ if (isNonEmptyArray(this.meta.assertionConsumerService)) {
253
+ this.meta.assertionConsumerService.forEach(obj => {
254
+ if (obj.binding === bindName) {
255
+ location = obj.location;
256
+ return;
257
+ }
258
+ });
259
+ } else {
260
+ if (this.meta.assertionConsumerService.binding === bindName) {
261
+ location = this.meta.assertionConsumerService.location;
262
+ }
263
+ }
264
+ return location;
265
+ }
266
+ return this.meta.assertionConsumerService;
267
+ }
268
+ }
@@ -0,0 +1,166 @@
1
+ /**
2
+ * @file metadata.ts
3
+ * @author tngan
4
+ * @desc An abstraction for metadata of identity provider and service provider
5
+ */
6
+ import * as fs from 'fs';
7
+ import { namespace } from './urn.js';
8
+ import { extract } from './extractor.js';
9
+ import { isString } from './utility.js';
10
+
11
+ export interface MetadataInterface {
12
+ xmlString: string;
13
+ getMetadata: () => string;
14
+ exportMetadata: (exportFile: string) => void;
15
+ getEntityID: () => string;
16
+ getX509Certificate: (certType: string) => string | string[];
17
+ getNameIDFormat: () => any[];
18
+ getSingleLogoutService: (binding: string | undefined) => string | object;
19
+ getSupportBindings: (services: string[]) => string[];
20
+ }
21
+
22
+ export default class Metadata implements MetadataInterface {
23
+
24
+ xmlString: string;
25
+ meta: any;
26
+
27
+ /**
28
+ * @param {string | Buffer} xml
29
+ * @param {object} extraParse for custom metadata extractor
30
+ */
31
+ constructor(xml: string | Buffer, extraParse: any = []) {
32
+ this.xmlString = xml.toString();
33
+ this.meta = extract(this.xmlString, extraParse.concat([
34
+ {
35
+ key: 'entityDescriptor',
36
+ localPath: ['EntityDescriptor'],
37
+ attributes: [],
38
+ context: true
39
+ },
40
+ {
41
+ key: 'entityID',
42
+ localPath: ['EntityDescriptor'],
43
+ attributes: ['entityID']
44
+ },
45
+ {
46
+ // shared certificate for both encryption and signing
47
+ key: 'sharedCertificate',
48
+ localPath: ['EntityDescriptor', '~SSODescriptor', 'KeyDescriptor', 'KeyInfo', 'X509Data', 'X509Certificate'],
49
+ attributes: []
50
+ },
51
+ {
52
+ // explicit certificate declaration for encryption and signing
53
+ key: 'certificate',
54
+ localPath: ['EntityDescriptor', '~SSODescriptor', 'KeyDescriptor'],
55
+ index: ['use'],
56
+ attributePath: ['KeyInfo', 'X509Data', 'X509Certificate'],
57
+ attributes: []
58
+ },
59
+ {
60
+ key: 'singleLogoutService',
61
+ localPath: ['EntityDescriptor', '~SSODescriptor', 'SingleLogoutService'],
62
+ attributes: ['Binding', 'Location']
63
+ },
64
+ {
65
+ key: 'nameIDFormat',
66
+ localPath: ['EntityDescriptor', '~SSODescriptor', 'NameIDFormat'],
67
+ attributes: [],
68
+ }
69
+ ]));
70
+
71
+ // get shared certificate
72
+ const sharedCertificate = this.meta.sharedCertificate;
73
+ if (typeof sharedCertificate === 'string') {
74
+ this.meta.certificate = {
75
+ signing: sharedCertificate,
76
+ encryption: sharedCertificate
77
+ };
78
+ delete this.meta.sharedCertificate;
79
+ }
80
+
81
+ if (
82
+ Array.isArray(this.meta.entityDescriptor) &&
83
+ this.meta.entityDescriptor.length > 1
84
+ ) {
85
+ throw new Error('ERR_MULTIPLE_METADATA_ENTITYDESCRIPTOR');
86
+ }
87
+
88
+ }
89
+
90
+ /**
91
+ * @desc Get the metadata in xml format
92
+ * @return {string} metadata in xml format
93
+ */
94
+ public getMetadata(): string {
95
+ return this.xmlString;
96
+ }
97
+
98
+ /**
99
+ * @desc Export the metadata to specific file
100
+ * @param {string} exportFile is the output file path
101
+ */
102
+ public exportMetadata(exportFile: string): void {
103
+ fs.writeFileSync(exportFile, this.xmlString);
104
+ }
105
+
106
+ /**
107
+ * @desc Get the entityID in metadata
108
+ * @return {string} entityID
109
+ */
110
+ public getEntityID(): string {
111
+ return this.meta.entityID;
112
+ }
113
+
114
+ /**
115
+ * @desc Get the x509 certificate declared in entity metadata
116
+ * @param {string} use declares the type of certificate
117
+ * @return {string} certificate in string format
118
+ */
119
+ public getX509Certificate(use: string) {
120
+ return this.meta.certificate[use] || null;
121
+ }
122
+
123
+ /**
124
+ * @desc Get the support NameID format declared in entity metadata
125
+ * @return {array} support NameID format
126
+ */
127
+ public getNameIDFormat(): any {
128
+ return this.meta.nameIDFormat;
129
+ }
130
+
131
+ /**
132
+ * @desc Get the entity endpoint for single logout service
133
+ * @param {string} binding e.g. redirect, post
134
+ * @return {string/object} location
135
+ */
136
+ public getSingleLogoutService(binding: string | undefined): string | object {
137
+ if (binding && isString(binding)) {
138
+ const bindType = namespace.binding[binding];
139
+ let singleLogoutService = this.meta.singleLogoutService;
140
+ if (!(singleLogoutService instanceof Array)) {
141
+ singleLogoutService = [singleLogoutService];
142
+ }
143
+ const service = singleLogoutService.find(obj => obj.binding === bindType);
144
+ if (service) {
145
+ return service.location;
146
+ }
147
+ }
148
+ return this.meta.singleLogoutService;
149
+ }
150
+
151
+ /**
152
+ * @desc Get the support bindings
153
+ * @param {[string]} services
154
+ * @return {[string]} support bindings
155
+ */
156
+ public getSupportBindings(services: string[]): string[] {
157
+ let supportBindings = [];
158
+ if (services) {
159
+ supportBindings = services.reduce((acc: any, service) => {
160
+ const supportBinding = Object.keys(service)[0];
161
+ return acc.push(supportBinding);
162
+ }, []);
163
+ }
164
+ return supportBindings;
165
+ }
166
+ }