WithMockUser not working, but SecurityContext.getContext().setAuthentification does - spring-boot

I try to mock login with #WithMockUserbut it is not working.
#SpringBootTest
class RoleTest {
#Autowired
private UserService userService;
#Autowired
private RoleService roleService;
private User user;
#BeforeEach
void setUp() {
AuthentificationService.AuthentificationMock.loginAsAdminOnly();
user = new User("maier", "password", "Hansi", "Meier", "hanmai#maier.de", "+4953353535353", roleService.getByName(Role.ROLE_ADMIN).orElse(null));
assertNotNull(user.getRoles());
userService.save(user);
AuthentificationService.AuthentificationMock.logout();
}
#AfterEach
void tearDown() {
AuthentificationService.AuthentificationMock.loginAsAdminOnly();
userService.delete(user);
AuthentificationService.AuthentificationMock.logout();
}
#Test
#WithMockUser(Role.ADMIN)
void testRoleHierarchy() {
boolean succeeded = true;
//WHEN
try {
final Optional<User> byUsername = userService.getByUsernameResolved(user.getUsername());
} catch (Exception e) {
succeeded = false;
}
//THEN
assertTrue(succeeded, "ADMIN has no USER Privileges, check RoleHierarchy");
}
}
If I run test authentication there is an AuthenticationCredentialsNotFoundException and so test fails.
That is the Service which the access is limited:
#Service
#Slf4j
#Transactional
#NoArgsConstructor
public class UserService implements JpaServiceContract<User>, UserDetailsService {
private UserRepository userRepository;
private AuthenticationManager authenticationManager;
private PasswordEncoder passwordEncoder;
#Autowired
public UserService(PasswordEncoder passwordEncoder, AuthenticationManager authenticationManager, UserRepository userRepository) {
this.userRepository = userRepository;
this.authenticationManager = authenticationManager;
this.passwordEncoder = passwordEncoder;
}
#Override
public UserDetails loadUserByUsername(#NotNull String username) {
final String callerName = SharedSecrets.getJavaLangAccess().getStackTraceElement(new Throwable(), 12).getClassName();
if (!callerName.equals("app.config.security.TokenAuthenticationFilter")) {
throw new MethodAccessException();
}
SecurityContextHolder.getContext().setAuthentication(new PreAuthenticatedAuthenticationToken(null, null, Collections.singletonList(new Role(Role.ADMIN))));
Optional<User> user = getByUsernameResolved(username);
SecurityContextHolder.clearContext();
final User user1 = user.orElse(null);
assert user1 != null;
return user1;
}
/**
* This Method is same as {#link #getByUsername(String)} but it resolves all Lazy loaded Properties,
* which could not be resolved outside of the current Transaction anymore
*
* #param username Of the {#link app.model.authentification.User} which should be found
* #return The {#link app.model.authentification.User} found as an {#link java.util.Optional}
*/
#RolesAllowed(value = Role.ROLE_USER)
public Optional<User> getByUsernameResolved(#NotNull String username) {
final Optional<User> userUnresolved = getByUsername(username);
userUnresolved.ifPresent(user -> Hibernate.initialize(user.getRoles()));
return userUnresolved;
}
#RolesAllowed(value = Role.ROLE_USER)
public Optional<User> getByUsername(#NotNull String username) {
if (!existsByUsername(username)) {
throw new RessourceNotFoundException("User not found");
}
return userRepository.findByUsername(username);
}
#Override
#RolesAllowed(Role.ROLE_USER)
public Optional<User> getById(#NotNull Long id) {
return userRepository.findById(id);
}
#Override
#RolesAllowed(Role.ROLE_USER)
public Optional<User> getByIdResolved(#NotNull Long id) {
final Optional<User> byId = getById(id);
if (byId.isPresent()) {
Hibernate.initialize(byId.get().getRoles());
return byId;
} else {
return Optional.empty();
}
}
#RolesAllowed(value = Role.ROLE_ADMIN)
#Override
public Set<User> getAll() {
return (Set<User>) userRepository.findAll();
}
#RolesAllowed(value = Role.ROLE_ADMIN)
#Override
public Set<User> getAllResolved() {
final Set<User> all = getAll();
Hibernate.initialize(all);
return all;
}
public User changePassword(#NotNull String oldPassword, #NotNull String newPassword) {
User user = getLoggedInUser();
user.setPassword(passwordEncoder.encode(newPassword));
return userRepository.save(user);
}
#Override
#RolesAllowed(value = Role.ROLE_USER)
public boolean existsById(#NotNull Long id) {
return userRepository.existsById(id);
}
#RolesAllowed(value = Role.ROLE_USER)
public boolean existsByUsername(#NotNull String username) {
return userRepository.existsByUsername(username);
}
#Override
#RolesAllowed(value = Role.ROLE_ADMIN)
public User save(#NotNull User user) throws RessourceAlreadyExistsException, InvalidParameterException {
if (UserValidator.isFullValid(user))
if (!userRepository.existsByUsername(user.getUsername())) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepository.save(user);
} else {
throw new RessourceAlreadyExistsException(user.getUsername());
}
throw new InvalidParameterException(new String[]{"User"});
}
#Override
#RolesAllowed(Role.ROLE_USER)
public User update(#NotNull User user) throws InvalidParameterException {
if (UserValidator.isFullValid(user) && userRepository.existsByUsername(user.getUsername())) {
user.setPassword(passwordEncoder.encode(user.getPassword()));
return userRepository.save(user);
}
throw new InvalidParameterException(new String[]{"User"});
}
#Override
#RolesAllowed(value = Role.ROLE_ADMIN)
public void delete(#NotNull User user) throws IllegalArgumentException {
userRepository.delete(user);
}
#RolesAllowed(value = Role.ROLE_ADMIN)
public void delete(#NotNull String username) {
userRepository.deleteByUsername(username);
}
#RolesAllowed(value = Role.ROLE_USER)
private User getLoggedInUser() throws InvalidStateException {
Authentication currentUser = SecurityContextHolder.getContext().getAuthentication();
String username = currentUser.getName();
final Optional<User> userValue = getByUsername(username);
if (userValue.isPresent())
return userValue.get();
throw new InvalidStateException("User " + username + " not found");
}
}
If you like to I could provide more Information of Configuration but at the Moment I don't know if this is necessary. But if you believe it is I will.

Related

Get additional security user fields without calling findByUsername

I'm calling the findUserByUsername() method to get the name field in the User entity and I'm wondering if there's any better to do it without having to execute an addional query
AuthenticationController.java
#PostMapping("/login")
public ResponseEntity<AuthenticationResponse> login (#RequestBody AuthenticationRequest userLogin) {
try {
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(userLogin.username(), userLogin.password()));
String token = tokenService.generateToken(authentication);
Optional<User> user = userRepository.findByUsername(authentication.getName());
AuthenticationResponse response = new AuthenticationResponse(user.get().getName(), token);
return ResponseEntity.ok().body(response);
} catch (BadCredentialsException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
SecurityUser.java
public class SecurityUser implements UserDetails {
private final User user;
public SecurityUser (User user) {
this.user = user;
}
#Override
public String getUsername() {
return user.getUsername();
}
#Override
public String getPassword() {
return user.getPassword();
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user
.getRoles()
.stream()
.map(role -> new SimpleGrantedAuthority(role.getName()))
.collect(Collectors.toSet());
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
#Override
public String toString() {
return "SecurityUser{" +
"user=" + user +
'}';
}
}
Depending on how your security configuration is set up, you can use authentication.getName(), as it usually maps to the username field. This would be the case with formLogin() for example, which uses the DaoAuthenticationProvider under the covers.

How to resolve getPrincipal() method error

While accessing the services using JWT token i was trying to print auth.getPrincipal() method it returning packageName.model.CustomUserDetails#3f97b72b instead of the UserDto details.
CustomUserDetails
public class CustomUserDetails implements UserDetails {
private static final long serialVersionUID = 8632209412694363798L;
private UsersDto userDto;
private UserEntity user;
public CustomUserDetails(UsersDto userDto) {
super();
this.userDto = userDto;
}
public UsersDto getUserDto() {
return userDto;
}
public void setUserDto(UsersDto userDto) {
this.userDto = userDto;
}
public CustomUserDetails(UserEntity user) {
this.user = user;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
// UserRole role = userDto.getRole();
// authorities.add(new SimpleGrantedAuthority(role.name()));
// return authorities;
return null;
}
#Override
public String getPassword() {
return user.getPassword();
}
#Override
public String getUsername() {
return user.getEmail();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
UsersDto
#Data
#NoArgsConstructor
#AllArgsConstructor
public class UsersDto extends User {
private Integer userId;
public UserEntity convertToUserEntity() throws NoSuchAlgorithmException {
UserEntity user=new UserEntity();
user.setUserId(this.userId);
user.setName(this.getName());
user.setEmail(this.getEmail());
user.setDateAdded(this.getDateAdded());
user.setDateModified(this.getDateModified());
user.setPassword(this.getPassword());
user.setPassword(this.getPassword());
return user;
}
}
UserController
#GetMapping("/getUser/{userId}")
public ResponseEntity<SuccessResponse> getuser(#PathVariable Integer userId,Authentication auth) throws Exception{
System.out.println(auth);
System.out.println(auth.getPrincipal());
UsersDto userFromAuth = ((CustomUserDetails) auth.getPrincipal()).getUserDto();
return ResponseEntity
.ok(new SuccessResponse(HttpStatus.OK.value(), SuccessMessage.SUCCESS,
userService.getUserById(userId)));
}
error
**packagename.CustomUserDetails#3f97b72b**
Instead of class details I want userdetails but it returning className with uniformed number so when i store this data into a variable it always stores NULL values.

AuthenticationManager returning Bad Credentials

I have this error and I don't know what it could be. I'm following a tutorial to do the User authentication, But when I try to do the authentication it throws a "Bad credentials" but the credentials are right. I'm using MongoDB.
From the tutorial I'm following with these steps it should work (other users confirmed that they did) but the only thing I did differently from the tutorial is in the "ClientEntity" class that already existed and I just implemented what I needed.
User return:
ClientEntity(id=63166ddbe3ea6c4fffd70818, clientName=Test, clientCpf=000.000.000-00, clientEmail=teste2#example.com, clientPassword=2b598e4c0e79baf9dc9211ad303e7626, clientIsBlocked=false, clientBirthDate=1989-05-20, creditCards=[CreditCardEntity()], clientCategory=[ACAO, COMEDIA])
My request to signin, I'm logging in by email and password:
AccountCredentials: AccountCredentials(email=teste2#example.com, password=2b598e4c0e79baf9dc9211ad303e7626)
I know the problem is in that class in "authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(email, password));" but I don't know how to solve it, because the credentials are correct
My AuthService class:
#Service
public class AuthService {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private JwtTokenProvider tokenProvider;
#Autowired
private ClientRepository repository;
public ResponseEntity signin(AccountCredentials data) {
try {
var email = data.getEmail();
var password = data.getPassword();
log.info("METODO SIGNIN, AccountCredentials: " + data);
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(email, password));
log.info("FOI AUTENTICADO!");
var user = repository.findByClientEmail(email);
log.info("O valor de User é: " + user);
var tokenResponse = new Token();
if (user != null) {
tokenResponse = tokenProvider.createAccessToken(email, user.getRoles());
} else {
throw new UsernameNotFoundException("Email " + email + " not found!");
}
return ResponseEntity.ok(tokenResponse);
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println(e.getCause());
System.out.println(e.getLocalizedMessage());
throw new BadCredentialsException("Invalid email/password supplied!");
}
}
public ResponseEntity refreshToken(String email, String refreshToken) {
var user = repository.findByClientEmail(email);
var tokenResponse = new Token();
if (user != null) {
tokenResponse = tokenProvider.refreshToken(refreshToken);
} else {
throw new UsernameNotFoundException("Email " + email + " not found!");
}
return ResponseEntity.ok(tokenResponse);
}
}
My ClientEntity:
#Data
#Document(collection = "Client")
public class ClientEntity implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
#Id
private String id;
private String clientName;
private String clientCpf;
private String clientEmail;
private String clientPassword;
private boolean clientIsBlocked = false;
private LocalDate clientBirthDate;
private List<CreditCardEntity> creditCards;
private List<ClientCategoryEnum> clientCategory;
private List<Permission> permissions;
public List<String> getRoles() {
List<String> roles = new ArrayList<>();
for (Permission permission : permissions) {
roles.add("USER");
roles.add(permission.getDescription());
}
return roles;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.permissions;
}
#Override
public String getPassword() {
return this.clientPassword;
}
#Override
public String getUsername() {
return this.clientEmail;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
My Class Permission:
#Data
#Document(collection = "Roles")
public class Permission implements GrantedAuthority, Serializable {
private static final long serialVersionUID = 1L;
#Id
private Long id;
private String description;
#Override
public String getAuthority() {
return this.description;
}
}
My SecurityConfig:
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtTokenProvider tokenProvider;
/*
#Bean
public UserDetailsService userDetailsService() {
return super.userDetailsService();
}
*/
#Bean
public PasswordEncoder passwordEncoder() {
Map<String, PasswordEncoder> encoders = new HashMap<>();
encoders.put("pbkdf2", new Pbkdf2PasswordEncoder());
DelegatingPasswordEncoder passwordEncoder = new DelegatingPasswordEncoder("pbkdf2", encoders);
passwordEncoder.setDefaultPasswordEncoderForMatches(new Pbkdf2PasswordEncoder());
return passwordEncoder;
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(
"/auth/signin",
"/auth/refresh"
).permitAll()
.antMatchers("/api/movie_search/**").authenticated()
.and()
.cors()
.and()
.apply(new JwtConfigurer(tokenProvider));
}
}
My CLass TokenProvider:
#Service
public class JwtTokenProvider{
#Value("${security.jwt.token.secret-key:secret}")
private String secretKey = "secret";
#Value("${security.jwt.token.expire-length:3600000}")
private long validityInMilliseconds = 3600000; // 1h
#Autowired
private UserDetailsService userDetailsService;
Algorithm algorithm = null;
#PostConstruct
protected void init() {
secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
algorithm = Algorithm.HMAC256(secretKey.getBytes());
}
public Token createAccessToken(String email, List<String> roles) {
Date now = new Date();
Date validity = new Date(now.getTime() + validityInMilliseconds);
var accessToken = getAccessToken(email, roles, now, validity);
var refreshToken = getRefreshToken(email, roles, now);
return new Token(email, true, now, validity, accessToken, refreshToken);
}
public Token refreshToken(String refreshToken) {
if (refreshToken.contains("Bearer ")) refreshToken =
refreshToken.substring("Bearer ".length());
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT decodedJWT = verifier.verify(refreshToken);
String email = decodedJWT.getSubject();
List<String> roles = decodedJWT.getClaim("roles").asList(String.class);
return createAccessToken(email, roles);
}
private String getAccessToken(String email, List<String> roles, Date now, Date validity) {
String issuerUrl = ServletUriComponentsBuilder
.fromCurrentContextPath().build().toUriString();
return JWT.create()
.withClaim("roles", roles)
.withIssuedAt(now)
.withExpiresAt(validity)
.withSubject(email)
.withIssuer(issuerUrl)
.sign(algorithm)
.strip();
}
private String getRefreshToken(String email, List<String> roles, Date now) {
Date validityRefreshToken = new Date(now.getTime() + (validityInMilliseconds * 3));
return JWT.create()
.withClaim("roles", roles)
.withIssuedAt(now)
.withExpiresAt(validityRefreshToken)
.withSubject(email)
.sign(algorithm)
.strip();
}
public Authentication getAuthentication(String token) {
DecodedJWT decodedJWT = decodedToken(token);
UserDetails userDetails = this.userDetailsService
.loadUserByUsername(decodedJWT.getSubject());
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
}
private DecodedJWT decodedToken(String token) {
Algorithm alg = Algorithm.HMAC256(secretKey.getBytes());
JWTVerifier verifier = JWT.require(alg).build();
DecodedJWT decodedJWT = verifier.verify(token);
return decodedJWT;
}
public String resolveToken(HttpServletRequest req) {
String bearerToken = req.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring("Bearer ".length());
}
return null;
}
public boolean validateToken(String token) {
DecodedJWT decodedJWT = decodedToken(token);
try {
if (decodedJWT.getExpiresAt().before(new Date())) {
return false;
}
return true;
} catch (Exception e) {
throw new InvalidJwtAuthenticationException("Expired or invalid JWT token!");
}
}
}
My ClientService:
#Service
public class ClientService implements UserDetailsService {
private final ClientRepository clientRepository;
private final ModelMapper modelMapper;
#Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
var user = clientRepository.findByClientEmail(email);
if (user != null) {
return user;
} else {
throw new UsernameNotFoundException("Email " + email + " not found!");
}
}
}
In debug I came across this:
UsernamePasswordAuthenticationToken
Credentials=[PROTECTED], Authenticated=false, Details=null, Granted Authorities=[]]
Short answer: Passwords stored in your DB must be encrypted by PasswordEncoder.
Long answer:
You created a bean of type PasswordEncoder, so it is used by AuthenticationProvider when you call .authenticate() method of AuthenticationManager class.
As stated in java docs, DelegatingPasswordEncoder expects your passwords to be stored in DB in format like this:
{encoderId}encryptedPassword
You use pbkdf2 password encoder as a default encoder, so passwords in DB should look like this:
{pbkdf2}encryptedPassword
By the look of the returned ClientEntity, you haven't used the PasswordEncoder when you saved this entity to a DB, so the raw password is stored instead of an encrypted one.
The authentication flow should look like this:
your app registers a user, stores his password in DB in encrypted form using PasswordEncoder bean;
user passes his username (email or whatever is neccessary) and raw password to your app through login form of API endpoint;
AuthenticationProvider retrieves encrypted password from the DB and compares it with the raw password the user has provided

Error creating bean with name 'registrationListener': Unsatisfied dependency expressed through field 'service' (Showing this after building war)

These codes runs fine on my STS but not running after making jar/war.
also tried with deploying on external tomcat. what is making the differace after making the war?? i am getting lost.
This is the registration listener class
#Component
public class RegistrationListener implements ApplicationListener<OnRegistrationCompleteEvent> {
#Autowired
private IUserService service;
#Autowired
private MessageSource messages;
#Autowired
private JavaMailSender mailSender;
#Autowired
private Environment env;
// API
#Override
public void onApplicationEvent(final OnRegistrationCompleteEvent event) {
this.confirmRegistration(event);
}
private void confirmRegistration(final OnRegistrationCompleteEvent event) {
final User user = event.getUser();
final String token = UUID.randomUUID().toString();
service.createVerificationTokenForUser(user, token);
final SimpleMailMessage email = constructEmailMessage(event, user, token);
mailSender.send(email);
}
//
private SimpleMailMessage constructEmailMessage(final OnRegistrationCompleteEvent event, final User user, final String token) {
final String recipientAddress = user.getEmail();
final String subject = "Registration Confirmation";
final String confirmationUrl = event.getAppUrl() + "/registrationConfirm?token=" + token;
String message= "Your SECRET for Google Authenticator: "+user.getSecret()+"\n";
message+= messages.getMessage("message.regSuccLink", null, "You registered successfully. To confirm your registration, please click on the below link.", event.getLocale());
final SimpleMailMessage email = new SimpleMailMessage();
email.setTo(recipientAddress);
email.setSubject(subject);
email.setText(message + " \r\n" + confirmationUrl);
email.setFrom(env.getProperty("support.email"));
return email;
}
}
I have tried with #Service and without #Service tag
#Service
public interface IUserService {
User registerNewUserAccount(UserDto accountDto);
User getUser(String verificationToken);
void saveRegisteredUser(User user);
void deleteUser(User user);
void createVerificationTokenForUser(User user, String token);
VerificationToken getVerificationToken(String VerificationToken);
VerificationToken generateNewVerificationToken(String token);
void createPasswordResetTokenForUser(User user, String token);
User findUserByEmail(String email);
PasswordResetToken getPasswordResetToken(String token);
Optional<User> getUserByPasswordResetToken(String token);
Optional<User> getUserByID(long id);
void changeUserPassword(User user, String password);
boolean checkIfValidOldPassword(User user, String password);
String validateVerificationToken(String token);
String generateQRUrl(User user) throws UnsupportedEncodingException;
User updateUser2FA(boolean use2FA);
List<String> getUsersFromSessionRegistry();
NewLocationToken isNewLoginLocation(String username, String ip);
String isValidNewLocationToken(String token);
void addUserLocation(User user, String ip);
}
is this where the problem is happening?
#Service
#Transactional
public class UserService implements IUserService {
#Autowired
private UserRepository userRepository;
#Autowired
private VerificationTokenRepository tokenRepository;
#Autowired
private PasswordResetTokenRepository passwordTokenRepository;
#Autowired
private PasswordEncoder passwordEncoder;
#Autowired
private RoleRepository roleRepository;
#Autowired
private SessionRegistry sessionRegistry;
#Autowired
#Qualifier("GeoIPCountry")
private DatabaseReader databaseReader;
#Autowired
private UserLocationRepository userLocationRepository;
#Autowired
private NewLocationTokenRepository newLocationTokenRepository;
#Autowired
private Environment env;
public static final String TOKEN_INVALID = "invalidToken";
public static final String TOKEN_EXPIRED = "expired";
public static final String TOKEN_VALID = "valid";
public static String QR_PREFIX = "https://chart.googleapis.com/chart?chs=200x200&chld=M%%7C0&cht=qr&chl=";
public static String APP_NAME = "SpringRegistration";
// API
#Override
public User registerNewUserAccount(final UserDto accountDto) {
if (emailExists(accountDto.getEmail())) {
throw new UserAlreadyExistException("There is an account with that email address: " + accountDto.getEmail());
}
final User user = new User();
user.setFirstName(accountDto.getFirstName());
user.setLastName(accountDto.getLastName());
user.setPassword(passwordEncoder.encode(accountDto.getPassword()));
user.setEmail(accountDto.getEmail());
user.setUsing2FA(accountDto.isUsing2FA());
user.setRoles(Arrays.asList(roleRepository.findByName("ROLE_USER")));
return userRepository.save(user);
}
#Override
public User getUser(final String verificationToken) {
final VerificationToken token = tokenRepository.findByToken(verificationToken);
if (token != null) {
return token.getUser();
}
return null;
}
#Override
public VerificationToken getVerificationToken(final String VerificationToken) {
return tokenRepository.findByToken(VerificationToken);
}
#Override
public void saveRegisteredUser(final User user) {
userRepository.save(user);
}
#Override
public void deleteUser(final User user) {
final VerificationToken verificationToken = tokenRepository.findByUser(user);
if (verificationToken != null) {
tokenRepository.delete(verificationToken);
}
final PasswordResetToken passwordToken = passwordTokenRepository.findByUser(user);
if (passwordToken != null) {
passwordTokenRepository.delete(passwordToken);
}
userRepository.delete(user);
}
#Override
public void createVerificationTokenForUser(final User user, final String token) {
final VerificationToken myToken = new VerificationToken(token, user);
tokenRepository.save(myToken);
}
#Override
public VerificationToken generateNewVerificationToken(final String existingVerificationToken) {
VerificationToken vToken = tokenRepository.findByToken(existingVerificationToken);
vToken.updateToken(UUID.randomUUID()
.toString());
vToken = tokenRepository.save(vToken);
return vToken;
}
#Override
public void createPasswordResetTokenForUser(final User user, final String token) {
final PasswordResetToken myToken = new PasswordResetToken(token, user);
passwordTokenRepository.save(myToken);
}
#Override
public User findUserByEmail(final String email) {
return userRepository.findByEmail(email);
}
#Override
public PasswordResetToken getPasswordResetToken(final String token) {
return passwordTokenRepository.findByToken(token);
}
#Override
public Optional<User> getUserByPasswordResetToken(final String token) {
return Optional.ofNullable(passwordTokenRepository.findByToken(token) .getUser());
}
#Override
public Optional<User> getUserByID(final long id) {
return userRepository.findById(id);
}
#Override
public void changeUserPassword(final User user, final String password) {
user.setPassword(passwordEncoder.encode(password));
userRepository.save(user);
}
#Override
public boolean checkIfValidOldPassword(final User user, final String oldPassword) {
return passwordEncoder.matches(oldPassword, user.getPassword());
}
#Override
public String validateVerificationToken(String token) {
final VerificationToken verificationToken = tokenRepository.findByToken(token);
if (verificationToken == null) {
return TOKEN_INVALID;
}
final User user = verificationToken.getUser();
final Calendar cal = Calendar.getInstance();
if ((verificationToken.getExpiryDate()
.getTime() - cal.getTime()
.getTime()) <= 0) {
tokenRepository.delete(verificationToken);
return TOKEN_EXPIRED;
}
user.setEnabled(true);
// tokenRepository.delete(verificationToken);
userRepository.save(user);
return TOKEN_VALID;
}
#Override
public String generateQRUrl(User user) throws UnsupportedEncodingException {
return QR_PREFIX + URLEncoder.encode(String.format("otpauth://totp/%s:%s?secret=%s&issuer=%s", APP_NAME, user.getEmail(), user.getSecret(), APP_NAME), "UTF-8");
}
#Override
public User updateUser2FA(boolean use2FA) {
final Authentication curAuth = SecurityContextHolder.getContext()
.getAuthentication();
User currentUser = (User) curAuth.getPrincipal();
currentUser.setUsing2FA(use2FA);
currentUser = userRepository.save(currentUser);
final Authentication auth = new UsernamePasswordAuthenticationToken(currentUser, currentUser.getPassword(), curAuth.getAuthorities());
SecurityContextHolder.getContext()
.setAuthentication(auth);
return currentUser;
}
private boolean emailExists(final String email) {
return userRepository.findByEmail(email) != null;
}
#Override
public List<String> getUsersFromSessionRegistry() {
return sessionRegistry.getAllPrincipals()
.stream()
.filter((u) -> !sessionRegistry.getAllSessions(u, false)
.isEmpty())
.map(o -> {
if (o instanceof User) {
return ((User) o).getEmail();
} else {
return o.toString()
;
}
}).collect(Collectors.toList());
}
#Override
public NewLocationToken isNewLoginLocation(String username, String ip) {
if(!isGeoIpLibEnabled()) {
return null;
}
try {
final InetAddress ipAddress = InetAddress.getByName(ip);
final String country = databaseReader.country(ipAddress)
.getCountry()
.getName();
System.out.println(country + "====****");
final User user = userRepository.findByEmail(username);
final UserLocation loc = userLocationRepository.findByCountryAndUser(country, user);
if ((loc == null) || !loc.isEnabled()) {
return createNewLocationToken(country, user);
}
} catch (final Exception e) {
return null;
}
return null;
}
#Override
public String isValidNewLocationToken(String token) {
final NewLocationToken locToken = newLocationTokenRepository.findByToken(token);
if (locToken == null) {
return null;
}
UserLocation userLoc = locToken.getUserLocation();
userLoc.setEnabled(true);
userLoc = userLocationRepository.save(userLoc);
newLocationTokenRepository.delete(locToken);
return userLoc.getCountry();
}
#Override
public void addUserLocation(User user, String ip) {
if(!isGeoIpLibEnabled()) {
return;
}
try {
final InetAddress ipAddress = InetAddress.getByName(ip);
final String country = databaseReader.country(ipAddress)
.getCountry()
.getName();
UserLocation loc = new UserLocation(country, user);
loc.setEnabled(true);
userLocationRepository.save(loc);
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
private boolean isGeoIpLibEnabled() {
return Boolean.parseBoolean(env.getProperty("geo.ip.lib.enabled"));
}
private NewLocationToken createNewLocationToken(String country, User user) {
UserLocation loc = new UserLocation(country, user);
loc = userLocationRepository.save(loc);
final NewLocationToken token = new NewLocationToken(UUID.randomUUID()
.toString(), loc);
return newLocationTokenRepository.save(token);
}
}
This is my error from jar,war,extarnal tomcat
o.s.b.f.UnsatisfiedDependencyException: Error creating bean with name 'registrationListener': Unsatisfied dependency expressed through field 'service'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userService': Unsatisfied dependency expressed through field 'databaseReader'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'GeoIPCountry' defined in class path resource [com/birol/spring/SecSecurityConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.maxmind.geoip2.DatabaseReader]: Factory method 'databaseReader' threw exception; nested exception is java.io.FileNotFoundException: src\main\resources\maxmind\GeoLite2-Country.mmdb (The system cannot find the path specified)
at o.s.b.f.a.GbHi8bXhDyMP2m1NDUSiYmznAJdJzX36DDor$AutowiredFieldElement.resolveFieldValue(GbHi8bXhDyMP2m1NDUSiYmznAJdJzX36DDor.java:659)
at o.s.b.f.a.GbHi8bXhDyMP2m1NDUSiYmznAJdJzX36DDor$AutowiredFieldElement.inject(GbHi8bXhDyMP2m1NDUSiYmznAJdJzX36DDor.java:639)
at o.s.b.f.a.InjectionMetadata.inject(InjectionMetadata.java:119)
at o.s.b.f.a.GbHi8bXhDyMP2m1NDUSiYmznAJdJzX36DDor.postProcessProperties(GbHi8bXhDyMP2m1NDUSiYmznAJdJzX36DDor.java:399)
at o.s.b.f.s.GbHi8bXhDyMP2m1NDUSiYmznAJdJzX36DD.populateBean(GbHi8bXhDyMP2m1NDUSiYmznAJdJzX36DD.java:1431)
... 46 frames truncated

Jwt in Springboot v2.4.5

I have this RestController:
#RestController
#Slf4j
public class AuthenticationRestController {
#Value("${jwt.header}")
private String tokenHeader;
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Autowired
private UserSecurityService userSecurityService;
#Autowired
private EmailService emailService;
#PostMapping(path = "/api/v1/auth", consumes = "application/json", produces = "application/json")
public ResponseEntity<JwtAuthenticationResponse>
createAuthenticationToken( #RequestBody JwtAuthenticationRequest authenticationRequest,
HttpServletRequest request) throws AuthenticationException {
LOG.info("authenticating {} " , authenticationRequest.getUsername());
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
...
/**
* Authenticates the user. If something is wrong, an {#link AuthenticationException} will be thrown
*/
private void authenticate(String username, String password) {
Objects.requireNonNull(username);
Objects.requireNonNull(password);
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
e.printStackTrace();
throw new AuthenticationException("User is disabled!", e);
} catch (BadCredentialsException e) {
throw new AuthenticationException("Bad credentials!", e);
} catch (Exception e) {
e.printStackTrace();
}
}
}
but I have this error when logging:
org.springframework.security.authentication.DisabledException: User is disabled
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider$DefaultPreAuthenticationChecks.check(AbstractUserDetailsAuthenticationProvider.java:331)
at org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:146)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:182)
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:201)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:518)
at com.kispackp.security.controllers.AuthenticationRestController.authenticate(AuthenticationRestController.java:138)
and
#Entity
#Table(name="t_user")
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonIgnoreProperties(ignoreUnknown = true)
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
public class User implements Serializable, UserDetails {
/** The Serial Version UID for Serializable classes. */
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(unique = true)
#JsonIgnore
private String username;
#JsonIgnore
private String password;
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
}
This error happens when the user is not enabled. The interface UserDetails has a method called isEnabled, and it's checked when authenticating the user.
AbstractUserDetailsAuthenticationProvider.java
...
if (!user.isEnabled()) {
AbstractUserDetailsAuthenticationProvider.this.logger
.debug("Failed to authenticate since user account is disabled");
throw new DisabledException(AbstractUserDetailsAuthenticationProvider.this.messages
.getMessage("AbstractUserDetailsAuthenticationProvider.disabled", "User is disabled"));
}
...
You should implement it and return true in the case the user is enabled, like so:
public class User implements Serializable, UserDetails {
... your current fields and methods
#Override
public boolean isEnabled() {
return true;
}
}

Resources