feat(core): Add OIDC support for SSO (#15988)

Co-authored-by: Andreas Fitzek <andreas.fitzek@n8n.io>
This commit is contained in:
Ricardo Espinoza
2025-06-13 16:18:14 +02:00
committed by GitHub
co-authored by Andreas Fitzek
parent 0d5ac1f822
commit 30148df7f3
40 changed files with 1358 additions and 197 deletions
@@ -105,6 +105,7 @@ export class E2EController {
[LICENSE_FEATURES.INSIGHTS_VIEW_DASHBOARD]: false,
[LICENSE_FEATURES.INSIGHTS_VIEW_HOURLY_DATA]: false,
[LICENSE_FEATURES.API_KEY_SCOPES]: false,
[LICENSE_FEATURES.OIDC]: false,
};
private static readonly numericFeaturesDefaults: Record<NumericLicenseFeature, number> = {
+31 -2
View File
@@ -22,6 +22,11 @@ import { AuthenticatedRequest, MeRequest } from '@/requests';
import { PasswordUtility } from '@/services/password.utility';
import { UserService } from '@/services/user.service';
import { isSamlLicensedAndEnabled } from '@/sso.ee/saml/saml-helpers';
import {
getCurrentAuthenticationMethod,
isLdapCurrentAuthenticationMethod,
isOidcCurrentAuthenticationMethod,
} from '@/sso.ee/sso-helpers';
import { PersonalizationSurveyAnswersV4 } from './survey-answers.dto';
@RestController('/me')
@@ -46,10 +51,34 @@ export class MeController {
res: Response,
@Body payload: UserUpdateRequestDto,
): Promise<PublicUser> {
const { id: userId, email: currentEmail, mfaEnabled } = req.user;
const {
id: userId,
email: currentEmail,
mfaEnabled,
firstName: currentFirstName,
lastName: currentLastName,
} = req.user;
const { email } = payload;
const { email, firstName, lastName } = payload;
const isEmailBeingChanged = email !== currentEmail;
const isFirstNameChanged = firstName !== currentFirstName;
const isLastNameChanged = lastName !== currentLastName;
if (
(isLdapCurrentAuthenticationMethod() || isOidcCurrentAuthenticationMethod()) &&
(isEmailBeingChanged || isFirstNameChanged || isLastNameChanged)
) {
this.logger.debug(
`Request to update user failed because ${getCurrentAuthenticationMethod()} user may not change their profile information`,
{
userId,
payload,
},
);
throw new BadRequestError(
` ${getCurrentAuthenticationMethod()} user may not change their profile information`,
);
}
// If SAML is enabled, we don't allow the user to change their email address
if (isSamlLicensedAndEnabled() && isEmailBeingChanged) {
@@ -23,7 +23,10 @@ import { MfaService } from '@/mfa/mfa.service';
import { AuthlessRequest } from '@/requests';
import { PasswordUtility } from '@/services/password.utility';
import { UserService } from '@/services/user.service';
import { isSamlCurrentAuthenticationMethod } from '@/sso.ee/sso-helpers';
import {
isOidcCurrentAuthenticationMethod,
isSamlCurrentAuthenticationMethod,
} from '@/sso.ee/sso-helpers';
import { UserManagementMailer } from '@/user-management/email';
@RestController()
@@ -76,17 +79,15 @@ export class PasswordResetController {
}
if (
isSamlCurrentAuthenticationMethod() &&
!(
user &&
(hasGlobalScope(user, 'user:resetPassword') || user.settings?.allowSSOManualLogin === true)
)
(isSamlCurrentAuthenticationMethod() || isOidcCurrentAuthenticationMethod()) &&
!(hasGlobalScope(user, 'user:resetPassword') || user.settings?.allowSSOManualLogin === true)
) {
const currentAuthenticationMethod = isSamlCurrentAuthenticationMethod() ? 'SAML' : 'OIDC';
this.logger.debug(
'Request to send password reset email failed because login is handled by SAML',
`Request to send password reset email failed because login is handled by ${currentAuthenticationMethod}`,
);
throw new ForbiddenError(
'Login is handled by SAML. Please contact your Identity Provider to reset your password.',
`Login is handled by ${currentAuthenticationMethod}. Please contact your Identity Provider to reset your password.`,
);
}