UNPKG

n8n

Version:

n8n Workflow Automation Tool

146 lines 6.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isSamlPreferences = void 0; exports.setSamlLoginEnabled = setSamlLoginEnabled; exports.setSamlLoginLabel = setSamlLoginLabel; exports.createUserFromSamlAttributes = createUserFromSamlAttributes; exports.updateUserFromSamlAttributes = updateUserFromSamlAttributes; exports.getMappedSamlAttributesFromFlowResult = getMappedSamlAttributesFromFlowResult; exports.isConnectionTestRequest = isConnectionTestRequest; exports.extractTestIdFromRelayState = extractTestIdFromRelayState; const config_1 = require("@n8n/config"); const db_1 = require("@n8n/db"); const di_1 = require("@n8n/di"); const n8n_workflow_1 = require("n8n-workflow"); const auth_error_1 = require("../../errors/response-errors/auth.error"); const internal_server_error_1 = require("../../errors/response-errors/internal-server.error"); const password_utility_1 = require("../../services/password.utility"); const sso_helpers_1 = require("../../sso.ee/sso-helpers"); const service_provider_ee_1 = require("./service-provider.ee"); async function setSamlLoginEnabled(enabled) { const currentAuthenticationMethod = (0, sso_helpers_1.getCurrentAuthenticationMethod)(); if (enabled && !(0, sso_helpers_1.isEmailCurrentAuthenticationMethod)() && !(0, sso_helpers_1.isSamlCurrentAuthenticationMethod)()) { throw new internal_server_error_1.InternalServerError(`Cannot switch SAML login enabled state when an authentication method other than email or saml is active (current: ${currentAuthenticationMethod})`); } const targetAuthenticationMethod = !enabled && currentAuthenticationMethod === 'saml' ? 'email' : currentAuthenticationMethod; di_1.Container.get(config_1.GlobalConfig).sso.saml.loginEnabled = enabled; await (0, sso_helpers_1.setCurrentAuthenticationMethod)(enabled ? 'saml' : targetAuthenticationMethod); } function setSamlLoginLabel(label) { di_1.Container.get(config_1.GlobalConfig).sso.saml.loginLabel = label; } const isSamlPreferences = (candidate) => { const o = candidate; return (typeof o === 'object' && typeof o.metadata === 'string' && typeof o.mapping === 'object' && o.mapping !== null && o.loginEnabled !== undefined); }; exports.isSamlPreferences = isSamlPreferences; async function createUserFromSamlAttributes(attributes) { const randomPassword = (0, n8n_workflow_1.randomString)(18); const userRepository = di_1.Container.get(db_1.UserRepository); return await userRepository.manager.transaction(async (trx) => { const { user } = await userRepository.createUserWithProject({ email: attributes.email.toLowerCase(), firstName: attributes.firstName, lastName: attributes.lastName, role: { slug: 'global:member' }, password: await di_1.Container.get(password_utility_1.PasswordUtility).hash(randomPassword), }, trx); await trx.save(trx.create(db_1.AuthIdentity, { providerId: attributes.userPrincipalName, providerType: 'saml', userId: user.id, })); return user; }); } async function updateUserFromSamlAttributes(user, attributes) { if (!attributes.email) throw new auth_error_1.AuthError('Email is required to update user'); if (!user) throw new auth_error_1.AuthError('User not found'); let samlAuthIdentity = user?.authIdentities.find((e) => e.providerType === 'saml'); if (!samlAuthIdentity) { samlAuthIdentity = new db_1.AuthIdentity(); samlAuthIdentity.providerId = attributes.userPrincipalName; samlAuthIdentity.providerType = 'saml'; samlAuthIdentity.user = user; user.authIdentities.push(samlAuthIdentity); } else { samlAuthIdentity.providerId = attributes.userPrincipalName; } await di_1.Container.get(db_1.AuthIdentityRepository).save(samlAuthIdentity, { transaction: false }); user.firstName = attributes.firstName; user.lastName = attributes.lastName; const resultUser = await di_1.Container.get(db_1.UserRepository).save(user, { transaction: false }); if (!resultUser) throw new auth_error_1.AuthError('Could not update User'); const userWithRole = await di_1.Container.get(db_1.UserRepository).findOne({ where: { id: resultUser.id }, relations: ['role'], transaction: false, }); if (!userWithRole) throw new auth_error_1.AuthError('Failed to fetch user!'); return userWithRole; } function getMappedSamlAttributesFromFlowResult(flowResult, attributeMapping, jitClaimNames) { const result = { attributes: undefined, missingAttributes: [], rawAttributes: {}, }; if (flowResult?.extract?.attributes) { const attributes = flowResult.extract.attributes; result.rawAttributes = attributes; const email = attributes[attributeMapping.email]; const firstName = attributes[attributeMapping.firstName]; const lastName = attributes[attributeMapping.lastName]; const userPrincipalName = attributes[attributeMapping.userPrincipalName]; result.attributes = { email, firstName, lastName, userPrincipalName, }; if (jitClaimNames.instanceRole && typeof attributes[jitClaimNames.instanceRole] === 'string') { result.attributes.n8nInstanceRole = attributes[jitClaimNames.instanceRole]; } if (jitClaimNames.projectRoles && attributes[jitClaimNames.projectRoles]) { const projectRolesFromFlowResult = attributes[jitClaimNames.projectRoles]; result.attributes.n8nProjectRoles = Array.isArray(projectRolesFromFlowResult) ? projectRolesFromFlowResult : [projectRolesFromFlowResult]; } if (!email) result.missingAttributes.push(attributeMapping.email); if (!userPrincipalName) result.missingAttributes.push(attributeMapping.userPrincipalName); if (!firstName) result.missingAttributes.push(attributeMapping.firstName); if (!lastName) result.missingAttributes.push(attributeMapping.lastName); } return result; } function isConnectionTestRequest(payload) { if (!payload.RelayState) return false; return payload.RelayState.startsWith((0, service_provider_ee_1.getServiceProviderConfigTestReturnUrl)()); } function extractTestIdFromRelayState(relayState) { if (!relayState) return undefined; try { const url = new URL(relayState); return url.searchParams.get('t') ?? undefined; } catch { return undefined; } } //# sourceMappingURL=saml-helpers.js.map