feat(core): Limit user changes when saml is enabled (#5577)

* consolidate SSO settings

* update saml settings

* fix type error

* limit user changes when saml is enabled

* add test
This commit is contained in:
Michael Auerswald
2023-03-03 10:05:30 +01:00
committed by GitHub
parent a91b631411
commit b5179597f3
5 changed files with 116 additions and 3 deletions

View File

@@ -22,6 +22,7 @@ import type {
IInternalHooksClass,
} from '@/Interfaces';
import { randomBytes } from 'crypto';
import { isSamlLicensedAndEnabled } from '../sso/saml/samlHelpers';
@RestController('/me')
export class MeController {
@@ -77,6 +78,20 @@ export class MeController {
await validateEntity(payload);
// If SAML is enabled, we don't allow the user to change their email address
if (isSamlLicensedAndEnabled()) {
if (email !== currentEmail) {
this.logger.debug(
'Request to update user failed because SAML user may not change their email',
{
userId,
payload,
},
);
throw new BadRequestError('SAML user may not change their email');
}
}
await this.userRepository.update(userId, payload);
const user = await this.userRepository.findOneOrFail({
where: { id: userId },
@@ -105,6 +120,16 @@ export class MeController {
async updatePassword(req: MeRequest.Password, res: Response) {
const { currentPassword, newPassword } = req.body;
// If SAML is enabled, we don't allow the user to change their email address
if (isSamlLicensedAndEnabled()) {
this.logger.debug('Attempted to change password for user, while SAML is enabled', {
userId: req.user?.id,
});
throw new BadRequestError(
'With SAML enabled, users need to use their SAML provider to change passwords',
);
}
if (typeof currentPassword !== 'string' || typeof newPassword !== 'string') {
throw new BadRequestError('Invalid payload.');
}

View File

@@ -1,7 +1,6 @@
import type { RequestHandler } from 'express';
import type { AuthenticatedRequest } from '../../../requests';
import { isSamlCurrentAuthenticationMethod } from '../../ssoHelpers';
import { isSamlLoginEnabled, isSamlLicensed } from '../samlHelpers';
import { isSamlLicensed, isSamlLicensedAndEnabled } from '../samlHelpers';
export const samlLicensedOwnerMiddleware: RequestHandler = (
req: AuthenticatedRequest,
@@ -16,7 +15,7 @@ export const samlLicensedOwnerMiddleware: RequestHandler = (
};
export const samlLicensedAndEnabledMiddleware: RequestHandler = (req, res, next) => {
if (isSamlLoginEnabled() && isSamlLicensed() && isSamlCurrentAuthenticationMethod()) {
if (isSamlLicensedAndEnabled()) {
next();
} else {
res.status(401).json({ status: 'error', message: 'Unauthorized' });

View File

@@ -10,6 +10,7 @@ import type { SamlUserAttributes } from './types/samlUserAttributes';
import type { FlowResult } from 'samlify/types/src/flow';
import type { SamlAttributeMapping } from './types/samlAttributeMapping';
import { SAML_ENTERPRISE_FEATURE_ENABLED, SAML_LOGIN_ENABLED, SAML_LOGIN_LABEL } from './constants';
import { isSamlCurrentAuthenticationMethod } from '../ssoHelpers';
/**
* Check whether the SAML feature is licensed and enabled in the instance
*/
@@ -37,6 +38,10 @@ export function isSamlLicensed(): boolean {
);
}
export function isSamlLicensedAndEnabled(): boolean {
return isSamlLoginEnabled() && isSamlLicensed() && isSamlCurrentAuthenticationMethod();
}
export const isSamlPreferences = (candidate: unknown): candidate is SamlPreferences => {
const o = candidate as SamlPreferences;
return (

View File

@@ -11,3 +11,9 @@ export function isSsoJustInTimeProvisioningEnabled(): boolean {
export function doRedirectUsersFromLoginToSsoFlow(): boolean {
return config.getEnv('sso.redirectLoginToSso');
}
export function setCurrentAuthenticationMethod(
authenticationMethod: 'email' | 'ldap' | 'saml',
): void {
config.set('userManagement.authenticationMethod', authenticationMethod);
}