I've been debugging for 10 hours and can't seem to figure out why I'm continuously getting bad credentials errors within Spring Security.
I can actually see that I'm grabbing the user from the database in my userdetailsservice. The passwords match up correctly (not hashing/encoding anything currently), but as I dive into the framework, I get the mismatch creds exception.
I'm honestly out of ideas, I feel like I have rewritten this code 3-4 times now, but to no avail.
I'm hitting /login to generate the token.
Jwt Security Config
import com.schachte.asciiphile.security.messaging.JwtAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity
#Configuration
#Order(1)
public class JwtSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String ROOT_CTX_MATCH_PATH = "/phile/**";
#Autowired
private JwtAuthenticationEntryPoint entryPoint;
#Qualifier("userDetailsServiceImpl")
#Autowired
private UserDetailsService userDetailsService;
#Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.addFilterBefore(new JwtLoginFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
http.headers().cacheControl();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
}
Jwt Login Filter
import com.fasterxml.jackson.databind.ObjectMapper;
import com.schachte.asciiphile.model.JwtAuthententicationToken;
import com.schachte.asciiphile.model.User;
import com.schachte.asciiphile.security.util.JwtGenerator;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.auth0.jwt.JWT;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import static com.auth0.jwt.algorithms.Algorithm.HMAC512;
import java.io.IOException;
import java.util.Date;
import java.util.List;
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {
private JwtGenerator jwtGenerator = new JwtGenerator();
private AuthenticationManager authenticationManager;
public JwtLoginFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(
HttpServletRequest req, HttpServletResponse res)
throws AuthenticationException {
User creds = null;
try {
creds = new ObjectMapper()
.readValue(req.getInputStream(), User.class);
} catch (IOException e) {
e.printStackTrace();
}
List<GrantedAuthority> grantedAuthorities = AuthorityUtils
.commaSeparatedStringToAuthorityList(creds.getRole());
return authenticationManager.authenticate(
new JwtAuthententicationToken(
creds.getUsername(),
creds.getPassword(),
grantedAuthorities
)
);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, auth);
String token = JWT.create()
.withSubject(((User) auth.getPrincipal()).getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + 864_000_000))
.sign(HMAC512("secret".getBytes()));
response.addHeader("Authorization", "Token " + token);
}
}
Jwt Authentication Token
import lombok.Data;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import java.util.List;
#Data
public class JwtAuthententicationToken extends UsernamePasswordAuthenticationToken {
private String username;
private String password;
private List<GrantedAuthority> grantedAuthorities;
public JwtAuthententicationToken(String username, String password, List<GrantedAuthority> grantedAuthorities) {
super(null, null);
this.username = username;
this.password = password;
this.grantedAuthorities = grantedAuthorities;
}
#Override
public Object getCredentials() {
return null;
}
#Override
public Object getPrincipal() {
return this.username;
}
}
Custom User Details
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
public class CustomUserDetails extends User implements UserDetails {
private Collection<? extends GrantedAuthority> authorities;
public CustomUserDetails(final User user, Collection<? extends GrantedAuthority> authorities) {
super(user);
this.authorities = authorities;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
#Override
public String getUsername() {
return super.getUsername();
}
#Override
public String getPassword() {
return super.getPassword();
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
User
import javax.persistence.*;
import lombok.Data;
#Entity
#Data
public class User {
public User() {}
public User(String username, String pass, String role) {
this.username = username;
this.password = pass;
this.role = role;
}
public User(User username) {
this.email = username.getEmail();
this.password = username.getPassword();
this.premium = username.getPremium();
this.storedBytes = username.getStoredBytes();
this.username = username.getUsername();
}
#Id
#Column(name = "username")
private String username;
#Column(name = "password")
private String password;
#Column(name = "email")
private String email;
#Column(name = "premium")
private int premium;
#Column(name = "storedbytes")
private int storedBytes;
#Column(name = "role")
private String role;
}
User Detail Service
import com.schachte.asciiphile.model.CustomUserDetails;
import com.schachte.asciiphile.model.User;
import com.schachte.asciiphile.repository.UserRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Optional;
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
private UserRepo applicationUserRepository;
public UserDetailsServiceImpl(UserRepo applicationUserRepository) {
this.applicationUserRepository = applicationUserRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<User> applicationUser = applicationUserRepository.findByUsername(username);
if (!applicationUser.isPresent()) {
throw new UsernameNotFoundException(username);
}
return new CustomUserDetails(applicationUser.get(), AuthorityUtils
.commaSeparatedStringToAuthorityList(applicationUser.get().getRole()));
}
}
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 21 days ago.
Improve this question
I've been trying to create a spring security logic to authorize users (inserted into my database) to do different things based on their roles (simple). I'm supposed to have ROLE_USER and ROLE_ADMIN, but I don't think any of them work. Please help. I'll try to put every bit of important code here (even the imports).
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.security.core.GrantedAuthority;
import com.vitoria.enums.RoleName;
#Entity
#Table(name = "TB_ROLE")
public class RoleModel implements GrantedAuthority, Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID roleId;
#Enumerated(EnumType.STRING)
#Column(nullable = false, unique = true)
private RoleName roleName;
#Override
public String getAuthority() {
return this.roleName.toString();
}
public UUID getRoleId() {
return roleId;
}
public void setRoleId(UUID roleId) {
this.roleId = roleId;
}
public RoleName getRoleName() {
return roleName;
}
public void setRoleName(RoleName roleName) {
this.roleName = roleName;
}
}
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
#Entity
#Table(name = "TB_USER")
public class UserModel implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private UUID userId;
#Column(nullable = false, unique = true)
private String username;
#Column(nullable = false)
private String password;
#ManyToMany
#JoinTable(name = "TB_USERS_ROLES",
joinColumns = #JoinColumn(name = "user_id"),
inverseJoinColumns = #JoinColumn(name = "role_id"))
private List<RoleModel> roles;
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles;
}
#Override
public String getPassword() {
return this.password;
}
#Override
public String getUsername() {
return this.username;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
public enum RoleName {
ROLE_ADMIN,
ROLE_USER;
}
import javax.transaction.Transactional;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import com.vitoria.models.UserModel;
import com.vitoria.repositories.UserRepository;
#Service
#Transactional
public class UserDetailsServiceImpl implements UserDetailsService {
final UserRepository userRepository;
public UserDetailsServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserModel userModel = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
return new User(userModel.getUsername(), userModel.getPassword(), true, true, true,true, userModel.getAuthorities());
}
}
import org.springframework.data.jpa.repository.JpaRepository;
import com.vitoria.models.RoleModel;
public interface RoleRepository extends JpaRepository<RoleModel, Long> {
RoleModel findByRoleName(String roleName);
}
import java.util.Optional;
import java.util.UUID;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.vitoria.models.UserModel;
#Repository
public interface UserRepository extends JpaRepository<UserModel, UUID> {
Optional<UserModel> findByUsername(String username);
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.httpBasic()
.and()
.authorizeHttpRequests()
.anyRequest().authenticated()
.and()
.csrf().disable();
return http.build();
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.vitoria.models.Flowers;
import com.vitoria.repositories.FlowersRepository;
#RestController
#CrossOrigin(origins = "*", maxAge = 3600)
#EnableAutoConfiguration
#RequestMapping("/flowers")
public class FlowersController {
#Autowired
private FlowersRepository repo;
#PreAuthorize("hasRole('ROLE_USER')")
#GetMapping
public ResponseEntity<List<Flowers>> findAll(){
List<Flowers> allFlowers=repo.findAll();
return ResponseEntity.ok().body(allFlowers);
}
#PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
#PostMapping("/insert")
public ResponseEntity<Flowers> insert(#RequestBody Flowers flower){
Flowers entity=flower;
repo.save(entity);
return ResponseEntity.ok().body(entity);
}
#PreAuthorize("hasRole('ROLE_ADMIN')")
#DeleteMapping("/delete/{id}")
public ResponseEntity<Void> deleteById(#PathVariable Integer id){
repo.deleteById(id);
return ResponseEntity.noContent().build();
}
}
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.vitoria.models.UserModel;
import com.vitoria.repositories.UserRepository;
#RestController
#RequestMapping("/users")
public class UserController {
#Autowired
private UserRepository repo;
#PreAuthorize("hasAnyRole('ROLE_ADMIN', 'ROLE_USER')")
#GetMapping
public ResponseEntity<List<UserModel>> findAll(){
List<UserModel> users=repo.findAll();
return ResponseEntity.ok().body(users);
}
#PreAuthorize("hasRole('ROLE_USER')")
#GetMapping("/{username}")
public ResponseEntity<Optional<UserModel>> findByUsername(#RequestParam("username")String username){
Optional<UserModel> user=repo.findByUsername(username);
return ResponseEntity.ok().body(user);
}
#PreAuthorize("hasRole('ROLE_ADMIN')")
#PostMapping("/save")
public ResponseEntity<UserModel> insert(#RequestBody UserModel user){
UserModel entity=user;
user.setPassword(passwordEncoder().encode(user.getPassword()));
repo.save(entity);
return ResponseEntity.ok().body(entity);
}
private PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
my database looks like this:
tb_user
tb_role
tb_users_roles
I think this is all.
Please keep in mind that when I try to make ->any<- request to any endpoint it comesback unauthorized. SO, I tried something else: taking off the role permission (using the #PreAuthorize("permitAll()")) of get all users and I still get 401 as return! Please please help me.
While hit login url in postman the above error occurs ..the concept is want to generate jwt token using cookies .am new to Springboot ..please help me to get out from this issue..The configuration am using was SpringBoot version:3.0.1 and java version 17
here i attach the configuration files used .
AuthEntryPointJwt.java:
import java.io.IOException;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
#Component
public class AuthEntryPointJwt extends ResponseEntityExceptionHandler implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
final Map<String, Object> body = Map.of("status", HttpServletResponse.SC_UNAUTHORIZED, "error", "Unauthorized",
"message", authException.getMessage(), "path", request.getServletPath());
final ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getOutputStream(), body);
}
}
AuthTokenFilter.java:
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;
import com.midfin.erp.impl.UserDetailsServiceImpl;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class AuthTokenFilter extends OncePerRequestFilter {
#Autowired
private JwtUtils jwtUtils;
#Autowired
private UserDetailsServiceImpl userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class);
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
String jwt = parseJwt(request);
if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
logger.error("Cannot set user authentication: {}", e);
}
filterChain.doFilter(request, response);
}
private String parseJwt(HttpServletRequest request) {
String jwt = jwtUtils.getJwtFromCookies(request);
return jwt;
}
}
JwtUtils.java:
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Component;
import org.springframework.web.util.WebUtils;
import com.midfin.erp.impl.UserDetailsImpl;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
#Component
public class JwtUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
#Value("${jwt.secret}")
private String jwtSecret;
#Value("${jwt.expirationMs}")
private int jwtExpirationMs;
#Value("${jwt.cookieName}")
private String jwtCookie;
public String getJwtFromCookies(HttpServletRequest request) {
Cookie cookie = WebUtils.getCookie(request, jwtCookie);
if (cookie != null) {
return cookie.getValue();
} else {
return null;
}
}
public ResponseCookie generateJwtCookie(UserDetailsImpl userPrincipal) {
String jwt = generateTokenFromUsername(userPrincipal.getUsername());
System.out.println(jwt);
ResponseCookie cookie = ResponseCookie.from(jwtCookie, jwt).path("/api").maxAge(24 * 60 * 60).httpOnly(true)
.build();
return cookie;
}
public ResponseCookie getCleanJwtCookie() {
ResponseCookie cookie = ResponseCookie.from(jwtCookie, null).path("/api").build();
return cookie;
}
public String getUserNameFromJwtToken(String token) {
return Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject();
}
public boolean validateJwtToken(String authToken) {
try {
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
return true;
} catch (SignatureException e) {
logger.error("Invalid JWT signature: {}", e.getMessage());
} catch (MalformedJwtException e) {
logger.error("Invalid JWT token: {}", e.getMessage());
} catch (ExpiredJwtException e) {
logger.error("JWT token is expired: {}", e.getMessage());
} catch (UnsupportedJwtException e) {
logger.error("JWT token is unsupported: {}", e.getMessage());
} catch (IllegalArgumentException e) {
logger.error("JWT claims string is empty: {}", e.getMessage());
}
return false;
}
public String generateTokenFromUsername(String username) {
return Jwts.builder().setSubject(username).setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(SignatureAlgorithm.HS512, jwtSecret).compact();
}
}
WebSecurityConfig.java:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.midfin.erp.impl.UserDetailsServiceImpl;
#Configuration
#EnableMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {
#Autowired
UserDetailsServiceImpl userDetailsService;
#Autowired
private AuthEntryPointJwt unauthorizedHandler;
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(bCryptPasswordEncoder);
return authProvider;
}
#Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeHttpRequests().requestMatchers("/api/auth/**").permitAll()
.anyRequest().authenticated();
http.authenticationProvider(authenticationProvider());
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
#Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy = "ROLE_ADMIN > ROLE_USER";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
}
UserDetailsImpl.java:
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.midfin.erp.domain.UserPrivilege;
import com.midfin.erp.domain.UserRole;
import com.midfin.erp.domain.Users;
import lombok.Data;
#Data
public class UserDetailsImpl implements UserDetails {
private static final long serialVersionUID = 1L;
private Long userId;
private String username;
private String email;
private String fullName;
private String mobileNumber;
private String password;
private boolean locked;
private Collection<? extends GrantedAuthority> authorities;
public UserDetailsImpl(Long userId, String username, String email, String password, String fullName,
String mobileNumber, Boolean locked, Collection<? extends GrantedAuthority> authorities) {
this.userId = userId;
this.username = username;
this.email = email;
this.password = password;
this.mobileNumber = mobileNumber;
this.fullName = fullName;
this.locked = locked;
this.authorities = authorities;
}
public static UserDetailsImpl build(Users user) {
List<GrantedAuthority> authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName())).collect(Collectors.toList());
return new UserDetailsImpl(user.getUserId(), user.getUsername(), user.getEmail(), user.getPassword(),
user.getMobileNumber(), user.getFullName(), user.getIslocked(), authorities);
}
#Override
public String getPassword() {
return this.password;
}
#Override
public String getUsername() {
return this.username;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return !this.locked;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
private List<String> getPrivileges(Collection<UserRole> roles) {
List<String> privileges = new ArrayList<>();
List<UserPrivilege> collection = new ArrayList<>();
for (UserRole role : roles) {
privileges.add(role.getName());
collection.addAll(role.getPrivileges());
}
for (UserPrivilege item : collection) {
privileges.add(item.getName());
}
return privileges;
}
private List<GrantedAuthority> getGrantedAuthorities(List<String> privileges) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (String privilege : privileges) {
authorities.add(new SimpleGrantedAuthority(privilege));
}
return authorities;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
}
UserDetailsServiceImpl.java:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.midfin.erp.domain.Users;
import com.midfin.erp.repo.UserRepo;
#Service
public class UserDetailsServiceImpl implements UserDetailsService {
#Autowired
UserRepo userRepo;
#Override
#Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Users user = userRepo.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
return UserDetailsImpl.build(user);
}
}
If you look closely at your logs, you'll see something like this: java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter
This is because the io.jsonwebtoken dependency uses javax.xml.bind.DatatypeConverter, but in spring version 3 it no longer uses the name javax but jakarta
As mentioned https://stackoverflow.com/a/75203778/9718846 you need to add the 0.11.5 dependencies. For maven, the answer is here : https://github.com/jwtk/jjwt#features
I created very simple site where everybody can access /about, authenticated users can access /profile and only user with "ADMIN" role can access. I added one "ADMIN" user in the DBInit.java Then I try to access /admin and I get an http basic login form. I enter adminEmail as login and admin123 as password and I can't access /admin page. So somewhere is an error in my code, and I can see it. So where is an error and how to get rid of it?
If I use in memory authentication everything works well.
// In memory authentication
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
// auth.authenticationProvider(authenticationProvider());
auth.inMemoryAuthentication()
.withUser("admin")
.password(passwordEncoder().encode("admin"))
.roles("ADMIN");
}
SecurityConfiguration.java
import Onlinestore.service.UserPrincipalDetailsService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
private UserPrincipalDetailsService userPrincipalDetailsService;
public SecurityConfiguration(UserPrincipalDetailsService userPrincipalDetailsService)
{
this.userPrincipalDetailsService = userPrincipalDetailsService;
}
#Override
protected void configure(AuthenticationManagerBuilder auth)
{
auth.authenticationProvider(authenticationProvider());
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers("/about").permitAll()
.antMatchers("/profile").authenticated()
.antMatchers("/admin/**").hasRole("ADMIN")
.and()
.httpBasic();
}
#Bean
DaoAuthenticationProvider authenticationProvider()
{
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
daoAuthenticationProvider.setUserDetailsService(userPrincipalDetailsService);
return daoAuthenticationProvider;
}
#Bean
public PasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
}
}
User.java
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
#Entity(name = "user")
#Table(name = "users")
#NoArgsConstructor
public class User
{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Getter
#Setter
private int id;
#Getter
#Setter
#Column(nullable = false)
private String name;
#Getter
#Setter
private String surname;
#Getter
#Setter
#Column(nullable = false)
private String password;
#Getter
#Setter
#Column(name = "telephone_number", nullable = false)
private String telephoneNumber;
#Getter
#Setter
#Column(unique = true)
private String email;
#Getter
#Setter
private String country;
#Getter
#Setter
private String address;
#Getter
#Setter
// delimiter = ";"
private String roleNames;
public User(String name, String surname, String password, String telephoneNumber, String email, String country, String address, String roleNames)
{
this.name = name;
this.surname = surname;
this.password = password;
this.telephoneNumber = telephoneNumber;
this.email = email;
this.country = country;
this.address = address;
this.roleNames = roleNames;
}
}
UserPrincipal.java
import Onlinestore.entity.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class UserPrincipal implements UserDetails
{
private User user;
public UserPrincipal(User user)
{
this.user = user;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities()
{
String[] roles = user.getRoleNames().split(";");
List<GrantedAuthority> authorities = new ArrayList<>();
for (String role : roles)
{
authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
}
#Override
public String getPassword()
{
return user.getPassword();
}
#Override
public String getUsername()
{
return user.getName();
}
#Override
public boolean isAccountNonExpired()
{
return false;
}
#Override
public boolean isAccountNonLocked()
{
return false;
}
#Override
public boolean isCredentialsNonExpired()
{
return false;
}
#Override
public boolean isEnabled()
{
return false;
}
}
UserPrincipalDetailsService.java
import Onlinestore.entity.User;
import Onlinestore.repository.UserRepository;
import Onlinestore.security.UserPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
#Service
public class UserPrincipalDetailsService implements UserDetailsService
{
private UserRepository userRepository;
public UserPrincipalDetailsService(UserRepository userRepository)
{
this.userRepository = userRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
User user = userRepository.findUserByEmail(username);
return new UserPrincipal(user);
}
}
DBInit.java
import Onlinestore.entity.User;
import Onlinestore.repository.UserRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
#Service
public class DBInit implements CommandLineRunner
{
private UserRepository userRepository;
private PasswordEncoder passwordEncoder;
public DBInit(UserRepository userRepository, PasswordEncoder passwordEncoder)
{
this.userRepository = userRepository;
this.passwordEncoder = passwordEncoder;
}
#Override
public void run(String[] args)
{
User user1 = new User("admin", "admin", passwordEncoder.encode("admin123"),
"+111111111", "adminEmail", "country1", "address1", "ADMIN");
List<User> users = Arrays.asList(user1);
userRepository.saveAll(users);
}
}
UserRepository
import Onlinestore.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface UserRepository extends JpaRepository<User, Integer>
{
User findUserByEmail(String email);
}
In memory authentication expects hard coded credentials in the configuration. It does not pull credentials from the database.
If you want to use credentials from a database, the rest of your setup looks good at first glance. Try
httpSecurity
.authorizeRequests()
.antMatchers(PUBLIC_MATCHERS)
.permitAll()
.anyRequest()
.authenticated();
Where PUBLIC_MATCHERS is an array of endpoints that do not require authentication, if you have such a thing.
I had found all errors.
In class UserPrincipal I had to override this methods and return true, but not return false. I think when I return false Spring Security thinks the user is blocked, expired, disabled and so on and blocks authentication.
This but there also some errors and application yet not working as I wanted to.
Proper implementation of methods in UserPrincipal
#Override
public boolean isAccountNonExpired()
{
return true;
}
#Override
public boolean isAccountNonLocked()
{
return true;
}
#Override
public boolean isCredentialsNonExpired()
{
return true;
}
#Override
public boolean isEnabled()
{
return true;
}
In class UserPrincipal I had to return user.getEmail() in getUserName(), but not return user.getName() because I use email as authentication username.
#Override
public String getUsername()
{
return user.getEmail();
}
In UserPrincipalDetailsService class in loadUserByUsername() I had to throw an exception UsernameNotFoundException when there is no user with such username
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
User user = userRepository.findUserByEmail(username);
if (user == null)
{
throw new UsernameNotFoundException("user not found");
}
return new UserPrincipal(user);
}
I have a spring controller that let's me sign in and supposed to return user details(roles, username) in response when entering correct credentials but instead only return the jwt token and username. Here's the api response:
{
"username": "adam",
"token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZGFtIiwicm9sZXMiOlsiUk9MRV9BRE1JTiJdLCJpYXQiOjE1NTcyMzUxMTMsImV4cCI6MTU1NzIzODcxM30.PksRTzgYu6r79KNmc4YDNXGqO1Ke63oOzzoPjURUY9k"
}
My controller:
package com.example.demo.controller;
import com.example.demo.domain.User;
import com.example.demo.repository.UserRepository;
import com.example.demo.security.jwt.JwtTokenProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
import static org.springframework.http.ResponseEntity.ok;
#RestController
#RequestMapping("/auth")
public class AuthController {
#Autowired
AuthenticationManager authenticationManager;
#Autowired
JwtTokenProvider jwtTokenProvider;
#Autowired
UserRepository users;
#PostMapping("/signin")
public ResponseEntity signin(#RequestBody User user) {
try {
String username = user.getUsername();
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, user.getPassword()));
String token = jwtTokenProvider.createToken(username, this.users.findByUsername(username).orElseThrow(() -> new UsernameNotFoundException("Username " + username + "not found")).getRoles());
Map<Object, Object> model = new HashMap<>();
model.put("username", username);
model.put("token", token);
model.put("roles", user.getRoles());
return ok(model);
} catch (AuthenticationException e) {
throw new BadCredentialsException("Invalid username/password supplied");
}
}
}
My entity:
package com.example.demo.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSetter;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static java.util.stream.Collectors.toList;
#Entity
#Table(name="users")
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class User implements UserDetails {
private static final long serialVersionUID = 357523406648925755L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
#NotEmpty
#Column(name="username")
private String username;
#Column(name="firstname")
private String firstName;
#Column(name="lastname")
private String lastName;
#NotEmpty
#Column(name="password")
private String password;
#Column(name = "email")
#NotEmpty()
private String email;
#Column(name = "enabled")
private boolean enabled;
#ElementCollection(fetch = FetchType.EAGER)
#Builder.Default
private List<String> roles = new ArrayList<>();
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles.stream().map(SimpleGrantedAuthority::new).collect(toList());
}
#JsonIgnore
#Override
public String getPassword() {
return this.password;
}
#JsonSetter
public void setPassword(String password) {
this.password = password;
}
#Override
public String getUsername() {
return this.username;
}
#JsonIgnore
#Override
public boolean isAccountNonExpired() {
return true;
}
#JsonIgnore
#Override
public boolean isAccountNonLocked() {
return true;
}
#JsonIgnore
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
}
My Custom UserDetailsService
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import br.com.fimd.entidades.Usuario;
import br.com.fimd.service.UsuarioService;
#Transactional(readOnly=true)
#Service("userDetailsServiceImpl")
public class UserDetailsServiceImpl implements UserDetailsService{
#Autowired
private UsuarioService usuarioService;
#Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Usuario usuario = usuarioService.findUserByEmail(email);
if(usuario == null) {
throw new UsernameNotFoundException("Usuário nao encontrado.");
}
return new User(usuario.getEmail(), usuario.getSenha(), usuario.getAuthorities());
}
}
My Security Configuration
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("userDetailsServiceImpl")
private UserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().disable().
csrf().disable().authorizeRequests()
.antMatchers("/home").permitAll()
.antMatchers("/public/**").permitAll()
.antMatchers("/private/**").hasRole("USER")
//.antMatchers("/admin*").access("hasRole('ROLE_ADMIN')")
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
//.addFilterBefore(new JWTAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class)
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/assets/**");
}
#Bean
CorsConfigurationSource corsConfigurationSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
return source;
}
}
My User Entity
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.NotBlank;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#Entity
#Table(name = "usuarios")
#EntityListeners(AuditingEntityListener.class)
#JsonIgnoreProperties(value = { "createdAt", "updatedAt" }, allowGetters = true)
public class Usuario implements UserDetails, Serializable{
private static final long serialVersionUID = 4038437690572999966L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "user_id")
private Long id;
#NotBlank
private String nome;
#NotBlank
private String email;
#NotBlank
private String senha;
#NotBlank
private String cpf;
#Column
private boolean ativo;
#ManyToMany
#JoinTable(name="perfil_usuario", joinColumns=
{#JoinColumn(name="user_id")}, inverseJoinColumns=
{#JoinColumn(name="tipo_perfil")})
private Set<Perfil> perfis = new HashSet<>();
#OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL)
private List<Investimento> investimentos;
#OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL)
private List<Extrato> extratos;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getCpf() {
return cpf;
}
public void setCpf(String cpf) {
this.cpf = cpf;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public String getSenha() {
return senha;
}
public void setSenha(String senha) {
this.senha = senha;
}
public boolean isAtivo() {
return ativo;
}
public void setAtivo(boolean ativo) {
this.ativo = ativo;
}
public Set<Perfil> getPerfis() {
return perfis;
}
public void setPerfis(Set<Perfil> perfis) {
this.perfis = perfis;
}
public List<Investimento> getInvestimentos() {
return investimentos;
}
public void setInvestimentos(List<Investimento> investimentos) {
this.investimentos = investimentos;
}
public List<Extrato> getExtratos() {
return extratos;
}
public void setExtratos(List<Extrato> extratos) {
this.extratos = extratos;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.perfis;
}
#Override
public String getPassword() {
return this.senha;
}
#Override
public String getUsername() {
return this.email;
}
#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 Perfil Entity
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import org.springframework.security.core.GrantedAuthority;
#Entity
public class Perfil implements GrantedAuthority{
private static final long serialVersionUID = 1L;
#Id
private String tipoPerfil;
#ManyToMany(mappedBy="perfis")
private List<Usuario> usuarios;
public List<Usuario> getUsuarios() {
return usuarios;
}
public void setUsuarios(List<Usuario> usuarios) {
this.usuarios = usuarios;
}
public String getTipoPerfil() {
return tipoPerfil;
}
public void setTipoPerfil(String tipoPerfil) {
this.tipoPerfil = tipoPerfil;
}
#Override
public String getAuthority() {
return this.tipoPerfil;
}
}
My Spring Filter Initializer
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
#Configuration
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}
When i call a "/private/service" my loadUserByUsername not being called never, my application ever send me a 403 forbidden, access denied.
Why that?
I tried a lot of tutorials from internet and my code seems to be correct, i'm using spring starter 2.0.5.RELEASE
I already tried to call the userDetailsService from a #Bean method in SecurityConfiguration
Your security configuration is not complete, you must provide as well the login information:
.formLogin()
.loginPage("/login.html")
.defaultSuccessUrl("/home")
.failureUrl("/login.html?error=true")
Otherwise all your requests will be unauthorized. Please see this tutorial:
https://www.baeldung.com/spring-security-login
Your Custom UserDetails service will be called only when the application will receive a POST to login url with username and password, otherwise it will not have what data to authorize.