samlify 2.12.0 → 2.13.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/README.md +1 -1
- package/build/src/api.js +41 -3
- package/build/src/api.js.map +1 -1
- package/build/src/binding-post.js +236 -182
- package/build/src/binding-post.js.map +1 -1
- package/build/src/binding-redirect.js +303 -215
- package/build/src/binding-redirect.js.map +1 -1
- package/build/src/binding-simplesign.js +285 -137
- package/build/src/binding-simplesign.js.map +1 -1
- package/build/src/entity-idp.js +130 -47
- package/build/src/entity-idp.js.map +1 -1
- package/build/src/entity-sp.js +81 -39
- package/build/src/entity-sp.js.map +1 -1
- package/build/src/entity.js +100 -62
- package/build/src/entity.js.map +1 -1
- package/build/src/extractor.js +118 -151
- package/build/src/extractor.js.map +1 -1
- package/build/src/flow.js +100 -96
- package/build/src/flow.js.map +1 -1
- package/build/src/libsaml.js +315 -259
- package/build/src/libsaml.js.map +1 -1
- package/build/src/metadata-idp.js +60 -30
- package/build/src/metadata-idp.js.map +1 -1
- package/build/src/metadata-sp.js +51 -41
- package/build/src/metadata-sp.js.map +1 -1
- package/build/src/metadata.js +47 -43
- package/build/src/metadata.js.map +1 -1
- package/build/src/options.js +73 -0
- package/build/src/options.js.map +1 -0
- package/build/src/urn.js +28 -1
- package/build/src/urn.js.map +1 -1
- package/build/src/utility.js +140 -85
- package/build/src/utility.js.map +1 -1
- package/build/src/validator.js +27 -10
- package/build/src/validator.js.map +1 -1
- package/package.json +16 -5
- package/types/src/api.d.ts +33 -3
- package/types/src/binding-post.d.ts +67 -34
- package/types/src/binding-redirect.d.ts +58 -31
- package/types/src/binding-simplesign.d.ts +77 -21
- package/types/src/entity-idp.d.ts +40 -31
- package/types/src/entity-sp.d.ts +37 -27
- package/types/src/entity.d.ts +71 -77
- package/types/src/extractor.d.ts +31 -22
- package/types/src/flow.d.ts +24 -2
- package/types/src/libsaml.d.ts +172 -118
- package/types/src/metadata-idp.d.ts +27 -11
- package/types/src/metadata-sp.d.ts +29 -19
- package/types/src/metadata.d.ts +59 -34
- package/types/src/options.d.ts +37 -0
- package/types/src/types.d.ts +250 -24
- package/types/src/urn.d.ts +7 -0
- package/types/src/utility.d.ts +139 -90
- package/types/src/validator.d.ts +21 -0
- package/.circleci/config.yml +0 -98
- package/.editorconfig +0 -19
- package/.github/FUNDING.yml +0 -1
- package/.github/workflows/deploy-docs.yml +0 -56
- package/.pre-commit.sh +0 -15
- package/.snyk +0 -4
- package/Makefile +0 -25
- package/index.ts +0 -28
- package/samlify-2.11.0.tgz +0 -0
- package/src/api.ts +0 -48
- package/src/binding-post.ts +0 -336
- package/src/binding-redirect.ts +0 -335
- package/src/binding-simplesign.ts +0 -231
- package/src/entity-idp.ts +0 -145
- package/src/entity-sp.ts +0 -114
- package/src/entity.ts +0 -243
- package/src/extractor.ts +0 -399
- package/src/flow.ts +0 -469
- package/src/libsaml.ts +0 -779
- package/src/metadata-idp.ts +0 -146
- package/src/metadata-sp.ts +0 -203
- package/src/metadata.ts +0 -166
- package/src/types.ts +0 -127
- package/src/urn.ts +0 -210
- package/src/utility.ts +0 -259
- package/src/validator.ts +0 -44
- package/tsconfig.json +0 -41
- package/tslint.json +0 -35
- package/types.d.ts +0 -2
- package/vitest.config.ts +0 -12
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file binding-simplesign.ts
|
|
3
|
-
* @author Orange
|
|
4
|
-
* @desc Binding-level API, declare the functions using POST SimpleSign binding
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { wording, StatusCode } from './urn';
|
|
8
|
-
import { BindingContext, SimpleSignComputedContext } from './entity';
|
|
9
|
-
import libsaml from './libsaml';
|
|
10
|
-
import utility, { get } from './utility';
|
|
11
|
-
|
|
12
|
-
const binding = wording.binding;
|
|
13
|
-
const urlParams = wording.urlParams;
|
|
14
|
-
|
|
15
|
-
export interface BuildSimpleSignConfig {
|
|
16
|
-
type: string;
|
|
17
|
-
context: string;
|
|
18
|
-
entitySetting: any;
|
|
19
|
-
relayState?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface BindingSimpleSignContext {
|
|
23
|
-
id: string;
|
|
24
|
-
context: string;
|
|
25
|
-
signature: any;
|
|
26
|
-
sigAlg: string;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @private
|
|
31
|
-
* @desc Helper of generating URL param/value pair
|
|
32
|
-
* @param {string} param key
|
|
33
|
-
* @param {string} value value of key
|
|
34
|
-
* @param {boolean} first determine whether the param is the starting one in order to add query header '?'
|
|
35
|
-
* @return {string}
|
|
36
|
-
*/
|
|
37
|
-
function pvPair(param: string, value: string, first?: boolean): string {
|
|
38
|
-
return (first === true ? '?' : '&') + param + '=' + value;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* @private
|
|
42
|
-
* @desc Refactored part of simple signature generation for login/logout request
|
|
43
|
-
* @param {string} type
|
|
44
|
-
* @param {string} rawSamlRequest
|
|
45
|
-
* @param {object} entitySetting
|
|
46
|
-
* @return {string}
|
|
47
|
-
*/
|
|
48
|
-
function buildSimpleSignature(opts: BuildSimpleSignConfig) : string {
|
|
49
|
-
const {
|
|
50
|
-
type,
|
|
51
|
-
context,
|
|
52
|
-
entitySetting,
|
|
53
|
-
} = opts;
|
|
54
|
-
let { relayState = '' } = opts;
|
|
55
|
-
const queryParam = libsaml.getQueryParamByType(type);
|
|
56
|
-
|
|
57
|
-
if (relayState !== '') {
|
|
58
|
-
relayState = pvPair(urlParams.relayState, relayState);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const sigAlg = pvPair(urlParams.sigAlg, entitySetting.requestSignatureAlgorithm);
|
|
62
|
-
const octetString = context + relayState + sigAlg;
|
|
63
|
-
return libsaml.constructMessageSignature(
|
|
64
|
-
queryParam + '=' + octetString,
|
|
65
|
-
entitySetting.privateKey,
|
|
66
|
-
entitySetting.privateKeyPass,
|
|
67
|
-
undefined,
|
|
68
|
-
entitySetting.requestSignatureAlgorithm
|
|
69
|
-
).toString();
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* @desc Generate a base64 encoded login request
|
|
74
|
-
* @param {string} referenceTagXPath reference uri
|
|
75
|
-
* @param {object} entity object includes both idp and sp
|
|
76
|
-
* @param {function} customTagReplacement used when developers have their own login response template
|
|
77
|
-
*/
|
|
78
|
-
function base64LoginRequest(entity: any, customTagReplacement?: (template: string) => BindingContext): SimpleSignComputedContext {
|
|
79
|
-
const metadata = { idp: entity.idp.entityMeta, sp: entity.sp.entityMeta };
|
|
80
|
-
const spSetting = entity.sp.entitySetting;
|
|
81
|
-
let id: string = '';
|
|
82
|
-
|
|
83
|
-
if (metadata && metadata.idp && metadata.sp) {
|
|
84
|
-
const base = metadata.idp.getSingleSignOnService(binding.simpleSign);
|
|
85
|
-
let rawSamlRequest: string;
|
|
86
|
-
if (spSetting.loginRequestTemplate && customTagReplacement) {
|
|
87
|
-
const info = customTagReplacement(spSetting.loginRequestTemplate.context);
|
|
88
|
-
id = get(info, 'id', null);
|
|
89
|
-
rawSamlRequest = get(info, 'context', null);
|
|
90
|
-
} else {
|
|
91
|
-
const nameIDFormat = spSetting.nameIDFormat;
|
|
92
|
-
const selectedNameIDFormat = Array.isArray(nameIDFormat) ? nameIDFormat[0] : nameIDFormat;
|
|
93
|
-
id = spSetting.generateID();
|
|
94
|
-
rawSamlRequest = libsaml.replaceTagsByValue(libsaml.defaultLoginRequestTemplate.context, {
|
|
95
|
-
ID: id,
|
|
96
|
-
Destination: base,
|
|
97
|
-
Issuer: metadata.sp.getEntityID(),
|
|
98
|
-
IssueInstant: new Date().toISOString(),
|
|
99
|
-
AssertionConsumerServiceURL: metadata.sp.getAssertionConsumerService(binding.simpleSign),
|
|
100
|
-
EntityID: metadata.sp.getEntityID(),
|
|
101
|
-
AllowCreate: spSetting.allowCreate,
|
|
102
|
-
NameIDFormat: selectedNameIDFormat
|
|
103
|
-
} as any);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
let simpleSignatureContext : any = null;
|
|
107
|
-
if (metadata.idp.isWantAuthnRequestsSigned()) {
|
|
108
|
-
const simpleSignature = buildSimpleSignature({
|
|
109
|
-
type: urlParams.samlRequest,
|
|
110
|
-
context: rawSamlRequest,
|
|
111
|
-
entitySetting: spSetting,
|
|
112
|
-
relayState: spSetting.relayState,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
simpleSignatureContext = {
|
|
116
|
-
signature: simpleSignature,
|
|
117
|
-
sigAlg: spSetting.requestSignatureAlgorithm,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
// No need to embeded XML signature
|
|
121
|
-
return {
|
|
122
|
-
id,
|
|
123
|
-
context: utility.base64Encode(rawSamlRequest),
|
|
124
|
-
...simpleSignatureContext,
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
throw new Error('ERR_GENERATE_POST_SIMPLESIGN_LOGIN_REQUEST_MISSING_METADATA');
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* @desc Generate a base64 encoded 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 relay state
|
|
135
|
-
* @param {function} customTagReplacement used when developers have their own login response template
|
|
136
|
-
*/
|
|
137
|
-
async function base64LoginResponse(requestInfo: any = {}, entity: any, user: any = {}, relayState?: string, customTagReplacement?: (template: string) => BindingContext): Promise<BindingSimpleSignContext> {
|
|
138
|
-
const idpSetting = entity.idp.entitySetting;
|
|
139
|
-
const spSetting = entity.sp.entitySetting;
|
|
140
|
-
const id = idpSetting.generateID();
|
|
141
|
-
const metadata = {
|
|
142
|
-
idp: entity.idp.entityMeta,
|
|
143
|
-
sp: entity.sp.entityMeta,
|
|
144
|
-
};
|
|
145
|
-
const nameIDFormat = idpSetting.nameIDFormat;
|
|
146
|
-
const selectedNameIDFormat = Array.isArray(nameIDFormat) ? nameIDFormat[0] : nameIDFormat;
|
|
147
|
-
if (metadata && metadata.idp && metadata.sp) {
|
|
148
|
-
const base = metadata.sp.getAssertionConsumerService(binding.simpleSign);
|
|
149
|
-
let rawSamlResponse: string;
|
|
150
|
-
const nowTime = new Date();
|
|
151
|
-
// Five minutes later : nowtime + 5 * 60 * 1000 (in milliseconds)
|
|
152
|
-
const fiveMinutesLaterTime = new Date(nowTime.getTime() + 300_000 );
|
|
153
|
-
const tvalue: any = {
|
|
154
|
-
ID: id,
|
|
155
|
-
AssertionID: idpSetting.generateID(),
|
|
156
|
-
Destination: base,
|
|
157
|
-
Audience: metadata.sp.getEntityID(),
|
|
158
|
-
EntityID: metadata.sp.getEntityID(),
|
|
159
|
-
SubjectRecipient: base,
|
|
160
|
-
Issuer: metadata.idp.getEntityID(),
|
|
161
|
-
IssueInstant: nowTime.toISOString(),
|
|
162
|
-
AssertionConsumerServiceURL: base,
|
|
163
|
-
StatusCode: StatusCode.Success,
|
|
164
|
-
// can be customized
|
|
165
|
-
ConditionsNotBefore: nowTime.toISOString(),
|
|
166
|
-
ConditionsNotOnOrAfter: fiveMinutesLaterTime.toISOString(),
|
|
167
|
-
SubjectConfirmationDataNotOnOrAfter: fiveMinutesLaterTime.toISOString(),
|
|
168
|
-
NameIDFormat: selectedNameIDFormat,
|
|
169
|
-
NameID: user.email || '',
|
|
170
|
-
InResponseTo: get(requestInfo, 'extract.request.id', ''),
|
|
171
|
-
AuthnStatement: '',
|
|
172
|
-
AttributeStatement: '',
|
|
173
|
-
};
|
|
174
|
-
if (idpSetting.loginResponseTemplate && customTagReplacement) {
|
|
175
|
-
const template = customTagReplacement(idpSetting.loginResponseTemplate.context);
|
|
176
|
-
rawSamlResponse = get(template, 'context', null);
|
|
177
|
-
} else {
|
|
178
|
-
if (requestInfo !== null) {
|
|
179
|
-
tvalue.InResponseTo = requestInfo.extract.request.id;
|
|
180
|
-
}
|
|
181
|
-
rawSamlResponse = libsaml.replaceTagsByValue(libsaml.defaultLoginResponseTemplate.context, tvalue);
|
|
182
|
-
}
|
|
183
|
-
const { privateKey, privateKeyPass, requestSignatureAlgorithm: signatureAlgorithm } = idpSetting;
|
|
184
|
-
const config = {
|
|
185
|
-
privateKey,
|
|
186
|
-
privateKeyPass,
|
|
187
|
-
signatureAlgorithm,
|
|
188
|
-
signingCert: metadata.idp.getX509Certificate('signing'),
|
|
189
|
-
isBase64Output: false,
|
|
190
|
-
};
|
|
191
|
-
// step: sign assertion ? -> encrypted ? -> sign message ?
|
|
192
|
-
if (metadata.sp.isWantAssertionsSigned()) {
|
|
193
|
-
rawSamlResponse = libsaml.constructSAMLSignature({
|
|
194
|
-
...config,
|
|
195
|
-
rawSamlMessage: rawSamlResponse,
|
|
196
|
-
transformationAlgorithms: spSetting.transformationAlgorithms,
|
|
197
|
-
referenceTagXPath: "/*[local-name(.)='Response']/*[local-name(.)='Assertion']",
|
|
198
|
-
signatureConfig: {
|
|
199
|
-
prefix: 'ds',
|
|
200
|
-
location: { reference: "/*[local-name(.)='Response']/*[local-name(.)='Assertion']/*[local-name(.)='Issuer']", action: 'after' },
|
|
201
|
-
},
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// SAML response must be signed sign message first, then encrypt
|
|
206
|
-
let simpleSignature: string = '';
|
|
207
|
-
// like in post and redirect bindings, login response is always signed.
|
|
208
|
-
simpleSignature = buildSimpleSignature({
|
|
209
|
-
type: urlParams.samlResponse,
|
|
210
|
-
context: rawSamlResponse,
|
|
211
|
-
entitySetting: idpSetting,
|
|
212
|
-
relayState: relayState,
|
|
213
|
-
} );
|
|
214
|
-
|
|
215
|
-
return Promise.resolve({
|
|
216
|
-
id,
|
|
217
|
-
context: utility.base64Encode(rawSamlResponse),
|
|
218
|
-
signature: simpleSignature,
|
|
219
|
-
sigAlg: idpSetting.requestSignatureAlgorithm,
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
throw new Error('ERR_GENERATE_POST_SIMPLESIGN_LOGIN_RESPONSE_MISSING_METADATA');
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
const simpleSignBinding = {
|
|
227
|
-
base64LoginRequest,
|
|
228
|
-
base64LoginResponse,
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
export default simpleSignBinding;
|
package/src/entity-idp.ts
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file entity-idp.ts
|
|
3
|
-
* @author tngan
|
|
4
|
-
* @desc Declares the actions taken by identity provider
|
|
5
|
-
*/
|
|
6
|
-
import Entity, { ESamlHttpRequest } from './entity';
|
|
7
|
-
import {
|
|
8
|
-
ServiceProviderConstructor as ServiceProvider,
|
|
9
|
-
ServiceProviderMetadata,
|
|
10
|
-
IdentityProviderMetadata,
|
|
11
|
-
IdentityProviderSettings,
|
|
12
|
-
} from './types';
|
|
13
|
-
import libsaml from './libsaml';
|
|
14
|
-
import { namespace } from './urn';
|
|
15
|
-
import postBinding from './binding-post';
|
|
16
|
-
import redirectBinding from './binding-redirect';
|
|
17
|
-
import simpleSignBinding from './binding-simplesign';
|
|
18
|
-
import { flow, FlowResult } from './flow';
|
|
19
|
-
import { isString } from './utility';
|
|
20
|
-
import { BindingContext } from './entity';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Identity provider can be configured using either metadata importing or idpSetting
|
|
24
|
-
*/
|
|
25
|
-
export default function(props: IdentityProviderSettings) {
|
|
26
|
-
return new IdentityProvider(props);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Identity provider can be configured using either metadata importing or idpSetting
|
|
31
|
-
*/
|
|
32
|
-
export class IdentityProvider extends Entity {
|
|
33
|
-
|
|
34
|
-
entityMeta: IdentityProviderMetadata;
|
|
35
|
-
|
|
36
|
-
constructor(idpSetting: IdentityProviderSettings) {
|
|
37
|
-
const defaultIdpEntitySetting = {
|
|
38
|
-
wantAuthnRequestsSigned: false,
|
|
39
|
-
tagPrefix: {
|
|
40
|
-
encryptedAssertion: 'saml',
|
|
41
|
-
},
|
|
42
|
-
};
|
|
43
|
-
const entitySetting = Object.assign(defaultIdpEntitySetting, idpSetting);
|
|
44
|
-
// build attribute part
|
|
45
|
-
if (idpSetting.loginResponseTemplate) {
|
|
46
|
-
if (isString(idpSetting.loginResponseTemplate.context) && Array.isArray(idpSetting.loginResponseTemplate.attributes)) {
|
|
47
|
-
let attributeStatementTemplate;
|
|
48
|
-
let attributeTemplate;
|
|
49
|
-
if (!idpSetting.loginResponseTemplate.additionalTemplates || !idpSetting.loginResponseTemplate.additionalTemplates!.attributeStatementTemplate) {
|
|
50
|
-
attributeStatementTemplate = libsaml.defaultAttributeStatementTemplate;
|
|
51
|
-
} else {
|
|
52
|
-
attributeStatementTemplate = idpSetting.loginResponseTemplate.additionalTemplates!.attributeStatementTemplate!;
|
|
53
|
-
}
|
|
54
|
-
if (!idpSetting.loginResponseTemplate.additionalTemplates || !idpSetting.loginResponseTemplate.additionalTemplates!.attributeTemplate) {
|
|
55
|
-
attributeTemplate = libsaml.defaultAttributeTemplate;
|
|
56
|
-
} else {
|
|
57
|
-
attributeTemplate = idpSetting.loginResponseTemplate.additionalTemplates!.attributeTemplate!;
|
|
58
|
-
}
|
|
59
|
-
const replacement = {
|
|
60
|
-
AttributeStatement: libsaml.attributeStatementBuilder(idpSetting.loginResponseTemplate.attributes, attributeTemplate, attributeStatementTemplate),
|
|
61
|
-
};
|
|
62
|
-
entitySetting.loginResponseTemplate = {
|
|
63
|
-
...entitySetting.loginResponseTemplate,
|
|
64
|
-
context: libsaml.replaceTagsByValue(entitySetting.loginResponseTemplate!.context, replacement),
|
|
65
|
-
};
|
|
66
|
-
} else {
|
|
67
|
-
console.warn('Invalid login response template');
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
super(entitySetting, 'idp');
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
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 },
|
|
88
|
-
customTagReplacement?: (template: string) => BindingContext,
|
|
89
|
-
encryptThenSign?: boolean,
|
|
90
|
-
relayState?: string,
|
|
91
|
-
) {
|
|
92
|
-
const protocol = namespace.binding[binding];
|
|
93
|
-
// can support post, redirect and post simple sign bindings for login response
|
|
94
|
-
let context: any = null;
|
|
95
|
-
switch (protocol) {
|
|
96
|
-
case namespace.binding.post:
|
|
97
|
-
context = await postBinding.base64LoginResponse(requestInfo, {
|
|
98
|
-
idp: this,
|
|
99
|
-
sp,
|
|
100
|
-
}, user, customTagReplacement, encryptThenSign);
|
|
101
|
-
break;
|
|
102
|
-
|
|
103
|
-
case namespace.binding.simpleSign:
|
|
104
|
-
context = await simpleSignBinding.base64LoginResponse( requestInfo, {
|
|
105
|
-
idp: this, sp,
|
|
106
|
-
}, user, relayState, customTagReplacement);
|
|
107
|
-
break;
|
|
108
|
-
|
|
109
|
-
case namespace.binding.redirect:
|
|
110
|
-
return redirectBinding.loginResponseRedirectURL(requestInfo, {
|
|
111
|
-
idp: this,
|
|
112
|
-
sp,
|
|
113
|
-
}, user, relayState, customTagReplacement);
|
|
114
|
-
|
|
115
|
-
default:
|
|
116
|
-
throw new Error('ERR_CREATE_RESPONSE_UNDEFINED_BINDING');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return {
|
|
120
|
-
...context,
|
|
121
|
-
relayState,
|
|
122
|
-
entityEndpoint: (sp.entityMeta as ServiceProviderMetadata).getAssertionConsumerService(binding) as string,
|
|
123
|
-
type: 'SAMLResponse'
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Validation of the parsed URL parameters
|
|
129
|
-
* @param sp ServiceProvider instance
|
|
130
|
-
* @param binding Protocol binding
|
|
131
|
-
* @param req RequesmessageSigningOrderst
|
|
132
|
-
*/
|
|
133
|
-
parseLoginRequest(sp: ServiceProvider, binding: string, req: ESamlHttpRequest) {
|
|
134
|
-
const self = this;
|
|
135
|
-
return flow({
|
|
136
|
-
from: sp,
|
|
137
|
-
self: self,
|
|
138
|
-
checkSignature: self.entityMeta.isWantAuthnRequestsSigned(),
|
|
139
|
-
parserType: 'SAMLRequest',
|
|
140
|
-
type: 'login',
|
|
141
|
-
binding: binding,
|
|
142
|
-
request: req
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
}
|
package/src/entity-sp.ts
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file entity-sp.ts
|
|
3
|
-
* @author tngan
|
|
4
|
-
* @desc Declares the actions taken by service provider
|
|
5
|
-
*/
|
|
6
|
-
import Entity, {
|
|
7
|
-
BindingContext,
|
|
8
|
-
PostBindingContext,
|
|
9
|
-
ESamlHttpRequest,
|
|
10
|
-
SimpleSignBindingContext,
|
|
11
|
-
} from './entity';
|
|
12
|
-
import {
|
|
13
|
-
IdentityProviderConstructor as IdentityProvider,
|
|
14
|
-
ServiceProviderMetadata,
|
|
15
|
-
ServiceProviderSettings,
|
|
16
|
-
} from './types';
|
|
17
|
-
import { namespace } from './urn';
|
|
18
|
-
import redirectBinding from './binding-redirect';
|
|
19
|
-
import postBinding from './binding-post';
|
|
20
|
-
import simpleSignBinding from './binding-simplesign';
|
|
21
|
-
import { flow, FlowResult } from './flow';
|
|
22
|
-
|
|
23
|
-
/*
|
|
24
|
-
* @desc interface function
|
|
25
|
-
*/
|
|
26
|
-
export default function(props: ServiceProviderSettings) {
|
|
27
|
-
return new ServiceProvider(props);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* @desc Service provider can be configured using either metadata importing or spSetting
|
|
32
|
-
* @param {object} spSettingimport { FlowResult } from '../types/src/flow.d';
|
|
33
|
-
|
|
34
|
-
*/
|
|
35
|
-
export class ServiceProvider extends Entity {
|
|
36
|
-
entityMeta: ServiceProviderMetadata;
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @desc Inherited from Entity
|
|
40
|
-
* @param {object} spSetting setting of service provider
|
|
41
|
-
*/
|
|
42
|
-
constructor(spSetting: ServiceProviderSettings) {
|
|
43
|
-
const entitySetting = Object.assign({
|
|
44
|
-
authnRequestsSigned: false,
|
|
45
|
-
wantAssertionsSigned: false,
|
|
46
|
-
wantMessageSigned: false,
|
|
47
|
-
}, spSetting);
|
|
48
|
-
super(entitySetting, 'sp');
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* @desc Generates the login request for developers to design their own method
|
|
53
|
-
* @param {IdentityProvider} idp object of identity provider
|
|
54
|
-
* @param {string} binding protocol binding
|
|
55
|
-
* @param {function} customTagReplacement used when developers have their own login response template
|
|
56
|
-
*/
|
|
57
|
-
public createLoginRequest(
|
|
58
|
-
idp: IdentityProvider,
|
|
59
|
-
binding = 'redirect',
|
|
60
|
-
customTagReplacement?: (template: string) => BindingContext,
|
|
61
|
-
): BindingContext | PostBindingContext| SimpleSignBindingContext {
|
|
62
|
-
const nsBinding = namespace.binding;
|
|
63
|
-
const protocol = nsBinding[binding];
|
|
64
|
-
if (this.entityMeta.isAuthnRequestSigned() !== idp.entityMeta.isWantAuthnRequestsSigned()) {
|
|
65
|
-
throw new Error('ERR_METADATA_CONFLICT_REQUEST_SIGNED_FLAG');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
let context: any = null;
|
|
69
|
-
switch (protocol) {
|
|
70
|
-
case nsBinding.redirect:
|
|
71
|
-
return redirectBinding.loginRequestRedirectURL({ idp, sp: this }, customTagReplacement);
|
|
72
|
-
|
|
73
|
-
case nsBinding.post:
|
|
74
|
-
context = postBinding.base64LoginRequest("/*[local-name(.)='AuthnRequest']", { idp, sp: this }, customTagReplacement);
|
|
75
|
-
break;
|
|
76
|
-
|
|
77
|
-
case nsBinding.simpleSign:
|
|
78
|
-
// Object context = {id, context, signature, sigAlg}
|
|
79
|
-
context = simpleSignBinding.base64LoginRequest( { idp, sp: this }, customTagReplacement);
|
|
80
|
-
break;
|
|
81
|
-
|
|
82
|
-
default:
|
|
83
|
-
// Will support artifact in the next release
|
|
84
|
-
throw new Error('ERR_SP_LOGIN_REQUEST_UNDEFINED_BINDING');
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
...context,
|
|
89
|
-
relayState: this.entitySetting.relayState,
|
|
90
|
-
entityEndpoint: idp.entityMeta.getSingleSignOnService(binding) as string,
|
|
91
|
-
type: 'SAMLRequest',
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @desc Validation of the parsed the URL parameters
|
|
97
|
-
* @param {IdentityProvider} idp object of identity provider
|
|
98
|
-
* @param {string} binding protocol binding
|
|
99
|
-
* @param {request} req request
|
|
100
|
-
*/
|
|
101
|
-
public parseLoginResponse(idp, binding, request: ESamlHttpRequest) {
|
|
102
|
-
const self = this;
|
|
103
|
-
return flow({
|
|
104
|
-
from: idp,
|
|
105
|
-
self: self,
|
|
106
|
-
checkSignature: true, // saml response must have signature
|
|
107
|
-
parserType: 'SAMLResponse',
|
|
108
|
-
type: 'login',
|
|
109
|
-
binding: binding,
|
|
110
|
-
request: request
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
}
|