mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-22 11:15:23 -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');
|
||||
throw new UnauthorizedException('No OIDC user identifier found');
|
||||
}
|
||||
request.session.authProviderType = ProviderType.OIDC;
|
||||
const identity = await this.oidcService.getExistingOidcIdentity(
|
||||
oidcIdentifier,
|
||||
oidcUserIdentifier,
|
||||
);
|
||||
request.session.authProviderType = ProviderType.OIDC;
|
||||
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;
|
||||
return { url: '/' };
|
||||
} else {
|
||||
if (identity === null) {
|
||||
request.session.newUserData = userInfo;
|
||||
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) {
|
||||
if (error instanceof HttpException) {
|
||||
throw error;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
import {
|
||||
ForbiddenException,
|
||||
Inject,
|
||||
Injectable,
|
||||
InternalServerErrorException,
|
||||
|
@ -264,6 +265,11 @@ export class OidcService {
|
|||
);
|
||||
} catch (e) {
|
||||
if (e instanceof NotInDBError) {
|
||||
if (!clientConfig.config.enableRegistration) {
|
||||
throw new ForbiddenException(
|
||||
'Registration is disabled for this OIDC provider',
|
||||
);
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
throw e;
|
||||
|
|
|
@ -546,6 +546,7 @@ describe('authConfig', () => {
|
|||
const defaultProfilePictureField = 'picture';
|
||||
const emailField = 'a_email';
|
||||
const defaultEmailField = 'email';
|
||||
const enableRegistration = 'false';
|
||||
const completeOidcConfig = {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
HD_AUTH_OIDC_SERVERS: oidcNames.join(','),
|
||||
|
@ -564,6 +565,7 @@ describe('authConfig', () => {
|
|||
HD_AUTH_OIDC_GITLAB_DISPLAY_NAME_FIELD: displayNameField,
|
||||
HD_AUTH_OIDC_GITLAB_PROFILE_PICTURE_FIELD: profilePictureField,
|
||||
HD_AUTH_OIDC_GITLAB_EMAIL_FIELD: emailField,
|
||||
HD_AUTH_OIDC_GITLAB_ENABLE_REGISTER: enableRegistration,
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
};
|
||||
describe('is correctly parsed', () => {
|
||||
|
@ -597,6 +599,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
expect(firstOidc.enableRegistration).toEqual(false);
|
||||
restore();
|
||||
});
|
||||
it('when HD_AUTH_OIDC_GITLAB_THEME is not set', () => {
|
||||
|
@ -630,6 +633,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
expect(firstOidc.enableRegistration).toEqual(false);
|
||||
restore();
|
||||
});
|
||||
it('when HD_AUTH_OIDC_GITLAB_AUTHORIZE_URL is not set', () => {
|
||||
|
@ -663,6 +667,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
expect(firstOidc.enableRegistration).toEqual(false);
|
||||
restore();
|
||||
});
|
||||
it('when HD_AUTH_OIDC_GITLAB_TOKEN_URL is not set', () => {
|
||||
|
@ -696,6 +701,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
expect(firstOidc.enableRegistration).toEqual(false);
|
||||
restore();
|
||||
});
|
||||
it('when HD_AUTH_OIDC_GITLAB_USERINFO_URL is not set', () => {
|
||||
|
@ -729,6 +735,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
expect(firstOidc.enableRegistration).toEqual(false);
|
||||
restore();
|
||||
});
|
||||
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.profilePictureField).toEqual(profilePictureField);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
expect(firstOidc.enableRegistration).toEqual(false);
|
||||
restore();
|
||||
});
|
||||
it('when HD_AUTH_OIDC_GITLAB_SCOPE is not set', () => {
|
||||
|
@ -795,6 +803,7 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
expect(firstOidc.enableRegistration).toEqual(false);
|
||||
restore();
|
||||
});
|
||||
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.profilePictureField).toEqual(profilePictureField);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
expect(firstOidc.enableRegistration).toEqual(false);
|
||||
restore();
|
||||
});
|
||||
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.profilePictureField).toEqual(profilePictureField);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
expect(firstOidc.enableRegistration).toEqual(false);
|
||||
restore();
|
||||
});
|
||||
it('when HD_AUTH_OIDC_GITLAB_PROFILE_PICTURE_FIELD is not set', () => {
|
||||
|
@ -896,6 +907,7 @@ describe('authConfig', () => {
|
|||
defaultProfilePictureField,
|
||||
);
|
||||
expect(firstOidc.emailField).toEqual(emailField);
|
||||
expect(firstOidc.enableRegistration).toEqual(false);
|
||||
restore();
|
||||
});
|
||||
it('when HD_AUTH_OIDC_GITLAB_EMAIL_FIELD is not set', () => {
|
||||
|
@ -929,6 +941,41 @@ describe('authConfig', () => {
|
|||
expect(firstOidc.displayNameField).toEqual(displayNameField);
|
||||
expect(firstOidc.profilePictureField).toEqual(profilePictureField);
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,6 +11,7 @@ import { Theme } from './theme.enum';
|
|||
import {
|
||||
buildErrorMessage,
|
||||
ensureNoDuplicatesExist,
|
||||
parseOptionalBoolean,
|
||||
parseOptionalNumber,
|
||||
replaceAuthErrorsWithEnvironmentVariables,
|
||||
toArrayConfig,
|
||||
|
@ -50,6 +51,7 @@ export interface OidcConfig extends InternalIdentifier {
|
|||
displayNameField: string;
|
||||
profilePictureField: string;
|
||||
emailField: string;
|
||||
enableRegistration?: boolean;
|
||||
}
|
||||
|
||||
export interface AuthConfig {
|
||||
|
@ -147,6 +149,7 @@ const authSchema = Joi.object({
|
|||
displayNameField: Joi.string().default('name').optional(),
|
||||
profilePictureField: Joi.string().default('picture').optional(),
|
||||
emailField: Joi.string().default('email').optional(),
|
||||
enableRegistration: Joi.boolean().default(true).optional(),
|
||||
}).optional(),
|
||||
)
|
||||
.optional(),
|
||||
|
@ -217,6 +220,9 @@ export default registerAs('authConfig', () => {
|
|||
profilePictureField:
|
||||
process.env[`HD_AUTH_OIDC_${oidcName}_PROFILE_PICTURE_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;
|
||||
|
@ -236,8 +242,12 @@ export default registerAs('authConfig', () => {
|
|||
lifetime: parseOptionalNumber(process.env.HD_SESSION_LIFETIME),
|
||||
},
|
||||
local: {
|
||||
enableLogin: process.env.HD_AUTH_LOCAL_ENABLE_LOGIN,
|
||||
enableRegister: process.env.HD_AUTH_LOCAL_ENABLE_REGISTER,
|
||||
enableLogin: parseOptionalBoolean(
|
||||
process.env.HD_AUTH_LOCAL_ENABLE_LOGIN,
|
||||
),
|
||||
enableRegister: parseOptionalBoolean(
|
||||
process.env.HD_AUTH_LOCAL_ENABLE_REGISTER,
|
||||
),
|
||||
minimalPasswordStrength: parseOptionalNumber(
|
||||
process.env.HD_AUTH_LOCAL_MINIMAL_PASSWORD_STRENGTH,
|
||||
),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue