mirror of https://github.com/halo-dev/halo
Add support to disable two-factor authentication (#6242)
#### What type of PR is this? /kind improvement /area core /milestone 2.17.0 #### What this PR does / why we need it: This PR provides a configuration property to control whether two-factor authentication is disabled. e.g.: ```yaml halo: security: two-factor-auth: disabled: true | false # Default is false. ``` #### Which issue(s) this PR fixes: Fixes #5640 #### Special notes for your reviewer: 1. Enable 2FA and configure TOTP 2. Disable 2FA by configuring property above 3. Restart Halo and try to login #### Does this PR introduce a user-facing change? ```release-note 支持通过配置的方式全局禁用二步验证 ```pull/6279/head
parent
0b7b74e826
commit
cc3564bf82
|
@ -127,8 +127,12 @@ public class WebServerSecurityConfig {
|
|||
|
||||
@Bean
|
||||
DefaultUserDetailService userDetailsService(UserService userService,
|
||||
RoleService roleService) {
|
||||
return new DefaultUserDetailService(userService, roleService);
|
||||
RoleService roleService,
|
||||
HaloProperties haloProperties) {
|
||||
var userDetailService = new DefaultUserDetailService(userService, roleService);
|
||||
var twoFactorAuthDisabled = haloProperties.getSecurity().getTwoFactorAuth().isDisabled();
|
||||
userDetailService.setTwoFactorAuthDisabled(twoFactorAuthDisabled);
|
||||
return userDetailService;
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -16,6 +16,18 @@ public class SecurityProperties {
|
|||
|
||||
private final RememberMeOptions rememberMe = new RememberMeOptions();
|
||||
|
||||
private final TwoFactorAuthOptions twoFactorAuth = new TwoFactorAuthOptions();
|
||||
|
||||
@Data
|
||||
public static class TwoFactorAuthOptions {
|
||||
|
||||
/**
|
||||
* Whether two-factor authentication is disabled.
|
||||
*/
|
||||
private boolean disabled;
|
||||
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class FrameOptions {
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import static run.halo.app.security.authorization.AuthorityUtils.ANONYMOUS_ROLE_
|
|||
import static run.halo.app.security.authorization.AuthorityUtils.AUTHENTICATED_ROLE_NAME;
|
||||
import static run.halo.app.security.authorization.AuthorityUtils.ROLE_PREFIX;
|
||||
|
||||
import lombok.Setter;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.ReactiveUserDetailsPasswordService;
|
||||
|
@ -31,6 +32,12 @@ public class DefaultUserDetailService
|
|||
|
||||
private final RoleService roleService;
|
||||
|
||||
/**
|
||||
* Indicates whether two-factor authentication is disabled.
|
||||
*/
|
||||
@Setter
|
||||
private boolean twoFactorAuthDisabled;
|
||||
|
||||
public DefaultUserDetailService(UserService userService, RoleService roleService) {
|
||||
this.userService = userService;
|
||||
this.roleService = roleService;
|
||||
|
@ -66,7 +73,9 @@ public class DefaultUserDetailService
|
|||
return setAuthorities.then(Mono.fromSupplier(() -> {
|
||||
var twoFactorAuthSettings = TwoFactorUtils.getTwoFactorAuthSettings(user);
|
||||
return new HaloUser.Builder(userBuilder.build())
|
||||
.twoFactorAuthEnabled(twoFactorAuthSettings.isAvailable())
|
||||
.twoFactorAuthEnabled(
|
||||
(!twoFactorAuthDisabled) && twoFactorAuthSettings.isAvailable()
|
||||
)
|
||||
.totpEncryptedSecret(user.getSpec().getTotpEncryptedSecret())
|
||||
.build();
|
||||
}));
|
||||
|
|
|
@ -156,11 +156,27 @@ class DefaultUserDetailServiceTest {
|
|||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFindHaloUserDetailsWith2faDisabledWhen2faDisabledGlobally() {
|
||||
userDetailService.setTwoFactorAuthDisabled(true);
|
||||
var fakeUser = createFakeUser();
|
||||
fakeUser.getSpec().setTwoFactorAuthEnabled(true);
|
||||
fakeUser.getSpec().setTotpEncryptedSecret("fake-totp-encrypted-secret");
|
||||
when(userService.getUser("faker")).thenReturn(Mono.just(fakeUser));
|
||||
when(roleService.listRoleRefs(any())).thenReturn(Flux.empty());
|
||||
userDetailService.findByUsername("faker")
|
||||
.as(StepVerifier::create)
|
||||
.assertNext(userDetails -> {
|
||||
assertInstanceOf(HaloUserDetails.class, userDetails);
|
||||
assertFalse(((HaloUserDetails) userDetails).isTwoFactorAuthEnabled());
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFindUserDetailsByExistingUsernameButKindOfRoleRefIsNotRole() {
|
||||
var foundUser = createFakeUser();
|
||||
|
||||
var roleGvk = new Role().groupVersionKind();
|
||||
var roleRef = new RoleRef();
|
||||
roleRef.setKind("FakeRole");
|
||||
roleRef.setApiGroup("fake.halo.run");
|
||||
|
|
Loading…
Reference in New Issue