mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
fix(core): Load SAML libraries dynamically (#6690)
load SAML dynamically
This commit is contained in:
parent
667c15d0df
commit
fce5609fa3
|
@ -184,7 +184,7 @@ export class SamlController {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleInitSSO(res: express.Response, relayState?: string) {
|
private async handleInitSSO(res: express.Response, relayState?: string) {
|
||||||
const result = this.samlService.getLoginRequestUrl(relayState);
|
const result = await this.samlService.getLoginRequestUrl(relayState);
|
||||||
if (result?.binding === 'redirect') {
|
if (result?.binding === 'redirect') {
|
||||||
return result.context.context;
|
return result.context.context;
|
||||||
} else if (result?.binding === 'post') {
|
} else if (result?.binding === 'post') {
|
||||||
|
|
|
@ -10,11 +10,12 @@ import { isSsoJustInTimeProvisioningEnabled } from '../ssoHelpers';
|
||||||
import type { SamlPreferences } from './types/samlPreferences';
|
import type { SamlPreferences } from './types/samlPreferences';
|
||||||
import { SAML_PREFERENCES_DB_KEY } from './constants';
|
import { SAML_PREFERENCES_DB_KEY } from './constants';
|
||||||
import type { IdentityProviderInstance, ServiceProviderInstance } from 'samlify';
|
import type { IdentityProviderInstance, ServiceProviderInstance } from 'samlify';
|
||||||
import { IdentityProvider, setSchemaValidator } from 'samlify';
|
import type { BindingContext, PostBindingContext } from 'samlify/types/src/entity';
|
||||||
import {
|
import {
|
||||||
createUserFromSamlAttributes,
|
createUserFromSamlAttributes,
|
||||||
getMappedSamlAttributesFromFlowResult,
|
getMappedSamlAttributesFromFlowResult,
|
||||||
getSamlLoginLabel,
|
getSamlLoginLabel,
|
||||||
|
isSamlLicensedAndEnabled,
|
||||||
isSamlLoginEnabled,
|
isSamlLoginEnabled,
|
||||||
setSamlLoginEnabled,
|
setSamlLoginEnabled,
|
||||||
setSamlLoginLabel,
|
setSamlLoginLabel,
|
||||||
|
@ -24,7 +25,6 @@ import type { Settings } from '@db/entities/Settings';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import https from 'https';
|
import https from 'https';
|
||||||
import type { SamlLoginBinding } from './types';
|
import type { SamlLoginBinding } from './types';
|
||||||
import type { BindingContext, PostBindingContext } from 'samlify/types/src/entity';
|
|
||||||
import { validateMetadata, validateResponse } from './samlValidator';
|
import { validateMetadata, validateResponse } from './samlValidator';
|
||||||
import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper';
|
import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper';
|
||||||
|
|
||||||
|
@ -32,6 +32,9 @@ import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper';
|
||||||
export class SamlService {
|
export class SamlService {
|
||||||
private identityProviderInstance: IdentityProviderInstance | undefined;
|
private identityProviderInstance: IdentityProviderInstance | undefined;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
||||||
|
private samlify: typeof import('samlify') | undefined;
|
||||||
|
|
||||||
private _samlPreferences: SamlPreferences = {
|
private _samlPreferences: SamlPreferences = {
|
||||||
mapping: {
|
mapping: {
|
||||||
email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress',
|
email: 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress',
|
||||||
|
@ -68,8 +71,20 @@ export class SamlService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async init(): Promise<void> {
|
async init(): Promise<void> {
|
||||||
await this.loadFromDbAndApplySamlPreferences();
|
// load preferences first but do not apply so as to not load samlify unnecessarily
|
||||||
setSchemaValidator({
|
await this.loadFromDbAndApplySamlPreferences(false);
|
||||||
|
if (isSamlLicensedAndEnabled()) {
|
||||||
|
await this.loadSamlify();
|
||||||
|
await this.loadFromDbAndApplySamlPreferences(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadSamlify() {
|
||||||
|
if (this.samlify === undefined) {
|
||||||
|
LoggerProxy.debug('Loading samlify library into memory');
|
||||||
|
this.samlify = await import('samlify');
|
||||||
|
}
|
||||||
|
this.samlify.setSchemaValidator({
|
||||||
validate: async (response: string) => {
|
validate: async (response: string) => {
|
||||||
const valid = await validateResponse(response);
|
const valid = await validateResponse(response);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
|
@ -80,8 +95,11 @@ export class SamlService {
|
||||||
}
|
}
|
||||||
|
|
||||||
getIdentityProviderInstance(forceRecreate = false): IdentityProviderInstance {
|
getIdentityProviderInstance(forceRecreate = false): IdentityProviderInstance {
|
||||||
|
if (this.samlify === undefined) {
|
||||||
|
throw new Error('Samlify is not initialized');
|
||||||
|
}
|
||||||
if (this.identityProviderInstance === undefined || forceRecreate) {
|
if (this.identityProviderInstance === undefined || forceRecreate) {
|
||||||
this.identityProviderInstance = IdentityProvider({
|
this.identityProviderInstance = this.samlify.IdentityProvider({
|
||||||
metadata: this._samlPreferences.metadata,
|
metadata: this._samlPreferences.metadata,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -90,16 +108,20 @@ export class SamlService {
|
||||||
}
|
}
|
||||||
|
|
||||||
getServiceProviderInstance(): ServiceProviderInstance {
|
getServiceProviderInstance(): ServiceProviderInstance {
|
||||||
return getServiceProviderInstance(this._samlPreferences);
|
if (this.samlify === undefined) {
|
||||||
|
throw new Error('Samlify is not initialized');
|
||||||
|
}
|
||||||
|
return getServiceProviderInstance(this._samlPreferences, this.samlify);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLoginRequestUrl(
|
async getLoginRequestUrl(
|
||||||
relayState?: string,
|
relayState?: string,
|
||||||
binding?: SamlLoginBinding,
|
binding?: SamlLoginBinding,
|
||||||
): {
|
): Promise<{
|
||||||
binding: SamlLoginBinding;
|
binding: SamlLoginBinding;
|
||||||
context: BindingContext | PostBindingContext;
|
context: BindingContext | PostBindingContext;
|
||||||
} {
|
}> {
|
||||||
|
await this.loadSamlify();
|
||||||
if (binding === undefined) binding = this._samlPreferences.loginBinding ?? 'redirect';
|
if (binding === undefined) binding = this._samlPreferences.loginBinding ?? 'redirect';
|
||||||
if (binding === 'post') {
|
if (binding === 'post') {
|
||||||
return {
|
return {
|
||||||
|
@ -192,6 +214,25 @@ export class SamlService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async setSamlPreferences(prefs: SamlPreferences): Promise<SamlPreferences | undefined> {
|
async setSamlPreferences(prefs: SamlPreferences): Promise<SamlPreferences | undefined> {
|
||||||
|
await this.loadSamlify();
|
||||||
|
await this.loadPreferencesWithoutValidation(prefs);
|
||||||
|
if (prefs.metadataUrl) {
|
||||||
|
const fetchedMetadata = await this.fetchMetadataFromUrl();
|
||||||
|
if (fetchedMetadata) {
|
||||||
|
this._samlPreferences.metadata = fetchedMetadata;
|
||||||
|
}
|
||||||
|
} else if (prefs.metadata) {
|
||||||
|
const validationResult = await validateMetadata(prefs.metadata);
|
||||||
|
if (!validationResult) {
|
||||||
|
throw new Error('Invalid SAML metadata');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.getIdentityProviderInstance(true);
|
||||||
|
const result = await this.saveSamlPreferencesToDb();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadPreferencesWithoutValidation(prefs: SamlPreferences) {
|
||||||
this._samlPreferences.loginBinding = prefs.loginBinding ?? this._samlPreferences.loginBinding;
|
this._samlPreferences.loginBinding = prefs.loginBinding ?? this._samlPreferences.loginBinding;
|
||||||
this._samlPreferences.metadata = prefs.metadata ?? this._samlPreferences.metadata;
|
this._samlPreferences.metadata = prefs.metadata ?? this._samlPreferences.metadata;
|
||||||
this._samlPreferences.mapping = prefs.mapping ?? this._samlPreferences.mapping;
|
this._samlPreferences.mapping = prefs.mapping ?? this._samlPreferences.mapping;
|
||||||
|
@ -207,34 +248,27 @@ export class SamlService {
|
||||||
prefs.wantMessageSigned ?? this._samlPreferences.wantMessageSigned;
|
prefs.wantMessageSigned ?? this._samlPreferences.wantMessageSigned;
|
||||||
if (prefs.metadataUrl) {
|
if (prefs.metadataUrl) {
|
||||||
this._samlPreferences.metadataUrl = prefs.metadataUrl;
|
this._samlPreferences.metadataUrl = prefs.metadataUrl;
|
||||||
const fetchedMetadata = await this.fetchMetadataFromUrl();
|
|
||||||
if (fetchedMetadata) {
|
|
||||||
this._samlPreferences.metadata = fetchedMetadata;
|
|
||||||
}
|
|
||||||
} else if (prefs.metadata) {
|
} else if (prefs.metadata) {
|
||||||
// remove metadataUrl if metadata is set directly
|
// remove metadataUrl if metadata is set directly
|
||||||
this._samlPreferences.metadataUrl = undefined;
|
this._samlPreferences.metadataUrl = undefined;
|
||||||
const validationResult = await validateMetadata(prefs.metadata);
|
|
||||||
if (!validationResult) {
|
|
||||||
throw new Error('Invalid SAML metadata');
|
|
||||||
}
|
|
||||||
this._samlPreferences.metadata = prefs.metadata;
|
this._samlPreferences.metadata = prefs.metadata;
|
||||||
}
|
}
|
||||||
await setSamlLoginEnabled(prefs.loginEnabled ?? isSamlLoginEnabled());
|
await setSamlLoginEnabled(prefs.loginEnabled ?? isSamlLoginEnabled());
|
||||||
setSamlLoginLabel(prefs.loginLabel ?? getSamlLoginLabel());
|
setSamlLoginLabel(prefs.loginLabel ?? getSamlLoginLabel());
|
||||||
this.getIdentityProviderInstance(true);
|
|
||||||
const result = await this.saveSamlPreferencesToDb();
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadFromDbAndApplySamlPreferences(): Promise<SamlPreferences | undefined> {
|
async loadFromDbAndApplySamlPreferences(apply = true): Promise<SamlPreferences | undefined> {
|
||||||
const samlPreferences = await Db.collections.Settings.findOne({
|
const samlPreferences = await Db.collections.Settings.findOne({
|
||||||
where: { key: SAML_PREFERENCES_DB_KEY },
|
where: { key: SAML_PREFERENCES_DB_KEY },
|
||||||
});
|
});
|
||||||
if (samlPreferences) {
|
if (samlPreferences) {
|
||||||
const prefs = jsonParse<SamlPreferences>(samlPreferences.value);
|
const prefs = jsonParse<SamlPreferences>(samlPreferences.value);
|
||||||
if (prefs) {
|
if (prefs) {
|
||||||
await this.setSamlPreferences(prefs);
|
if (apply) {
|
||||||
|
await this.setSamlPreferences(prefs);
|
||||||
|
} else {
|
||||||
|
await this.loadPreferencesWithoutValidation(prefs);
|
||||||
|
}
|
||||||
return prefs;
|
return prefs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,6 +296,7 @@ export class SamlService {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchMetadataFromUrl(): Promise<string | undefined> {
|
async fetchMetadataFromUrl(): Promise<string | undefined> {
|
||||||
|
await this.loadSamlify();
|
||||||
if (!this._samlPreferences.metadataUrl)
|
if (!this._samlPreferences.metadataUrl)
|
||||||
throw new BadRequestError('Error fetching SAML Metadata, no Metadata URL set');
|
throw new BadRequestError('Error fetching SAML Metadata, no Metadata URL set');
|
||||||
try {
|
try {
|
||||||
|
@ -297,6 +332,7 @@ export class SamlService {
|
||||||
if (!this._samlPreferences.mapping)
|
if (!this._samlPreferences.mapping)
|
||||||
throw new BadRequestError('Error fetching SAML Attributes, no Attribute mapping set');
|
throw new BadRequestError('Error fetching SAML Attributes, no Attribute mapping set');
|
||||||
try {
|
try {
|
||||||
|
await this.loadSamlify();
|
||||||
parsedSamlResponse = await this.getServiceProviderInstance().parseLoginResponse(
|
parsedSamlResponse = await this.getServiceProviderInstance().parseLoginResponse(
|
||||||
this.getIdentityProviderInstance(),
|
this.getIdentityProviderInstance(),
|
||||||
binding,
|
binding,
|
||||||
|
@ -324,46 +360,4 @@ export class SamlService {
|
||||||
}
|
}
|
||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
async testSamlConnection(): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
// TODO:SAML: this will not work once axios is upgraded to > 1.2.0 (see checkServerIdentity)
|
|
||||||
const agent = new https.Agent({
|
|
||||||
rejectUnauthorized: !this._samlPreferences.ignoreSSL,
|
|
||||||
});
|
|
||||||
const requestContext = this.getLoginRequestUrl();
|
|
||||||
if (!requestContext) return false;
|
|
||||||
if (requestContext.binding === 'redirect') {
|
|
||||||
const fetchResult = await axios.get(requestContext.context.context, { httpsAgent: agent });
|
|
||||||
if (fetchResult.status !== 200) {
|
|
||||||
LoggerProxy.debug('SAML: Error while testing SAML connection.');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} else if (requestContext.binding === 'post') {
|
|
||||||
const context = requestContext.context as PostBindingContext;
|
|
||||||
const endpoint = context.entityEndpoint;
|
|
||||||
const params = new URLSearchParams();
|
|
||||||
params.append(context.type, context.context);
|
|
||||||
if (context.relayState) {
|
|
||||||
params.append('RelayState', context.relayState);
|
|
||||||
}
|
|
||||||
const fetchResult = await axios.post(endpoint, params, {
|
|
||||||
headers: {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
||||||
'Content-type': 'application/x-www-form-urlencoded',
|
|
||||||
},
|
|
||||||
httpsAgent: agent,
|
|
||||||
});
|
|
||||||
if (fetchResult.status !== 200) {
|
|
||||||
LoggerProxy.debug('SAML: Error while testing SAML connection.');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} catch (error) {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
||||||
LoggerProxy.debug('SAML: Error while testing SAML connection: ', error);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +1,76 @@
|
||||||
import { LoggerProxy } from 'n8n-workflow';
|
import { LoggerProxy } from 'n8n-workflow';
|
||||||
import type { XMLFileInfo } from 'xmllint-wasm';
|
import type { XMLFileInfo } from 'xmllint-wasm';
|
||||||
import { validateXML } from 'xmllint-wasm';
|
|
||||||
import { xsdSamlSchemaAssertion20 } from './schema/saml-schema-assertion-2.0.xsd';
|
|
||||||
import { xsdSamlSchemaMetadata20 } from './schema/saml-schema-metadata-2.0.xsd';
|
|
||||||
import { xsdSamlSchemaProtocol20 } from './schema/saml-schema-protocol-2.0.xsd';
|
|
||||||
import { xsdXenc } from './schema/xenc-schema.xsd';
|
|
||||||
import { xsdXml } from './schema/xml.xsd';
|
|
||||||
import { xsdXmldsigCore } from './schema/xmldsig-core-schema.xsd';
|
|
||||||
|
|
||||||
const xml: XMLFileInfo = {
|
let xml: XMLFileInfo;
|
||||||
fileName: 'xml.xsd',
|
let xmldsigCore: XMLFileInfo;
|
||||||
contents: xsdXml,
|
let xmlXenc: XMLFileInfo;
|
||||||
};
|
let xmlMetadata: XMLFileInfo;
|
||||||
|
let xmlAssertion: XMLFileInfo;
|
||||||
|
let xmlProtocol: XMLFileInfo;
|
||||||
|
|
||||||
const xmldsigCore: XMLFileInfo = {
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
||||||
fileName: 'xmldsig-core-schema.xsd',
|
let xmllintWasm: typeof import('xmllint-wasm') | undefined;
|
||||||
contents: xsdXmldsigCore,
|
|
||||||
};
|
|
||||||
|
|
||||||
const xmlXenc: XMLFileInfo = {
|
// dynamically load schema files
|
||||||
fileName: 'xenc-schema.xsd',
|
async function loadSchemas(): Promise<void> {
|
||||||
contents: xsdXenc,
|
if (!xml || xml.contents === '') {
|
||||||
};
|
LoggerProxy.debug('Loading XML schema files for SAML validation into memory');
|
||||||
|
const f = await import('./schema/xml.xsd');
|
||||||
|
xml = {
|
||||||
|
fileName: 'xml.xsd',
|
||||||
|
contents: f.xsdXml,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!xmldsigCore || xmldsigCore.contents === '') {
|
||||||
|
const f = await import('./schema/xmldsig-core-schema.xsd');
|
||||||
|
xmldsigCore = {
|
||||||
|
fileName: 'xmldsig-core-schema.xsd',
|
||||||
|
contents: f.xsdXmldsigCore,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!xmlXenc || xmlXenc.contents === '') {
|
||||||
|
const f = await import('./schema/xenc-schema.xsd');
|
||||||
|
xmlXenc = {
|
||||||
|
fileName: 'xenc-schema.xsd',
|
||||||
|
contents: f.xsdXenc,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!xmlMetadata || xmlMetadata.contents === '') {
|
||||||
|
const f = await import('./schema/saml-schema-metadata-2.0.xsd');
|
||||||
|
xmlMetadata = {
|
||||||
|
fileName: 'saml-schema-metadata-2.0.xsd',
|
||||||
|
contents: f.xsdSamlSchemaMetadata20,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!xmlAssertion || xmlAssertion.contents === '') {
|
||||||
|
const f = await import('./schema/saml-schema-assertion-2.0.xsd');
|
||||||
|
xmlAssertion = {
|
||||||
|
fileName: 'saml-schema-assertion-2.0.xsd',
|
||||||
|
contents: f.xsdSamlSchemaAssertion20,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!xmlProtocol || xmlProtocol.contents === '') {
|
||||||
|
const f = await import('./schema/saml-schema-protocol-2.0.xsd');
|
||||||
|
xmlProtocol = {
|
||||||
|
fileName: 'saml-schema-protocol-2.0.xsd',
|
||||||
|
contents: f.xsdSamlSchemaProtocol20,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const xmlMetadata: XMLFileInfo = {
|
// dynamically load xmllint-wasm
|
||||||
fileName: 'saml-schema-metadata-2.0.xsd',
|
async function loadXmllintWasm(): Promise<void> {
|
||||||
contents: xsdSamlSchemaMetadata20,
|
if (xmllintWasm === undefined) {
|
||||||
};
|
LoggerProxy.debug('Loading xmllint-wasm library into memory');
|
||||||
|
xmllintWasm = await import('xmllint-wasm');
|
||||||
const xmlAssertion: XMLFileInfo = {
|
}
|
||||||
fileName: 'saml-schema-assertion-2.0.xsd',
|
}
|
||||||
contents: xsdSamlSchemaAssertion20,
|
|
||||||
};
|
|
||||||
|
|
||||||
const xmlProtocol: XMLFileInfo = {
|
|
||||||
fileName: 'saml-schema-protocol-2.0.xsd',
|
|
||||||
contents: xsdSamlSchemaProtocol20,
|
|
||||||
};
|
|
||||||
|
|
||||||
export async function validateMetadata(metadata: string): Promise<boolean> {
|
export async function validateMetadata(metadata: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const validationResult = await validateXML({
|
await loadXmllintWasm();
|
||||||
|
await loadSchemas();
|
||||||
|
const validationResult = await xmllintWasm?.validateXML({
|
||||||
xml: [
|
xml: [
|
||||||
{
|
{
|
||||||
fileName: 'metadata.xml',
|
fileName: 'metadata.xml',
|
||||||
|
@ -51,12 +81,12 @@ export async function validateMetadata(metadata: string): Promise<boolean> {
|
||||||
schema: [xmlMetadata],
|
schema: [xmlMetadata],
|
||||||
preload: [xmlProtocol, xmlAssertion, xmldsigCore, xmlXenc, xml],
|
preload: [xmlProtocol, xmlAssertion, xmldsigCore, xmlXenc, xml],
|
||||||
});
|
});
|
||||||
if (validationResult.valid) {
|
if (validationResult?.valid) {
|
||||||
LoggerProxy.debug('SAML Metadata is valid');
|
LoggerProxy.debug('SAML Metadata is valid');
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
LoggerProxy.warn('SAML Validate Metadata: Invalid metadata');
|
LoggerProxy.warn('SAML Validate Metadata: Invalid metadata');
|
||||||
LoggerProxy.warn(validationResult.errors.join('\n'));
|
LoggerProxy.warn(validationResult ? validationResult.errors.join('\n') : '');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||||
|
@ -67,7 +97,9 @@ export async function validateMetadata(metadata: string): Promise<boolean> {
|
||||||
|
|
||||||
export async function validateResponse(response: string): Promise<boolean> {
|
export async function validateResponse(response: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const validationResult = await validateXML({
|
await loadXmllintWasm();
|
||||||
|
await loadSchemas();
|
||||||
|
const validationResult = await xmllintWasm?.validateXML({
|
||||||
xml: [
|
xml: [
|
||||||
{
|
{
|
||||||
fileName: 'response.xml',
|
fileName: 'response.xml',
|
||||||
|
@ -78,12 +110,12 @@ export async function validateResponse(response: string): Promise<boolean> {
|
||||||
schema: [xmlProtocol],
|
schema: [xmlProtocol],
|
||||||
preload: [xmlMetadata, xmlAssertion, xmldsigCore, xmlXenc, xml],
|
preload: [xmlMetadata, xmlAssertion, xmldsigCore, xmlXenc, xml],
|
||||||
});
|
});
|
||||||
if (validationResult.valid) {
|
if (validationResult?.valid) {
|
||||||
LoggerProxy.debug('SAML Response is valid');
|
LoggerProxy.debug('SAML Response is valid');
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
LoggerProxy.warn('SAML Validate Response: Failed');
|
LoggerProxy.warn('SAML Validate Response: Failed');
|
||||||
LoggerProxy.warn(validationResult.errors.join('\n'));
|
LoggerProxy.warn(validationResult ? validationResult.errors.join('\n') : '');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper';
|
import { getInstanceBaseUrl } from '@/UserManagement/UserManagementHelper';
|
||||||
import type { ServiceProviderInstance } from 'samlify';
|
import type { ServiceProviderInstance } from 'samlify';
|
||||||
import { ServiceProvider } from 'samlify';
|
|
||||||
import { SamlUrls } from './constants';
|
import { SamlUrls } from './constants';
|
||||||
import type { SamlPreferences } from './types/samlPreferences';
|
import type { SamlPreferences } from './types/samlPreferences';
|
||||||
|
|
||||||
|
@ -20,9 +19,13 @@ export function getServiceProviderConfigTestReturnUrl(): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO:SAML: make these configurable for the end user
|
// TODO:SAML: make these configurable for the end user
|
||||||
export function getServiceProviderInstance(prefs: SamlPreferences): ServiceProviderInstance {
|
export function getServiceProviderInstance(
|
||||||
|
prefs: SamlPreferences,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
||||||
|
samlify: typeof import('samlify'),
|
||||||
|
): ServiceProviderInstance {
|
||||||
if (serviceProviderInstance === undefined) {
|
if (serviceProviderInstance === undefined) {
|
||||||
serviceProviderInstance = ServiceProvider({
|
serviceProviderInstance = samlify.ServiceProvider({
|
||||||
entityID: getServiceProviderEntityId(),
|
entityID: getServiceProviderEntityId(),
|
||||||
authnRequestsSigned: prefs.authnRequestsSigned,
|
authnRequestsSigned: prefs.authnRequestsSigned,
|
||||||
wantAssertionsSigned: prefs.wantAssertionsSigned,
|
wantAssertionsSigned: prefs.wantAssertionsSigned,
|
||||||
|
|
Loading…
Reference in a new issue