mirror of https://github.com/boxyhq/jackson.git
parent
ae5df1ff2f
commit
74becab9f2
|
@ -14,7 +14,7 @@
|
|||
"@aws-sdk/util-dynamodb": "3.529.1",
|
||||
"@boxyhq/error-code-mnemonic": "0.1.1",
|
||||
"@boxyhq/metrics": "0.2.6",
|
||||
"@boxyhq/saml20": "1.4.13",
|
||||
"@boxyhq/saml20": "1.4.14",
|
||||
"@googleapis/admin": "15.0.0",
|
||||
"axios": "1.6.7",
|
||||
"encoding": "0.1.13",
|
||||
|
@ -30,8 +30,7 @@
|
|||
"redis": "4.6.13",
|
||||
"reflect-metadata": "0.2.1",
|
||||
"ripemd160": "2.0.2",
|
||||
"typeorm": "0.3.20",
|
||||
"xmlbuilder": "15.1.1"
|
||||
"typeorm": "0.3.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "8.4.1",
|
||||
|
@ -1162,9 +1161,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@boxyhq/saml20": {
|
||||
"version": "1.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@boxyhq/saml20/-/saml20-1.4.13.tgz",
|
||||
"integrity": "sha512-ypj3/0pQqLGJxWtXjAr+sXcCNQz0DnMK00FTb3RUyTxFyksr8gVTO66cd+Qlu3rDzYLSEp+d6PLAGTb4ThTwkA==",
|
||||
"version": "1.4.14",
|
||||
"resolved": "https://registry.npmjs.org/@boxyhq/saml20/-/saml20-1.4.14.tgz",
|
||||
"integrity": "sha512-aLoCe6MTxoA65GXAXCZ+2bmZbb+9OZVUp7w0VbWlpFTcQpBOpKjkFnYqEfh3tkPZqDsFgjIESnBYfYDqbtPOvQ==",
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "0.8.10",
|
||||
"xml-crypto": "6.0.0",
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
"@aws-sdk/util-dynamodb": "3.529.1",
|
||||
"@boxyhq/error-code-mnemonic": "0.1.1",
|
||||
"@boxyhq/metrics": "0.2.6",
|
||||
"@boxyhq/saml20": "1.4.13",
|
||||
"@boxyhq/saml20": "1.4.14",
|
||||
"@googleapis/admin": "15.0.0",
|
||||
"axios": "1.6.7",
|
||||
"encoding": "0.1.13",
|
||||
|
@ -60,8 +60,7 @@
|
|||
"redis": "4.6.13",
|
||||
"reflect-metadata": "0.2.1",
|
||||
"ripemd160": "2.0.2",
|
||||
"typeorm": "0.3.20",
|
||||
"xmlbuilder": "15.1.1"
|
||||
"typeorm": "0.3.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "8.4.1",
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import crypto from 'crypto';
|
||||
import { promisify } from 'util';
|
||||
import xmlbuilder from 'xmlbuilder';
|
||||
import { deflateRaw } from 'zlib';
|
||||
import * as dbutils from '../db/utils';
|
||||
|
||||
|
@ -60,7 +59,11 @@ export class LogoutController {
|
|||
throw new JacksonError(`${provider} doesn't support SLO or disabled by IdP.`, 400);
|
||||
}
|
||||
|
||||
const { id, xml } = buildRequestXML(nameId, this.opts.samlAudience!, slo.redirectUrl as string);
|
||||
const { id, xml } = saml.createLogoutRequest({
|
||||
nameId,
|
||||
providerName: this.opts.samlAudience!,
|
||||
sloUrl: slo.redirectUrl as string,
|
||||
});
|
||||
const sessionId = crypto.randomBytes(16).toString('hex');
|
||||
|
||||
let logoutUrl: string | null = null;
|
||||
|
@ -149,34 +152,6 @@ export class LogoutController {
|
|||
}
|
||||
}
|
||||
|
||||
// Create the XML for the SLO Request
|
||||
const buildRequestXML = (nameId: string, providerName: string, sloUrl: string) => {
|
||||
const id = '_' + crypto.randomBytes(10).toString('hex');
|
||||
|
||||
const xml: Record<string, any> = {
|
||||
'samlp:LogoutRequest': {
|
||||
'@xmlns:samlp': 'urn:oasis:names:tc:SAML:2.0:protocol',
|
||||
'@xmlns:saml': 'urn:oasis:names:tc:SAML:2.0:assertion',
|
||||
'@ID': id,
|
||||
'@Version': '2.0',
|
||||
'@IssueInstant': new Date().toISOString(),
|
||||
'@Destination': sloUrl,
|
||||
'saml:Issuer': {
|
||||
'#text': providerName,
|
||||
},
|
||||
'saml:NameID': {
|
||||
'@Format': 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
|
||||
'#text': nameId,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
id,
|
||||
xml: xmlbuilder.create(xml).end({}),
|
||||
};
|
||||
};
|
||||
|
||||
// Sign the XML
|
||||
const signXML = async (xml: string, signingKey: string, publicKey: string): Promise<string> => {
|
||||
return await saml.sign(xml, signingKey, publicKey, logoutXPath);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import type { JacksonOption } from '../typings';
|
||||
|
||||
import saml20 from '@boxyhq/saml20';
|
||||
import xmlbuilder from 'xmlbuilder';
|
||||
import { getDefaultCertificate } from '../saml/x509';
|
||||
|
||||
// Service Provider SSO Configuration
|
||||
|
@ -66,61 +65,7 @@ export class SPSSOConfig {
|
|||
public async toXMLMetadata(encryption = false): Promise<string> {
|
||||
const { entityId, acsUrl, publicKeyString } = await this.get();
|
||||
|
||||
const today = new Date();
|
||||
|
||||
const keyDescriptor: any[] = [
|
||||
{
|
||||
'@use': 'signing',
|
||||
'ds:KeyInfo': {
|
||||
'@xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
'ds:X509Data': {
|
||||
'ds:X509Certificate': {
|
||||
'#text': publicKeyString,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
if (encryption) {
|
||||
keyDescriptor.push({
|
||||
'@use': 'encryption',
|
||||
'ds:KeyInfo': {
|
||||
'@xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
'ds:X509Data': {
|
||||
'ds:X509Certificate': {
|
||||
'#text': publicKeyString,
|
||||
},
|
||||
},
|
||||
},
|
||||
'md:EncryptionMethod': {
|
||||
'@Algorithm': 'http://www.w3.org/2001/04/xmlenc#aes256-cbc',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const nodes = {
|
||||
'md:EntityDescriptor': {
|
||||
'@xmlns:md': 'urn:oasis:names:tc:SAML:2.0:metadata',
|
||||
'@entityID': entityId,
|
||||
'@validUntil': new Date(today.setFullYear(today.getFullYear() + 10)).toISOString(),
|
||||
'md:SPSSODescriptor': {
|
||||
//'@WantAuthnRequestsSigned': true,
|
||||
'@protocolSupportEnumeration': 'urn:oasis:names:tc:SAML:2.0:protocol',
|
||||
'md:KeyDescriptor': keyDescriptor,
|
||||
'md:NameIDFormat': {
|
||||
'#text': 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
|
||||
},
|
||||
'md:AssertionConsumerService': {
|
||||
'@index': 1,
|
||||
'@Binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
|
||||
'@Location': acsUrl,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return xmlbuilder.create(nodes, { encoding: 'UTF-8', standalone: false }).end({ pretty: true });
|
||||
return saml20.createSPMetadataXML({ entityId, acsUrl, publicKeyString, encryption });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import crypto from 'crypto';
|
||||
import saml from '@boxyhq/saml20';
|
||||
|
||||
import type {
|
||||
Storable,
|
||||
JacksonOption,
|
||||
|
@ -8,7 +10,6 @@ import type {
|
|||
AppRequestParams,
|
||||
} from '../../typings';
|
||||
import { fedAppID, clientIDFederatedPrefix } from '../../controller/utils';
|
||||
import { createMetadataXML } from '../../saml/lib';
|
||||
import { JacksonError } from '../../controller/error';
|
||||
import { getDefaultCertificate } from '../../saml/x509';
|
||||
import { IndexNames, validateTenantAndProduct } from '../../controller/utils';
|
||||
|
@ -614,10 +615,11 @@ export class App {
|
|||
const ssoUrl = `${this.opts.externalUrl}/api/federated-saml/sso`;
|
||||
const entityId = `${this.opts.samlAudience}`;
|
||||
|
||||
const xml = await createMetadataXML({
|
||||
const xml = saml.createIdPMetadataXML({
|
||||
entityId,
|
||||
ssoUrl,
|
||||
x509cert: publicKey,
|
||||
wantAuthnRequestsSigned: false,
|
||||
});
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import crypto from 'crypto';
|
||||
import saml from '@boxyhq/saml20';
|
||||
import xmlbuilder from 'xmlbuilder';
|
||||
import * as dbutils from '../db/utils';
|
||||
import claims from '../saml/claims';
|
||||
|
||||
|
@ -27,58 +26,6 @@ export const extractSAMLResponseAttributes = async (
|
|||
return attributes;
|
||||
};
|
||||
|
||||
// Create Metadata XML
|
||||
export const createMetadataXML = async ({
|
||||
ssoUrl,
|
||||
entityId,
|
||||
x509cert,
|
||||
}: {
|
||||
ssoUrl: string;
|
||||
entityId: string;
|
||||
x509cert: string;
|
||||
}): Promise<string> => {
|
||||
x509cert = saml.stripCertHeaderAndFooter(x509cert);
|
||||
|
||||
const today = new Date();
|
||||
const nodes = {
|
||||
'md:EntityDescriptor': {
|
||||
'@xmlns:md': 'urn:oasis:names:tc:SAML:2.0:metadata',
|
||||
'@entityID': entityId,
|
||||
'@validUntil': new Date(today.setFullYear(today.getFullYear() + 10)).toISOString(),
|
||||
'md:IDPSSODescriptor': {
|
||||
'@WantAuthnRequestsSigned': false,
|
||||
'@protocolSupportEnumeration': 'urn:oasis:names:tc:SAML:2.0:protocol',
|
||||
'md:KeyDescriptor': {
|
||||
'@use': 'signing',
|
||||
'ds:KeyInfo': {
|
||||
'@xmlns:ds': 'http://www.w3.org/2000/09/xmldsig#',
|
||||
'ds:X509Data': {
|
||||
'ds:X509Certificate': {
|
||||
'#text': x509cert,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
'md:NameIDFormat': {
|
||||
'#text': 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress',
|
||||
},
|
||||
'md:SingleSignOnService': [
|
||||
{
|
||||
'@Binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
|
||||
'@Location': ssoUrl,
|
||||
},
|
||||
{
|
||||
'@Binding': 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
|
||||
'@Location': ssoUrl,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return xmlbuilder.create(nodes, { encoding: 'UTF-8', standalone: false }).end({ pretty: true });
|
||||
};
|
||||
|
||||
export type ValidateOption = {
|
||||
thumbprint?: string;
|
||||
publicKey?: string;
|
||||
|
|
|
@ -1880,9 +1880,9 @@
|
|||
"link": true
|
||||
},
|
||||
"node_modules/@boxyhq/saml20": {
|
||||
"version": "1.4.13",
|
||||
"resolved": "https://registry.npmjs.org/@boxyhq/saml20/-/saml20-1.4.13.tgz",
|
||||
"integrity": "sha512-ypj3/0pQqLGJxWtXjAr+sXcCNQz0DnMK00FTb3RUyTxFyksr8gVTO66cd+Qlu3rDzYLSEp+d6PLAGTb4ThTwkA==",
|
||||
"version": "1.4.14",
|
||||
"resolved": "https://registry.npmjs.org/@boxyhq/saml20/-/saml20-1.4.14.tgz",
|
||||
"integrity": "sha512-aLoCe6MTxoA65GXAXCZ+2bmZbb+9OZVUp7w0VbWlpFTcQpBOpKjkFnYqEfh3tkPZqDsFgjIESnBYfYDqbtPOvQ==",
|
||||
"dependencies": {
|
||||
"@xmldom/xmldom": "0.8.10",
|
||||
"xml-crypto": "6.0.0",
|
||||
|
@ -23434,7 +23434,7 @@
|
|||
"@aws-sdk/util-dynamodb": "3.528.0",
|
||||
"@boxyhq/error-code-mnemonic": "0.1.1",
|
||||
"@boxyhq/metrics": "0.2.6",
|
||||
"@boxyhq/saml20": "1.4.13",
|
||||
"@boxyhq/saml20": "1.4.14",
|
||||
"@googleapis/admin": "15.0.0",
|
||||
"axios": "1.6.7",
|
||||
"encoding": "0.1.13",
|
||||
|
@ -23450,8 +23450,7 @@
|
|||
"redis": "4.6.13",
|
||||
"reflect-metadata": "0.2.1",
|
||||
"ripemd160": "2.0.2",
|
||||
"typeorm": "0.3.20",
|
||||
"xmlbuilder": "15.1.1"
|
||||
"typeorm": "0.3.20"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "8.4.1",
|
||||
|
|
Loading…
Reference in New Issue