2021年4月4日星期日

Unable to set refresh token and get back the response

In this project I just added a user entity and role entity and added jwt auth which everything works well untill the jwt expires. After adding a filter and an entry point, I got an error which is raised by the entry point:

{      "error": "Full authentication is required to access this resource"  }  

In the JwtRequest filter, I added a try catch to catch a ExpiredJwtException, but I'm still unable to refresh the token and getting the response of the endpoint requested.

/* Intercepts every request and examine the header for jwt */  @Component  public class JwtRequestFilter extends OncePerRequestFilter  {        @Autowired      private AuthService authService;        @Autowired      private RestTemplate restTemplate;        @Autowired      private JwtUtil jwtUtil;        private static final String REFRESH_TOKEN = "http://localhost:8080/refreshtoken";      private static final String AUTHENTICATION_URL = "http://localhost:8080/authenticate";          protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException      {          try {              /*Get only the token */              String jwt = extractJwtFromRequest(request);              if(StringUtils.hasText(jwt) && this.jwtUtil.validateToken(jwt))              {                  System.out.println("Entro ," +jwt);                  UserDetails userDetails = this.authService.refreshTokenUserDetails(this.jwtUtil.getUsernameFromToken(jwt));                  UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());                    /* After setting the auth in the context, we specify that the current user is authenticated..                   * So it passes the Spring Security Config successfully */                  SecurityContextHolder.getContext().setAuthentication(authToken);                } else {                  System.out.println("Cannot set the Security Context");              }          } catch (ExpiredJwtException ex) {              /* Expired token */              if (ex.getMessage().contains("io.jsonwebtoken.ExpiredJwtException"))              {                  request.setAttribute("claims", ex.getClaims());                  /* Refresh token*/                  String jwt = this.refreshToken(extractJwtFromRequest(request));                  request.setAttribute("Autorization", jwt);                  Object[] res = this.getData(request, jwt);                  byte[] body = new ObjectMapper().writeValueAsBytes(res);                  response.getOutputStream().write(body);                                }            } catch (BadCredentialsException ex) {              request.setAttribute("exception", ex);              throw ex;          } catch (Exception e) {              System.out.println(e);              throw e;          }          filterChain.doFilter(request, response);      }        private String getData(HttpServletRequest request, String token)      {          String response = null;          HttpHeaders headers = getHeaders();          headers.set("Authorization", token);          headers.set("isRefreshToken", "true");          HttpEntity<String> jwtEntity = new HttpEntity<String>(headers);            /* Use token to get response */          String urlRequested = request.getRequestURL().toString();          ResponseEntity<String> requested = restTemplate.exchange(urlRequested, HttpMethod.GET, jwtEntity, String.class);            if(requested.getStatusCode().equals(HttpStatus.OK))          {              response = requested.getBody();          }          return response;      }        private HttpHeaders getHeaders()      {          HttpHeaders headers = new HttpHeaders();          headers.set("Content-Type", MediaType.APPLICATION_JSON_VALUE);          headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);          return headers;      }        private String extractJwtFromRequest(HttpServletRequest request)      {          String authorizationHeader = request.getHeader("Authorization");          if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {              return authorizationHeader.substring(7);          }          return null;      }        private String refreshToken(String token)      {          HttpHeaders headers = getHeaders();          headers.set("Authorization", token);          headers.set("isRefreshToken", "true");          HttpEntity<String> jwtEntity = new HttpEntity<String>(headers);            /* Use Token to get Response */          ResponseEntity<AuthResponse> refreshTokenResponse = restTemplate.exchange(REFRESH_TOKEN, HttpMethod.GET, jwtEntity, AuthResponse.class);            if(refreshTokenResponse.getStatusCode().equals(HttpStatus.OK))          {              return "Bearer " + refreshTokenResponse.getBody().getJwt();          }          return null;      }        private void allowForRefreshToken(ExpiredJwtException ex, HttpServletRequest request)      {          /* Create a UsernameAuthenticationToken with null values */          UsernamePasswordAuthenticationToken upat = new UsernamePasswordAuthenticationToken(null, null, null);            /* After setting the auth in the context, we specify that the current user is authenticated. So it          * passes the Spring Security Config successfully */          SecurityContextHolder.getContext().setAuthentication(upat);            /* Set the claims so that in controller we will be using it to create new Jwt */          request.setAttribute("claims", ex.getClaims());      }  }  

JwtAuthenticationEntryPoint

@Component  public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint  {        @Override      public void commence(HttpServletRequest request, HttpServletResponse response,                           AuthenticationException authException) throws IOException, ServletException {            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);          response.setContentType(MediaType.APPLICATION_JSON_VALUE);          String message;            /* Check if the request as any exception that we have stored in Request */          final Exception exception = (Exception) request.getAttribute("exception");            // If yes then use it to create the response message else use the authException          if (exception != null)          {              byte[] body = new ObjectMapper().writeValueAsBytes(Collections.singletonMap("cause", exception.toString()));              response.getOutputStream().write(body);          } else {                if (authException.getCause() != null) {                  message = authException.getCause().toString() + " " + authException.getMessage();              } else {                  message = authException.getMessage();              }               /* Error on postman */              byte[] body = new ObjectMapper().writeValueAsBytes(Collections.singletonMap("error", message));              response.getOutputStream().write(body);          }      }  }  

SessionController endpoint

@RequestMapping(value = "/refresh-token", method = RequestMethod.GET)      public ResponseEntity<?> refreshToekn(HttpServletRequest request) throws Exception {          /* From the http ruest get claims */          DefaultClaims claims = (io.jsonwebtoken.impl.DefaultClaims) request.getAttribute("claims");          Map<String, Object> expectedMap = this.authService.getMapFromIoJsonwebtokenClaims(claims);          String token = this.authService.refreshToken(expectedMap, expectedMap.get("sub").toString());            return ResponseEntity.ok(new AuthResponse(token));      }  

AuthService

public String refreshToken(Map<String, Object> claims, String subject)      {          return this.jwtUtil.createTokenInfinity(claims, subject);      }        public Map<String, Object> getMapFromIoJsonwebtokenClaims(Claims claims)      {          Map<String, Object> expectedMap = new HashMap<String, Object>();          for (Map.Entry<String, Object> entry : claims.entrySet())          {              expectedMap.put(entry.getKey(), entry.getValue());          }          return expectedMap;      }  

And finally JwtUtil

public String createTokenInfinity(Map<String, Object> claims, String subject)      {          /* Subject -> person who has been authenticated */          return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))                  .setExpiration(new Date(System.currentTimeMillis() + REFRESH_TIME)) //* 60 *60 *800)                  .signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();      }  

If you can tell me a better approach to get this done, I'll be very helpful.

https://stackoverflow.com/questions/66947472/unable-to-set-refresh-token-and-get-back-the-response April 05, 2021 at 10:01AM

没有评论:

发表评论