@boxyhq/saml-jackson 0.5.1 → 1.0.2
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/dist/controller/api.d.ts +1 -0
- package/dist/controller/api.js +37 -5
- package/dist/controller/health-check.d.ts +11 -0
- package/dist/controller/health-check.js +53 -0
- package/dist/controller/logout.d.ts +18 -0
- package/dist/controller/logout.js +199 -0
- package/dist/controller/oauth/redirect.d.ts +1 -1
- package/dist/controller/oauth/redirect.js +6 -1
- package/dist/controller/oauth.d.ts +5 -3
- package/dist/controller/oauth.js +156 -27
- package/dist/controller/utils.d.ts +2 -1
- package/dist/controller/utils.js +11 -24
- package/dist/db/mem.js +31 -12
- package/dist/db/mongo.js +3 -10
- package/dist/db/redis.js +17 -6
- package/dist/db/sql/sql.d.ts +1 -1
- package/dist/db/sql/sql.js +10 -9
- package/dist/db/utils.d.ts +2 -0
- package/dist/db/utils.js +3 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +14 -2
- package/dist/typings.d.ts +50 -21
- package/package.json +22 -25
- package/dist/saml/saml.d.ts +0 -12
- package/dist/saml/saml.js +0 -211
package/dist/typings.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
export declare type IdPConfig = {
|
2
2
|
defaultRedirectUrl: string;
|
3
|
-
redirectUrl: string;
|
3
|
+
redirectUrl: string[] | string;
|
4
4
|
tenant: string;
|
5
5
|
product: string;
|
6
6
|
name: string;
|
@@ -29,7 +29,8 @@ export interface IOAuthController {
|
|
29
29
|
authorize_form?: string;
|
30
30
|
}>;
|
31
31
|
samlResponse(body: SAMLResponsePayload): Promise<{
|
32
|
-
redirect_url
|
32
|
+
redirect_url?: string;
|
33
|
+
app_select_form?: string;
|
33
34
|
}>;
|
34
35
|
token(body: OAuthTokenReq): Promise<OAuthTokenRes>;
|
35
36
|
userInfo(token: string): Promise<Profile>;
|
@@ -37,20 +38,28 @@ export interface IOAuthController {
|
|
37
38
|
export interface IAdminController {
|
38
39
|
getAllConfig(pageOffset?: number, pageLimit?: number): any;
|
39
40
|
}
|
41
|
+
export interface IHealthCheckController {
|
42
|
+
status(): Promise<{
|
43
|
+
status: number;
|
44
|
+
}>;
|
45
|
+
init(): Promise<void>;
|
46
|
+
}
|
40
47
|
export interface OAuthReqBody {
|
41
48
|
response_type: 'code';
|
42
49
|
client_id: string;
|
43
50
|
redirect_uri: string;
|
44
51
|
state: string;
|
45
|
-
tenant
|
46
|
-
product
|
52
|
+
tenant?: string;
|
53
|
+
product?: string;
|
47
54
|
code_challenge: string;
|
48
55
|
code_challenge_method: 'plain' | 'S256' | '';
|
49
56
|
provider: 'saml';
|
57
|
+
idp_hint?: string;
|
50
58
|
}
|
51
59
|
export interface SAMLResponsePayload {
|
52
60
|
SAMLResponse: string;
|
53
61
|
RelayState: string;
|
62
|
+
idp_hint?: string;
|
54
63
|
}
|
55
64
|
export interface OAuthTokenReq {
|
56
65
|
client_id: string;
|
@@ -105,23 +114,6 @@ export interface DatabaseOption {
|
|
105
114
|
encryptionKey?: string;
|
106
115
|
pageLimit?: number;
|
107
116
|
}
|
108
|
-
export interface SAMLReq {
|
109
|
-
ssoUrl?: string;
|
110
|
-
entityID: string;
|
111
|
-
callbackUrl: string;
|
112
|
-
isPassive?: boolean;
|
113
|
-
forceAuthn?: boolean;
|
114
|
-
identifierFormat?: 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress';
|
115
|
-
providerName?: 'BoxyHQ';
|
116
|
-
signingKey: string;
|
117
|
-
publicKey: string;
|
118
|
-
}
|
119
|
-
export interface SAMLProfile {
|
120
|
-
audience: string;
|
121
|
-
claims: Record<string, any>;
|
122
|
-
issuer: string;
|
123
|
-
sessionIndex: string;
|
124
|
-
}
|
125
117
|
export interface JacksonOption {
|
126
118
|
externalUrl: string;
|
127
119
|
samlPath: string;
|
@@ -130,4 +122,41 @@ export interface JacksonOption {
|
|
130
122
|
idpEnabled?: boolean;
|
131
123
|
db: DatabaseOption;
|
132
124
|
clientSecretVerifier?: string;
|
125
|
+
idpDiscoveryPath?: string;
|
126
|
+
}
|
127
|
+
export interface SLORequestParams {
|
128
|
+
nameId: string;
|
129
|
+
tenant: string;
|
130
|
+
product: string;
|
131
|
+
redirectUrl?: string;
|
132
|
+
}
|
133
|
+
interface Metadata {
|
134
|
+
sso: {
|
135
|
+
postUrl?: string;
|
136
|
+
redirectUrl: string;
|
137
|
+
};
|
138
|
+
slo: {
|
139
|
+
redirectUrl?: string;
|
140
|
+
postUrl?: string;
|
141
|
+
};
|
142
|
+
entityID: string;
|
143
|
+
thumbprint: string;
|
144
|
+
loginType: 'idp';
|
145
|
+
provider: string;
|
146
|
+
}
|
147
|
+
export interface SAMLConfig {
|
148
|
+
idpMetadata: Metadata;
|
149
|
+
certs: {
|
150
|
+
privateKey: string;
|
151
|
+
publicKey: string;
|
152
|
+
};
|
153
|
+
defaultRedirectUrl: string;
|
154
|
+
}
|
155
|
+
export interface ILogoutController {
|
156
|
+
createRequest(body: SLORequestParams): Promise<{
|
157
|
+
logoutUrl: string | null;
|
158
|
+
logoutForm: string | null;
|
159
|
+
}>;
|
160
|
+
handleResponse(body: SAMLResponsePayload): Promise<any>;
|
133
161
|
}
|
162
|
+
export {};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@boxyhq/saml-jackson",
|
3
|
-
"version": "0.
|
3
|
+
"version": "1.0.2",
|
4
4
|
"description": "SAML Jackson library",
|
5
5
|
"keywords": [
|
6
6
|
"SAML 2.0"
|
@@ -18,12 +18,12 @@
|
|
18
18
|
],
|
19
19
|
"scripts": {
|
20
20
|
"build": "tsc -p tsconfig.build.json",
|
21
|
-
"db:migration:generate:postgres": "ts-node -
|
22
|
-
"db:migration:generate:mysql": "cross-env DB_TYPE=mysql DB_URL=mysql://root:mysql@localhost:3307/mysql ts-node -
|
23
|
-
"db:migration:generate:mariadb": "cross-env DB_TYPE=mariadb DB_URL=mariadb://root@localhost:3306/mysql ts-node -
|
24
|
-
"db:migration:run:postgres": "ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run",
|
25
|
-
"db:migration:run:mysql": "cross-env DB_TYPE=mysql DB_URL=mysql://root:mysql@localhost:3307/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run",
|
26
|
-
"db:migration:run:mariadb": "cross-env DB_TYPE=mariadb DB_URL=mariadb://root@localhost:3306/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run",
|
21
|
+
"db:migration:generate:postgres": "ts-node --transpile-only ./node_modules/typeorm/cli.js migration:generate -d typeorm.ts migration/postgres/pg_${MIGRATION_NAME}",
|
22
|
+
"db:migration:generate:mysql": "cross-env DB_TYPE=mysql DB_URL=mysql://root:mysql@localhost:3307/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:generate -d typeorm.ts migration/mysql/ms_${MIGRATION_NAME}",
|
23
|
+
"db:migration:generate:mariadb": "cross-env DB_TYPE=mariadb DB_URL=mariadb://root@localhost:3306/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:generate -d typeorm.ts migration/mariadb/md_${MIGRATION_NAME}",
|
24
|
+
"db:migration:run:postgres": "ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run -d typeorm.ts",
|
25
|
+
"db:migration:run:mysql": "cross-env DB_TYPE=mysql DB_URL=mysql://root:mysql@localhost:3307/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run -d typeorm.ts",
|
26
|
+
"db:migration:run:mariadb": "cross-env DB_TYPE=mariadb DB_URL=mariadb://root@localhost:3306/mysql ts-node --transpile-only ./node_modules/typeorm/cli.js migration:run -d typeorm.ts",
|
27
27
|
"prepublishOnly": "npm run build",
|
28
28
|
"test": "tap --ts --timeout=100 --coverage test/**/*.test.ts",
|
29
29
|
"sort": "npx sort-package-json"
|
@@ -36,38 +36,35 @@
|
|
36
36
|
"statements": 70
|
37
37
|
},
|
38
38
|
"dependencies": {
|
39
|
-
"@boxyhq/saml20": "0.2
|
39
|
+
"@boxyhq/saml20": "1.0.2",
|
40
40
|
"@opentelemetry/api-metrics": "0.27.0",
|
41
|
-
"@peculiar/webcrypto": "1.3.
|
41
|
+
"@peculiar/webcrypto": "1.3.3",
|
42
42
|
"@peculiar/x509": "1.6.1",
|
43
|
-
"mongodb": "4.
|
43
|
+
"mongodb": "4.5.0",
|
44
44
|
"mysql2": "2.3.3",
|
45
45
|
"pg": "8.7.3",
|
46
|
-
"
|
47
|
-
"redis": "4.0.4",
|
46
|
+
"redis": "4.0.6",
|
48
47
|
"reflect-metadata": "0.1.13",
|
49
48
|
"ripemd160": "2.0.2",
|
50
|
-
"
|
51
|
-
"typeorm": "0.2.45",
|
52
|
-
"xml-crypto": "2.1.3",
|
49
|
+
"typeorm": "0.3.6",
|
53
50
|
"xml2js": "0.4.23",
|
54
51
|
"xmlbuilder": "15.1.1"
|
55
52
|
},
|
56
53
|
"devDependencies": {
|
57
|
-
"@types/node": "17.0.
|
54
|
+
"@types/node": "17.0.30",
|
58
55
|
"@types/sinon": "10.0.11",
|
59
|
-
"@types/tap": "15.0.
|
60
|
-
"@typescript-eslint/eslint-plugin": "5.
|
61
|
-
"@typescript-eslint/parser": "5.
|
56
|
+
"@types/tap": "15.0.7",
|
57
|
+
"@typescript-eslint/eslint-plugin": "5.21.0",
|
58
|
+
"@typescript-eslint/parser": "5.21.0",
|
62
59
|
"cross-env": "7.0.3",
|
63
|
-
"eslint": "8.
|
60
|
+
"eslint": "8.14.0",
|
64
61
|
"eslint-config-prettier": "8.5.0",
|
65
|
-
"prettier": "2.6.
|
66
|
-
"sinon": "13.0.
|
67
|
-
"tap": "16.
|
62
|
+
"prettier": "2.6.2",
|
63
|
+
"sinon": "13.0.2",
|
64
|
+
"tap": "16.1.0",
|
68
65
|
"ts-node": "10.7.0",
|
69
|
-
"tsconfig-paths": "3.14.
|
70
|
-
"typescript": "4.6.
|
66
|
+
"tsconfig-paths": "3.14.1",
|
67
|
+
"typescript": "4.6.4"
|
71
68
|
},
|
72
69
|
"engines": {
|
73
70
|
"node": ">=14.18.1 <=16.x"
|
package/dist/saml/saml.d.ts
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
import { SAMLProfile, SAMLReq } from '../typings';
|
2
|
-
export declare const stripCertHeaderAndFooter: (cert: string) => string;
|
3
|
-
declare const _default: {
|
4
|
-
request: ({ ssoUrl, entityID, callbackUrl, isPassive, forceAuthn, identifierFormat, providerName, signingKey, publicKey, }: SAMLReq) => {
|
5
|
-
id: string;
|
6
|
-
request: string;
|
7
|
-
};
|
8
|
-
parseAsync: (rawAssertion: string) => Promise<SAMLProfile>;
|
9
|
-
validateAsync: (rawAssertion: string, options: any) => Promise<SAMLProfile>;
|
10
|
-
parseMetadataAsync: (idpMeta: string) => Promise<Record<string, any>>;
|
11
|
-
};
|
12
|
-
export default _default;
|
package/dist/saml/saml.js
DELETED
@@ -1,211 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3
|
-
if (k2 === undefined) k2 = k;
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
7
|
-
}
|
8
|
-
Object.defineProperty(o, k2, desc);
|
9
|
-
}) : (function(o, m, k, k2) {
|
10
|
-
if (k2 === undefined) k2 = k;
|
11
|
-
o[k2] = m[k];
|
12
|
-
}));
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
15
|
-
}) : function(o, v) {
|
16
|
-
o["default"] = v;
|
17
|
-
});
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
19
|
-
if (mod && mod.__esModule) return mod;
|
20
|
-
var result = {};
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
22
|
-
__setModuleDefault(result, mod);
|
23
|
-
return result;
|
24
|
-
};
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
32
|
-
});
|
33
|
-
};
|
34
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
35
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
36
|
-
};
|
37
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
38
|
-
exports.stripCertHeaderAndFooter = void 0;
|
39
|
-
const saml20_1 = __importDefault(require("@boxyhq/saml20"));
|
40
|
-
const xml2js_1 = __importDefault(require("xml2js"));
|
41
|
-
const thumbprint_1 = __importDefault(require("thumbprint"));
|
42
|
-
const xml_crypto_1 = __importDefault(require("xml-crypto"));
|
43
|
-
const rambda = __importStar(require("rambda"));
|
44
|
-
const xmlbuilder_1 = __importDefault(require("xmlbuilder"));
|
45
|
-
const crypto_1 = __importDefault(require("crypto"));
|
46
|
-
const claims_1 = __importDefault(require("./claims"));
|
47
|
-
const idPrefix = '_';
|
48
|
-
const authnXPath = '/*[local-name(.)="AuthnRequest" and namespace-uri(.)="urn:oasis:names:tc:SAML:2.0:protocol"]';
|
49
|
-
const issuerXPath = '/*[local-name(.)="Issuer" and namespace-uri(.)="urn:oasis:names:tc:SAML:2.0:assertion"]';
|
50
|
-
const stripCertHeaderAndFooter = (cert) => {
|
51
|
-
cert = cert.replace(/-+BEGIN CERTIFICATE-+\r?\n?/, '');
|
52
|
-
cert = cert.replace(/-+END CERTIFICATE-+\r?\n?/, '');
|
53
|
-
cert = cert.replace(/\r\n/g, '\n');
|
54
|
-
return cert;
|
55
|
-
};
|
56
|
-
exports.stripCertHeaderAndFooter = stripCertHeaderAndFooter;
|
57
|
-
function PubKeyInfo(pubKey) {
|
58
|
-
this.pubKey = (0, exports.stripCertHeaderAndFooter)(pubKey);
|
59
|
-
this.getKeyInfo = function (_key, prefix) {
|
60
|
-
prefix = prefix || '';
|
61
|
-
prefix = prefix ? prefix + ':' : prefix;
|
62
|
-
return `<${prefix}X509Data><${prefix}X509Certificate>${this.pubKey}</${prefix}X509Certificate</${prefix}X509Data>`;
|
63
|
-
};
|
64
|
-
}
|
65
|
-
const signRequest = (xml, signingKey, publicKey) => {
|
66
|
-
if (!xml) {
|
67
|
-
throw new Error('Please specify xml');
|
68
|
-
}
|
69
|
-
if (!signingKey) {
|
70
|
-
throw new Error('Please specify signingKey');
|
71
|
-
}
|
72
|
-
const sig = new xml_crypto_1.default.SignedXml();
|
73
|
-
sig.signatureAlgorithm = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256';
|
74
|
-
sig.keyInfoProvider = new PubKeyInfo(publicKey);
|
75
|
-
sig.signingKey = signingKey;
|
76
|
-
sig.addReference(authnXPath, ['http://www.w3.org/2000/09/xmldsig#enveloped-signature', 'http://www.w3.org/2001/10/xml-exc-c14n#'], 'http://www.w3.org/2001/04/xmlenc#sha256');
|
77
|
-
sig.computeSignature(xml, {
|
78
|
-
location: { reference: authnXPath + issuerXPath, action: 'after' },
|
79
|
-
});
|
80
|
-
return sig.getSignedXml();
|
81
|
-
};
|
82
|
-
const request = ({ ssoUrl, entityID, callbackUrl, isPassive = false, forceAuthn = false, identifierFormat = 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', providerName = 'BoxyHQ', signingKey, publicKey, }) => {
|
83
|
-
const id = idPrefix + crypto_1.default.randomBytes(10).toString('hex');
|
84
|
-
const date = new Date().toISOString();
|
85
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
86
|
-
const samlReq = {
|
87
|
-
'samlp:AuthnRequest': {
|
88
|
-
'@xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol',
|
89
|
-
'@ID': id,
|
90
|
-
'@Version': '2.0',
|
91
|
-
'@IssueInstant': date,
|
92
|
-
'@ProtocolBinding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
|
93
|
-
'@Destination': ssoUrl,
|
94
|
-
'saml:Issuer': {
|
95
|
-
'@xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion',
|
96
|
-
'#text': entityID,
|
97
|
-
},
|
98
|
-
},
|
99
|
-
};
|
100
|
-
if (isPassive)
|
101
|
-
samlReq['samlp:AuthnRequest']['@IsPassive'] = true;
|
102
|
-
if (forceAuthn) {
|
103
|
-
samlReq['samlp:AuthnRequest']['@ForceAuthn'] = true;
|
104
|
-
}
|
105
|
-
samlReq['samlp:AuthnRequest']['@AssertionConsumerServiceURL'] = callbackUrl;
|
106
|
-
samlReq['samlp:AuthnRequest']['samlp:NameIDPolicy'] = {
|
107
|
-
'@xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol',
|
108
|
-
'@Format': identifierFormat,
|
109
|
-
'@AllowCreate': 'true',
|
110
|
-
};
|
111
|
-
if (providerName != null) {
|
112
|
-
samlReq['samlp:AuthnRequest']['@ProviderName'] = providerName;
|
113
|
-
}
|
114
|
-
let xml = xmlbuilder_1.default.create(samlReq).end({});
|
115
|
-
if (signingKey) {
|
116
|
-
xml = signRequest(xml, signingKey, publicKey);
|
117
|
-
}
|
118
|
-
return {
|
119
|
-
id,
|
120
|
-
request: xml,
|
121
|
-
};
|
122
|
-
};
|
123
|
-
const parseAsync = (rawAssertion) => __awaiter(void 0, void 0, void 0, function* () {
|
124
|
-
return new Promise((resolve, reject) => {
|
125
|
-
saml20_1.default.parse(rawAssertion, function onParseAsync(err, profile) {
|
126
|
-
if (err) {
|
127
|
-
reject(err);
|
128
|
-
return;
|
129
|
-
}
|
130
|
-
resolve(profile);
|
131
|
-
});
|
132
|
-
});
|
133
|
-
});
|
134
|
-
const validateAsync = (rawAssertion, options) => __awaiter(void 0, void 0, void 0, function* () {
|
135
|
-
return new Promise((resolve, reject) => {
|
136
|
-
saml20_1.default.validate(rawAssertion, options, function onValidateAsync(err, profile) {
|
137
|
-
if (err) {
|
138
|
-
reject(err);
|
139
|
-
return;
|
140
|
-
}
|
141
|
-
if (profile && profile.claims) {
|
142
|
-
// we map claims to our attributes id, email, firstName, lastName where possible. We also map original claims to raw
|
143
|
-
profile.claims = claims_1.default.map(profile.claims);
|
144
|
-
// some providers don't return the id in the assertion, we set it to a sha256 hash of the email
|
145
|
-
if (!profile.claims.id) {
|
146
|
-
profile.claims.id = crypto_1.default.createHash('sha256').update(profile.claims.email).digest('hex');
|
147
|
-
}
|
148
|
-
}
|
149
|
-
resolve(profile);
|
150
|
-
});
|
151
|
-
});
|
152
|
-
});
|
153
|
-
const parseMetadataAsync = (idpMeta) => __awaiter(void 0, void 0, void 0, function* () {
|
154
|
-
return new Promise((resolve, reject) => {
|
155
|
-
xml2js_1.default.parseString(idpMeta, { tagNameProcessors: [xml2js_1.default.processors.stripPrefix] }, (err, res) => {
|
156
|
-
if (err) {
|
157
|
-
reject(err);
|
158
|
-
return;
|
159
|
-
}
|
160
|
-
const entityID = rambda.path('EntityDescriptor.$.entityID', res);
|
161
|
-
let X509Certificate = null;
|
162
|
-
let ssoPostUrl = null;
|
163
|
-
let ssoRedirectUrl = null;
|
164
|
-
let loginType = 'idp';
|
165
|
-
let ssoDes = rambda.pathOr(null, 'EntityDescriptor.IDPSSODescriptor', res);
|
166
|
-
if (!ssoDes) {
|
167
|
-
ssoDes = rambda.pathOr([], 'EntityDescriptor.SPSSODescriptor', res);
|
168
|
-
if (!ssoDes) {
|
169
|
-
loginType = 'sp';
|
170
|
-
}
|
171
|
-
}
|
172
|
-
for (const ssoDesRec of ssoDes) {
|
173
|
-
const keyDes = ssoDesRec['KeyDescriptor'];
|
174
|
-
for (const keyDesRec of keyDes) {
|
175
|
-
if (keyDesRec['$'] && keyDesRec['$'].use === 'signing') {
|
176
|
-
const ki = keyDesRec['KeyInfo'][0];
|
177
|
-
const cd = ki['X509Data'][0];
|
178
|
-
X509Certificate = cd['X509Certificate'][0];
|
179
|
-
}
|
180
|
-
}
|
181
|
-
const ssoSvc = ssoDesRec['SingleSignOnService'] || ssoDesRec['AssertionConsumerService'] || [];
|
182
|
-
for (const ssoSvcRec of ssoSvc) {
|
183
|
-
if (rambda.pathOr('', '$.Binding', ssoSvcRec).endsWith('HTTP-POST')) {
|
184
|
-
ssoPostUrl = rambda.path('$.Location', ssoSvcRec);
|
185
|
-
}
|
186
|
-
else if (rambda.pathOr('', '$.Binding', ssoSvcRec).endsWith('HTTP-Redirect')) {
|
187
|
-
ssoRedirectUrl = rambda.path('$.Location', ssoSvcRec);
|
188
|
-
}
|
189
|
-
}
|
190
|
-
}
|
191
|
-
const ret = {
|
192
|
-
sso: {},
|
193
|
-
};
|
194
|
-
if (entityID) {
|
195
|
-
ret.entityID = entityID;
|
196
|
-
}
|
197
|
-
if (X509Certificate) {
|
198
|
-
ret.thumbprint = thumbprint_1.default.calculate(X509Certificate);
|
199
|
-
}
|
200
|
-
if (ssoPostUrl) {
|
201
|
-
ret.sso.postUrl = ssoPostUrl;
|
202
|
-
}
|
203
|
-
if (ssoRedirectUrl) {
|
204
|
-
ret.sso.redirectUrl = ssoRedirectUrl;
|
205
|
-
}
|
206
|
-
ret.loginType = loginType;
|
207
|
-
resolve(ret);
|
208
|
-
});
|
209
|
-
});
|
210
|
-
});
|
211
|
-
exports.default = { request, parseAsync, validateAsync, parseMetadataAsync };
|