Как правильно реализовать TOTP (2FA) в Spring Security? - PullRequest
1 голос
/ 01 апреля 2020

Я пишу небольшое приложение для себя и хочу реализовать двухфакторную аутентификацию в Spring Boot. Для этого следуйте советам этой статьи: https://www.baeldung.com/spring-security-two-factor-authentication-with-soft-token

Столкнулся со следующими проблемами: 1) Мой код, написанный на основе этой статьи, не работает. Spring Security полностью игнорирует is2FaEnabled == true и в любом случае авторизует пользователя, даже если код не был введен.

Судя по журналам в этом потоке .authenticationDetailsSource (authenticationDetailsSource) даже go для проверка.

2) Как я могу реализовать следующее: во время авторизации сначала проверьте, включен ли 2FA, если да, то направьте пользователя на другой URL-адрес или откройте модуль с вводом и после правильного ввода кода, авторизовать его?

Вот мой исходный код:

CustomWebAuthenticationDetailsSource. java

@Component
public class CustomWebAuthenticationDetailsSource implements
        AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {

    @Override
    public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
        return new CustomWebAuthenticationDetails(context);
    }
}

CustomWebAuthenticationDetails. java

public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {

    @Getter
    private String verificationCode;

    public CustomWebAuthenticationDetails(HttpServletRequest request) {
        super(request);
        verificationCode = request.getParameter("code");
    }
}

CustomAuthenticationProvider . java

    public class CustomAuthenticationProvider extends DaoAuthenticationProvider {

        @Autowired
        private UserServiceImpl userServiceImpl;

        private Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);

        @Override
        public Authentication authenticate(Authentication auth)
                throws AuthenticationException {
        User user = userServiceImpl.findUserByEmail(auth.getName());

        String verificationCode
                = ((CustomWebAuthenticationDetails) auth.getDetails())
                .getVerificationCode();
        if ((user == null)) {
            throw new BadCredentialsException("Invalid username or password");
        }

        if (user.getIs2FaEnabled()) {
            Totp totp = new Totp(user.getTwoFaSecret());
            if (!isValidLong(verificationCode) || !totp.verify(verificationCode)) {
                throw new BadCredentialsException("Invalid verfication code");
            }
        }

        Authentication result = super.authenticate(auth);
        return new UsernamePasswordAuthenticationToken(
                user, result.getCredentials(), result.getAuthorities());
    }

    private boolean isValidLong(String code) {
        try {
            Long.parseLong(code);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

WebSecurityConfig. java

Заранее спасибо!

...