package ch.rasc.sec.security; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.InternalAuthenticationServiceException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.util.StringUtils; public class TotpAuthenticationProvider extends DaoAuthenticationProvider { @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException { super.additionalAuthenticationChecks(userDetails, authentication); if (authentication.getDetails() instanceof TotpWebAuthenticationDetails) { String secret = ((JpaUserDetails) userDetails).getSecret(); if (StringUtils.hasText(secret)) { Integer totpKey = ((TotpWebAuthenticationDetails) authentication .getDetails()).getTotpKey(); if (totpKey != null) { try { if (!TotpAuthenticatorUtil.verifyCode(secret, totpKey, 2)) { throw new BadCredentialsException( "Google Authenticator Code is not valid"); } } catch (InvalidKeyException | NoSuchAlgorithmException e) { throw new InternalAuthenticationServiceException( "Google Authenticator Code verify failed", e); } } else { throw new MissingTotpKeyAuthenticatorException( "Google Authenticator Code is mandatory"); } } } } }