Home > Net >  Why is Spring security Authentication returning a Null authentication object?
Why is Spring security Authentication returning a Null authentication object?

Time:11-19

I need to get the User object details for the currently signed in User so that I can get the customers assigned to the User but I keep getting a null object when I printed to the console. I can sign in successfully with a generated token for the user type , but i keep getting null response when the logged in username is queried by Spring authentication.

Controller

@RestController
public class CustomerController {
    
@Autowired
CustomerAccountService customerRepo;
        
@Autowired
UserAccountService  userRepo;

 @GetMapping(value="marketers/customers")
public List<Customer> getLlistByMarketerName()
{
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();  
User loggedInUser = userRepo.findByUserName(authentication.getName());
System.out.println("logged in user:"  loggedInUser);
return customerRepo.findByMarketer(loggedInUser);
}
    

The repository


public interface CustomerAccountRepo extends JpaRepository <Customer, Long  > 

{
@Query("select customer from Customer customer join customer.marketer marketer where marketer = :marketer")
     List<Customer> findByMarketer(User marketer);
}

UserDetails Service

@Service
public class UserAccountService implements UserDetailsService {
    
    
@Autowired  
private UserAccountRepository userRepository;
        
private PasswordEncoder bCryptPasswordEncoder;
       
public  UserAccountService (PasswordEncoder bCryptPasswordEncoder) {
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
         
       }
    
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUserName(username);
if(user == null) {
throw new UsernameNotFoundException("User not found");
}
            
           // List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority(user.getUserRole()));
            
          return MyUserDetails.build(user);
}

JWT Request filter

@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    @Autowired
private JwtTokenUtil jwtTokenUtil;
private final UserAccountService userAccountService;
    
@Autowired
public JwtRequestFilter( @Lazy final UserAccountService userAccountService) {
this.userAccountService = userAccountService;
        
}
    
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

final String requestTokenHeader = request.getHeader("Authorization");

String username = null;
String jwtToken = null;
if (requestTokenHeader != null) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
System.out.println("JWT Token has expired");
}
} 

if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userAccountService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
String authorities = userDetails.getAuthorities().stream().map(GrantedAuthority::getAuthority)
.collect(Collectors.joining());
System.out.println("Authorities granted : "   authorities);
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
else {
 System.out.println("Not Valid Token");
        }

        }
chain.doFilter(request, response);
}

The User entity

@Entity
public class User {

    
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    
    private String firstName ;
    private String lastName;
    
    @Column(name="user_name", unique=true)
    private String userName;
    
    private String password;
    private String Gender; 
    private String phoneNumber;
    private String email;
    
    @JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
    @ManyToOne(targetEntity = Branch.class, 
     fetch = FetchType.LAZY )
    @JoinColumn(name="branch_id") 
    private Branch branch;
    
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private Date createdDate;
    
    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(
    name = "users_roles", 
    joinColumns = @JoinColumn(name = "user_id"),
    inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<UserRole> userRole = new HashSet<>();
    
    @Enumerated(EnumType.STRING)
    private UserStatus status;
    
    @JsonBackReference
    @OneToMany(mappedBy="marketer",cascade = CascadeType.ALL, targetEntity=Customer.class)
    private List <Customer> customer;

This is MyUserDetails class that provides the username and password authentication details

public class MyUserDetails implements UserDetails {
    
private static final long serialVersionUID = -2456373662763511974L;

private Long id;
private String username;
private String password;
private String email;
private Collection<? extends GrantedAuthority> authorities;
    
public MyUserDetails() {}
    
public MyUserDetails(Long id, String username, String email, String password,
Collection<? extends GrantedAuthority> authorities)
    {
        this.id = id;
        this.username = username;
        this.email = email;
        this.password = password;
        this.authorities = authorities;
    }
public static MyUserDetails build(User user) {
List<GrantedAuthority> authorities = user.getUserRole()
.stream().map(role -> new SimpleGrantedAuthority
(role.getName()))
.collect(Collectors.toList());
return new MyUserDetails(user.getId(),
user.getUserName(),
user.getEmail(),
user.getPassword(),
authorities);
        
}

UPDATED: Security config file . This is my first big project in Java , forgive my errors

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
  private UserDetailsService myUserDetailsService;
    
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
      exposeDirectory("customer-photos", registry);
  }
    
    private void exposeDirectory(String dirName, ResourceHandlerRegistry registry) {
      Path uploadDir = Paths.get(dirName);
      String uploadPath = uploadDir.toFile().getAbsolutePath();
       
      if (dirName.startsWith("../")) dirName = dirName.replace("../", "");
       
      registry.addResourceHandler("/"   dirName   "/**").addResourceLocations("file:/"  uploadPath   "/");
  }

  @Autowired 
    private JwtRequestFilter jwtRequestFilter;
     
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
     @Bean
     public DaoAuthenticationProvider daoAuthenticationProvider(PasswordEncoder passwordEncoder, UserDetailsService userDetailsService) { 
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
        daoAuthenticationProvider.setUserDetailsService(userDetailsService);
        return daoAuthenticationProvider;
    }
     
     @Override
     @Bean
     public AuthenticationManager authenticationManagerBean() throws Exception {
         return super.authenticationManagerBean();
     }

   @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.userDetailsService(myUserDetailsService).passwordEncoder(passwordEncoder());
     }

  @Override
    protected void configure(HttpSecurity http) throws Exception {
      http.cors().and().csrf().disable()
      .authorizeRequests()
      .antMatchers("/auth/login", "/validate", "/**").permitAll()
      .antMatchers("/admin/**").hasAuthority("ADMIN")
      
      .anyRequest().authenticated()
      .and()
      .exceptionHandling()
      .authenticationEntryPoint(jwtAuthenticationEntryPoint)
      
      .and()
      .formLogin().permitAll()
      
      .and()
      .sessionManagement()
      .maximumSessions(1)
      .and()
      .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
      .and()
      .logout().logoutUrl("/logout").logoutSuccessUrl("/auth/login")
      .deleteCookies("JSESSIONID");
      http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }
}  

CodePudding user response:

It seems to me that you don't want all your endpoints to not require authentication. In order to achieve it you will need to remove /** from your permitAll() in the security configuration as follows:

@Override
protected void configure(HttpSecurity http) throws Exception {
  http.cors().and().csrf().disable()
  .authorizeRequests()
  .antMatchers("/auth/login", "/validate").permitAll()
  .antMatchers("/admin/**").hasAuthority("ADMIN")
    
  .anyRequest().authenticated()
  .and()
    .exceptionHandling()
  .authenticationEntryPoint(jwtAuthenticationEntryPoint)
  
  .and()
  .formLogin().permitAll()
  
  .and()
  .sessionManagement()
  .maximumSessions(1)
  .and()
  .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  .and()
  .logout().logoutUrl("/logout").logoutSuccessUrl("/auth/login")
  .deleteCookies("JSESSIONID");
  http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
  • Related