MyAuthProvider.java
package org.flasby.security;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.transaction.Transactional;
import org.flasby.entity.Authority;
import org.flasby.entity.ChristmasUser;
import org.flasby.entity.Users;
import org.flasby.entity.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import lombok.extern.log4j.Log4j2;
@Log4j2
// @Configuration
@Component
public class MyAuthProvider implements AuthenticationProvider {
public MyAuthProvider(@Autowired UserRepository<ChristmasUser> users /*, @Autowired Environment env, @Autowired Config config */ ) {
// this.env = env;
this.users = users;
// this.config = config;
System.err.println("Instantiating MyAuthProvider with "+users);
}
private final UserRepository<ChristmasUser> users;
// private final Environment env;
// private final Config config;
public static interface AuthHandler<T extends Authentication> {
Authentication handle(T authentication);
}
Set<Class<? extends Principal>> handlers = new HashSet<>();
{
handlers.add(RememberMeAuthenticationToken.class);
handlers.add(UsernamePasswordAuthenticationToken.class);
}
@Override
public boolean supports(Class<?> authentication) {
log.warn(" supports - - - - - - - - " + authentication + " is OK: " + handlers.contains(authentication));
return handlers.contains(authentication);
}
/**
* checks the userId and password.
* In addition it will invoke the IP Block checks
*/
@Override
@Transactional(dontRollbackOn = AuthenticationException.class)
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
AbstractAuthenticationToken token = (AbstractAuthenticationToken) authentication;
log.info("authentication: " + authentication.getPrincipal()); // User Name
if (authentication instanceof RememberMeAuthenticationToken) {
RememberMeAuthenticationToken at = (RememberMeAuthenticationToken) authentication;
log.warn("RememberMeAuthenticationToken");
// Must be a remember me here so don't build a new user.
return new UsernamePasswordAuthenticationToken(at.getPrincipal(),
null,
// If the principal owned additional stuff like certs or passwords they
// can be put here to be made available to other systems. I don't need them
// so set to null.
at.getAuthorities());
}
Users<Authority> user = users.findByName((String) authentication.getPrincipal());
if (user == null) {
log.info("Can't find " + authentication.getPrincipal() + " in database");
throw new UsernameNotFoundException("Incorrect credentials");
} else {
if (!user.checkPassword((String) authentication.getCredentials())) {
log.info("Incorrect password for " + authentication.getPrincipal()
+ " - " + user.getPassword()
+ " - Passwords are now BCrypt encoded in the database: " + user.getFailedLoginAttempts());
if (user.isDisabled()) {
log.warn("User {} presented an incorrect password but is additionally disabled - Login refused", () -> user.getName());
throw new DisabledException("User is disabled");
}
throw new UsernameNotFoundException("Incorrect credentials");
} else if (user.isDisabled()) {
log.warn("User {} is correctly authenticated but disabled - Login refused", () -> user.getName());
throw new DisabledException("User is disabled");
}
}
// Grrr, it seems that the Authority has to be ROLE_USER so that
// .hasRole("USER") evaluates to true.
// A bit crap in my view.
// Compare with the roles used in SocketSecurityConfig
List<GrantedAuthority> auths = new ArrayList<>();
user.getRoles().forEach((a) -> auths.add(new SimpleGrantedAuthority(a.getAuthority())));
// Dispose of any passwords lying around
token.eraseCredentials();
log.info("Initial Login all good: " + auths);
return new UsernamePasswordAuthenticationToken(authentication.getPrincipal(),
null,
// If the principal owned additional stuff like certs or passwords they
// can be put here to be made available to other systems. I don't need them
// so set to null.
auths);
}
}