0

I would like to generate the token for login using springboot, The token is generating while checking using postman, but I am getting null in console

Authenticate controller

package com.demo.grocery.controller; import com.demo.grocery.config.JwtUtils; import com.demo.grocery.model.JwtRequest; import com.demo.grocery.model.JwtResponse; import com.demo.grocery.model.User; import com.demo.grocery.service.impl.UserDetailsServiceImpl; 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.DisabledException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.web.bind.annotation.*; import java.security.Principal; @RestController public class AuthenticateController { @Autowired private AuthenticationManager authenticationManager; @Autowired private UserDetailsServiceImpl userDetailsServiceImpl; @Autowired private JwtUtils jwtUtils; //generate token @CrossOrigin("http://localhost:4200") @PostMapping("/generate-token") public ResponseEntity<?> generateToken(@RequestBody JwtRequest jwtRequest) throws Exception { try { this.authenticate(jwtRequest.getUsername(), jwtRequest.getPassword()); } catch (UsernameNotFoundException e) { // TODO: handle exception e.printStackTrace(); throw new Exception("User Not Found"); } ////////////authenticate UserDetails userDetails = this.userDetailsServiceImpl.loadUserByUsername(jwtRequest.getUsername()); String token = this.jwtUtils.generateToken(userDetails); return ResponseEntity.ok(new JwtResponse(token)); } private void authenticate(String username, String password) throws Exception { try { authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); } catch (DisabledException e) { e.printStackTrace(); throw new Exception("USER DISABLED "+e.getMessage()); } catch(BadCredentialsException e) { throw new Exception("Invalid Credentials "+e.getMessage()); } } //returns the details of current logged in user @CrossOrigin("http://localhost:4200") @GetMapping("/current-user") public User getCurrentUser(Principal principal) { return (User) this.userDetailsServiceImpl.loadUserByUsername(principal.getName()); } } 

JwtAuthenticationFilter

package com.demo.grocery.config; import com.demo.grocery.service.impl.UserDetailsServiceImpl; import io.jsonwebtoken.ExpiredJwtException; 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.stereotype.Component; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component public class JwtAuthenticationFilter extends OncePerRequestFilter { @Autowired private UserDetailsServiceImpl userDetailsService; @Autowired private JwtUtils jwtUtil; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { final String requestTokenHeader = request.getHeader("Authorization"); System.out.println(requestTokenHeader); String username = null; String jwtToken = null; if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) { // yes jwtToken = requestTokenHeader.substring(7); try { username = this.jwtUtil.extractUsername(jwtToken); } catch (ExpiredJwtException e) { e.printStackTrace(); System.out.println("jwt token has expired.."); } catch (Exception e) { e.printStackTrace(); System.out.println("error"); } } else { System.out.println("Invalid Token, Not Starts with bearer String"); } //validate Token if(username!=null && SecurityContextHolder.getContext().getAuthentication() == null) { final UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); if(this.jwtUtil.validateToken(jwtToken, userDetails)) { //token is valid UsernamePasswordAuthenticationToken usernamePasswordAuthentication = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities()); usernamePasswordAuthentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthentication); } else { System.out.println("Token is not Valid"); } } filterChain.doFilter(request, response); } } 

Service

package com.demo.grocery.service.impl; import com.demo.grocery.model.User; import com.demo.grocery.repository.UserRepo; 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; @Service public class UserDetailsServiceImpl implements UserDetailsService { @Autowired private UserRepo userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = this.userRepository.findByUsername(username); if (user == null) { System.out.println("User Not Found"); throw new UsernameNotFoundException("No User Found!!"); } return user; } } 

Output in intelliji

Output

Postman output Generating Token

Getting current user details

Look into the screenshots and help me to solve the issue. Why it is storing as null?

1 Answer 1

1

For your method to work you should pass your JWT in Postman using Authorization -> Type: Bearer Token.

Postman example

As you can see in your console log, there's a message "Invalid Token, Not Starts with bearer String", which is printed from your JwtAuthenticationFilter when there's no Authorization header or it doesn't start with "Bearer".
At this point your user is not authenticated, so there's no Principal object in SecurityContextHolder when controller method is executed.

For these cases you should convert response to 401 UNAUTHORIZED status. For example, you can do it in your filter by writing straight to response.

But implementing your own security mechanism is considered a bad practice. I advise to use spring-security build-in JWT-support, which will automatically respond with 401 when there's no valid token found in Authorization header and will store additional info about missing or invalid token at response WWW-Authenticate header.
Take a look at spring-security official sample of jwt-secured resource-server.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.