updated saml20 (#2410)

* updated saml20

* updated saml20
This commit is contained in:
Deepak Prabhakara 2024-03-08 13:34:02 +00:00 committed by GitHub
parent ae5df1ff2f
commit 74becab9f2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 22 additions and 156 deletions

11
npm/package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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);

View File

@ -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 });
}
}

View File

@ -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 {

View File

@ -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;

11
package-lock.json generated
View File

@ -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",