mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-20 02:05:21 -04:00
feat(auth): allow to disable OIDC user registration
Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
parent
b24f8b0a76
commit
fd1795f941
4 changed files with 80 additions and 16 deletions
|
@ -73,29 +73,30 @@ export class OidcController {
|
||||||
this.logger.log('No OIDC user identifier in callback', 'callback');
|
this.logger.log('No OIDC user identifier in callback', 'callback');
|
||||||
throw new UnauthorizedException('No OIDC user identifier found');
|
throw new UnauthorizedException('No OIDC user identifier found');
|
||||||
}
|
}
|
||||||
|
request.session.authProviderType = ProviderType.OIDC;
|
||||||
const identity = await this.oidcService.getExistingOidcIdentity(
|
const identity = await this.oidcService.getExistingOidcIdentity(
|
||||||
oidcIdentifier,
|
oidcIdentifier,
|
||||||
oidcUserIdentifier,
|
oidcUserIdentifier,
|
||||||
);
|
);
|
||||||
request.session.authProviderType = ProviderType.OIDC;
|
|
||||||
const mayUpdate = this.identityService.mayUpdateIdentity(oidcIdentifier);
|
const mayUpdate = this.identityService.mayUpdateIdentity(oidcIdentifier);
|
||||||
if (identity !== null) {
|
|
||||||
const user = await identity.user;
|
|
||||||
if (mayUpdate) {
|
|
||||||
await this.usersService.updateUser(
|
|
||||||
user,
|
|
||||||
userInfo.displayName,
|
|
||||||
userInfo.email,
|
|
||||||
userInfo.photoUrl,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
request.session.username = user.username;
|
if (identity === null) {
|
||||||
return { url: '/' };
|
|
||||||
} else {
|
|
||||||
request.session.newUserData = userInfo;
|
request.session.newUserData = userInfo;
|
||||||
return { url: '/new-user' };
|
return { url: '/new-user' };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const user = await identity.user;
|
||||||
|
if (mayUpdate) {
|
||||||
|
await this.usersService.updateUser(
|
||||||
|
user,
|
||||||
|
userInfo.displayName,
|
||||||
|
userInfo.email,
|
||||||
|
userInfo.photoUrl,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
request.session.username = user.username;
|
||||||
|
return { url: '/' };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof HttpException) {
|
if (error instanceof HttpException) {
|
||||||
throw error;
|
throw error;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
|
ForbiddenException,
|
||||||
Inject,
|
Inject,
|
||||||
Injectable,
|
Injectable,
|
||||||
InternalServerErrorException,
|
InternalServerErrorException,
|
||||||
|
@ -264,6 +265,11 @@ export class OidcService {
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof NotInDBError) {
|
if (e instanceof NotInDBError) {
|
||||||
|
if (!clientConfig.config.enableRegistration) {
|
||||||
|
throw new ForbiddenException(
|
||||||
|
'Registration is disabled for this OIDC provider',
|
||||||
|
);
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
@ -546,6 +546,7 @@ describe('authConfig', () => {
|
||||||
const defaultProfilePictureField = 'picture';
|
const defaultProfilePictureField = 'picture';
|
||||||
const emailField = 'a_email';
|
const emailField = 'a_email';
|
||||||
const defaultEmailField = 'email';
|
const defaultEmailField = 'email';
|
||||||
|
const enableRegistration = 'false';
|
||||||
const completeOidcConfig = {
|
const completeOidcConfig = {
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
HD_AUTH_OIDC_SERVERS: oidcNames.join(','),
|
HD_AUTH_OIDC_SERVERS: oidcNames.join(','),
|
||||||
|
@ -564,6 +565,7 @@ describe('authConfig', () => {
|
||||||
HD_AUTH_OIDC_GITLAB_DISPLAY_NAME_FIELD: displayNameField,
|
HD_AUTH_OIDC_GITLAB_DISPLAY_NAME_FIELD: displayNameField,
|
||||||
HD_AUTH_OIDC_GITLAB_PROFILE_PICTURE_FIELD: profilePictureField,
|
HD_AUTH_OIDC_GITLAB_PROFILE_PICTURE_FIELD: profilePictureField,
|
||||||
HD_AUTH_OIDC_GITLAB_EMAIL_FIELD: emailField,
|
HD_AUTH_OIDC_GITLAB_EMAIL_FIELD: emailField,
|
||||||
|
HD_AUTH_OIDC_GITLAB_ENABLE_REGISTER: enableRegistration,
|
||||||
/* eslint-enable @typescript-eslint/naming-convention */
|
/* eslint-enable @typescript-eslint/naming-convention */
|
||||||
};
|
};
|
||||||
describe('is correctly parsed', () => {
|
describe('is correctly parsed', () => {
|
||||||
|
@ -597,6 +599,7 @@ describe('authConfig', () => {
|
||||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
expect(firstOidc.emailField).toEqual(emailField);
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
it('when HD_AUTH_OIDC_GITLAB_THEME is not set', () => {
|
it('when HD_AUTH_OIDC_GITLAB_THEME is not set', () => {
|
||||||
|
@ -630,6 +633,7 @@ describe('authConfig', () => {
|
||||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
expect(firstOidc.emailField).toEqual(emailField);
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
it('when HD_AUTH_OIDC_GITLAB_AUTHORIZE_URL is not set', () => {
|
it('when HD_AUTH_OIDC_GITLAB_AUTHORIZE_URL is not set', () => {
|
||||||
|
@ -663,6 +667,7 @@ describe('authConfig', () => {
|
||||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
expect(firstOidc.emailField).toEqual(emailField);
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
it('when HD_AUTH_OIDC_GITLAB_TOKEN_URL is not set', () => {
|
it('when HD_AUTH_OIDC_GITLAB_TOKEN_URL is not set', () => {
|
||||||
|
@ -696,6 +701,7 @@ describe('authConfig', () => {
|
||||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
expect(firstOidc.emailField).toEqual(emailField);
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
it('when HD_AUTH_OIDC_GITLAB_USERINFO_URL is not set', () => {
|
it('when HD_AUTH_OIDC_GITLAB_USERINFO_URL is not set', () => {
|
||||||
|
@ -729,6 +735,7 @@ describe('authConfig', () => {
|
||||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
expect(firstOidc.emailField).toEqual(emailField);
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
it('when HD_AUTH_OIDC_GITLAB_END_SESSION_URL is not set', () => {
|
it('when HD_AUTH_OIDC_GITLAB_END_SESSION_URL is not set', () => {
|
||||||
|
@ -762,6 +769,7 @@ describe('authConfig', () => {
|
||||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
expect(firstOidc.emailField).toEqual(emailField);
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
it('when HD_AUTH_OIDC_GITLAB_SCOPE is not set', () => {
|
it('when HD_AUTH_OIDC_GITLAB_SCOPE is not set', () => {
|
||||||
|
@ -795,6 +803,7 @@ describe('authConfig', () => {
|
||||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
expect(firstOidc.emailField).toEqual(emailField);
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
it('when HD_AUTH_OIDC_GITLAB_USER_ID_FIELD is not set', () => {
|
it('when HD_AUTH_OIDC_GITLAB_USER_ID_FIELD is not set', () => {
|
||||||
|
@ -828,6 +837,7 @@ describe('authConfig', () => {
|
||||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
expect(firstOidc.emailField).toEqual(emailField);
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
it('when HD_AUTH_OIDC_GITLAB_DISPLAY_NAME_FIELD is not set', () => {
|
it('when HD_AUTH_OIDC_GITLAB_DISPLAY_NAME_FIELD is not set', () => {
|
||||||
|
@ -861,6 +871,7 @@ describe('authConfig', () => {
|
||||||
expect(firstOidc.displayNameField).toEqual(defaultDisplayNameField);
|
expect(firstOidc.displayNameField).toEqual(defaultDisplayNameField);
|
||||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
expect(firstOidc.emailField).toEqual(emailField);
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
it('when HD_AUTH_OIDC_GITLAB_PROFILE_PICTURE_FIELD is not set', () => {
|
it('when HD_AUTH_OIDC_GITLAB_PROFILE_PICTURE_FIELD is not set', () => {
|
||||||
|
@ -896,6 +907,7 @@ describe('authConfig', () => {
|
||||||
defaultProfilePictureField,
|
defaultProfilePictureField,
|
||||||
);
|
);
|
||||||
expect(firstOidc.emailField).toEqual(emailField);
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
it('when HD_AUTH_OIDC_GITLAB_EMAIL_FIELD is not set', () => {
|
it('when HD_AUTH_OIDC_GITLAB_EMAIL_FIELD is not set', () => {
|
||||||
|
@ -929,6 +941,41 @@ describe('authConfig', () => {
|
||||||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
expect(firstOidc.emailField).toEqual(defaultEmailField);
|
expect(firstOidc.emailField).toEqual(defaultEmailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(false);
|
||||||
|
restore();
|
||||||
|
});
|
||||||
|
it('when HD_AUTH_OIDC_GITLAB_ENABLE_REGISTER is not set', () => {
|
||||||
|
const restore = mockedEnv(
|
||||||
|
{
|
||||||
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
|
...neededAuthConfig,
|
||||||
|
...completeOidcConfig,
|
||||||
|
HD_AUTH_OIDC_GITLAB_ENABLE_REGISTER: undefined,
|
||||||
|
/* eslint-enable @typescript-eslint/naming-convention */
|
||||||
|
},
|
||||||
|
{
|
||||||
|
clear: true,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const config = authConfig();
|
||||||
|
expect(config.oidc).toHaveLength(1);
|
||||||
|
const firstOidc = config.oidc[0];
|
||||||
|
expect(firstOidc.identifier).toEqual(oidcNames[0]);
|
||||||
|
expect(firstOidc.issuer).toEqual(issuer);
|
||||||
|
expect(firstOidc.clientID).toEqual(clientId);
|
||||||
|
expect(firstOidc.clientSecret).toEqual(clientSecret);
|
||||||
|
expect(firstOidc.theme).toEqual(theme);
|
||||||
|
expect(firstOidc.authorizeUrl).toEqual(authorizeUrl);
|
||||||
|
expect(firstOidc.tokenUrl).toEqual(tokenUrl);
|
||||||
|
expect(firstOidc.scope).toEqual(scope);
|
||||||
|
expect(firstOidc.userinfoUrl).toEqual(userinfoUrl);
|
||||||
|
expect(firstOidc.endSessionUrl).toEqual(endSessionUrl);
|
||||||
|
expect(firstOidc.userIdField).toEqual(userIdField);
|
||||||
|
expect(firstOidc.userNameField).toEqual(userNameField);
|
||||||
|
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||||
|
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||||
|
expect(firstOidc.emailField).toEqual(emailField);
|
||||||
|
expect(firstOidc.enableRegistration).toEqual(true);
|
||||||
restore();
|
restore();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { Theme } from './theme.enum';
|
||||||
import {
|
import {
|
||||||
buildErrorMessage,
|
buildErrorMessage,
|
||||||
ensureNoDuplicatesExist,
|
ensureNoDuplicatesExist,
|
||||||
|
parseOptionalBoolean,
|
||||||
parseOptionalNumber,
|
parseOptionalNumber,
|
||||||
replaceAuthErrorsWithEnvironmentVariables,
|
replaceAuthErrorsWithEnvironmentVariables,
|
||||||
toArrayConfig,
|
toArrayConfig,
|
||||||
|
@ -50,6 +51,7 @@ export interface OidcConfig extends InternalIdentifier {
|
||||||
displayNameField: string;
|
displayNameField: string;
|
||||||
profilePictureField: string;
|
profilePictureField: string;
|
||||||
emailField: string;
|
emailField: string;
|
||||||
|
enableRegistration?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AuthConfig {
|
export interface AuthConfig {
|
||||||
|
@ -147,6 +149,7 @@ const authSchema = Joi.object({
|
||||||
displayNameField: Joi.string().default('name').optional(),
|
displayNameField: Joi.string().default('name').optional(),
|
||||||
profilePictureField: Joi.string().default('picture').optional(),
|
profilePictureField: Joi.string().default('picture').optional(),
|
||||||
emailField: Joi.string().default('email').optional(),
|
emailField: Joi.string().default('email').optional(),
|
||||||
|
enableRegistration: Joi.boolean().default(true).optional(),
|
||||||
}).optional(),
|
}).optional(),
|
||||||
)
|
)
|
||||||
.optional(),
|
.optional(),
|
||||||
|
@ -217,6 +220,9 @@ export default registerAs('authConfig', () => {
|
||||||
profilePictureField:
|
profilePictureField:
|
||||||
process.env[`HD_AUTH_OIDC_${oidcName}_PROFILE_PICTURE_FIELD`],
|
process.env[`HD_AUTH_OIDC_${oidcName}_PROFILE_PICTURE_FIELD`],
|
||||||
emailField: process.env[`HD_AUTH_OIDC_${oidcName}_EMAIL_FIELD`],
|
emailField: process.env[`HD_AUTH_OIDC_${oidcName}_EMAIL_FIELD`],
|
||||||
|
enableRegistration: parseOptionalBoolean(
|
||||||
|
process.env[`HD_AUTH_OIDC_${oidcName}_ENABLE_REGISTER`],
|
||||||
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let syncSource = process.env.HD_AUTH_SYNC_SOURCE;
|
let syncSource = process.env.HD_AUTH_SYNC_SOURCE;
|
||||||
|
@ -236,8 +242,12 @@ export default registerAs('authConfig', () => {
|
||||||
lifetime: parseOptionalNumber(process.env.HD_SESSION_LIFETIME),
|
lifetime: parseOptionalNumber(process.env.HD_SESSION_LIFETIME),
|
||||||
},
|
},
|
||||||
local: {
|
local: {
|
||||||
enableLogin: process.env.HD_AUTH_LOCAL_ENABLE_LOGIN,
|
enableLogin: parseOptionalBoolean(
|
||||||
enableRegister: process.env.HD_AUTH_LOCAL_ENABLE_REGISTER,
|
process.env.HD_AUTH_LOCAL_ENABLE_LOGIN,
|
||||||
|
),
|
||||||
|
enableRegister: parseOptionalBoolean(
|
||||||
|
process.env.HD_AUTH_LOCAL_ENABLE_REGISTER,
|
||||||
|
),
|
||||||
minimalPasswordStrength: parseOptionalNumber(
|
minimalPasswordStrength: parseOptionalNumber(
|
||||||
process.env.HD_AUTH_LOCAL_MINIMAL_PASSWORD_STRENGTH,
|
process.env.HD_AUTH_LOCAL_MINIMAL_PASSWORD_STRENGTH,
|
||||||
),
|
),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue