- Advantage of JSON token is it could be used form multiple platforms like PC, Mobile for accessing secured pages
- User enters user credentials(Username and Password) and gets authenticated.
- User Credentails are validated and token is generated
- On Subsequent request from APIs tokens are used in header for authorization
- Tokens are generated and verified by filters.There would be line of filters on way from request to API
- JwtUsernameAndPasswordAuthenticationFilter generates the Token after authentication
- JwtTokenVerifierFilter authorizes the user in each and every request by interpreting the token in the request header
JwtTokenVerifierFilter.java
public class JwtTokenVerifierFilter extends OncePerRequestFilter { private final SecretKey secretKey; private final JwtConfig jwtConfig; public JwtTokenVerifierFilter(SecretKey secretKey, JwtConfig jwtConfig) { this.secretKey = secretKey; this.jwtConfig = jwtConfig; } @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { String authorizationHeader = httpServletRequest.getHeader(jwtConfig.getAuthorizationHeader()); if(Strings.isNullOrEmpty(authorizationHeader) || !authorizationHeader.startsWith("Bearer ")){ filterChain.doFilter(httpServletRequest, httpServletResponse); return; } String token = authorizationHeader.replace(jwtConfig.getTokenPrefix(), ""); try{ Jws<Claims> claimsJws = Jwts.parser() .setSigningKey(secretKey) .parseClaimsJws(token); Claims body = claimsJws.getBody(); String username = body.getSubject(); List<Map<String, String>> authorities = (List<Map<String, String>>)body.get("authorities"); Set<SimpleGrantedAuthority> simpleGrantedAuth = authorities.stream() .map(m -> new SimpleGrantedAuthority(m.get("authority"))) .collect(Collectors.toSet()); Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, simpleGrantedAuth); SecurityContextHolder.getContext().setAuthentication(authentication); }catch (JwtException e){ throw new IllegalStateException(String.format("Token %s cannot be Trusted", token)); } filterChain.doFilter(httpServletRequest, httpServletResponse); } }
JwtUsernameAndPasswordAuthenticationFilter.java
public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter { private final AuthenticationManager authenticationManager; private final JwtConfig jwtConfig; private final SecretKey secretKey; public JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authenticationManager, JwtConfig jwtConfig, SecretKey secretKey) { this.authenticationManager = authenticationManager; this.jwtConfig = jwtConfig; this.secretKey = secretKey; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { try { UsernameAndPasswordAuthenticationRequest authenticationRequest = new ObjectMapper() .readValue(request.getInputStream(), UsernameAndPasswordAuthenticationRequest.class); Authentication authentication = new UsernamePasswordAuthenticationToken( authenticationRequest.getUsername(), authenticationRequest.getPassword() ); Authentication authenticate = authenticationManager.authenticate(authentication); return authenticate; } catch (IOException e) { throw new RuntimeException(e); } } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { String token = Jwts.builder() .setSubject(authResult.getName()) .claim("authorities", authResult.getAuthorities()) .setIssuedAt(new Date()) .setExpiration(java.sql.Date.valueOf(LocalDate.now().plusWeeks(jwtConfig.getTokenExpirationAfterDays()))) .signWith(secretKey) .compact(); response.addHeader(jwtConfig.getAuthorizationHeader(), jwtConfig.getTokenPrefix() + token); } }