1

I would like to ensure that my JSON Web tokens are revoked/expire after a configurable ammount of time and i have the following set up:

Security Filter:

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import yourwebproject2.service.UserService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @author: kameshr
 */
public class JWTTokenAuthFilter extends OncePerRequestFilter {
    private static List<Pattern> AUTH_ROUTES = new ArrayList<>();
    private static List<String> NO_AUTH_ROUTES = new ArrayList<>();
    public static final String JWT_KEY = "JWT-TOKEN-SECRET";

    static {
        AUTH_ROUTES.add(Pattern.compile("/api/*"));
        NO_AUTH_ROUTES.add("/api/user/authenticate");
        NO_AUTH_ROUTES.add("/api/user/register");
    }

    private Logger LOG = LoggerFactory.getLogger(JWTTokenAuthFilter.class);

    @Autowired
    private UserService userService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String authorizationHeader = request.getHeader("authorization");
        String authenticationHeader = request.getHeader("authentication");
        String route = request.getRequestURI();

        // no auth route matching
        boolean needsAuthentication = false;

        for (Pattern p : AUTH_ROUTES) {
            if (p.matcher(route).matches()) {
                needsAuthentication = true;
                break;
            }
        }

        if(route.startsWith("/api/")) {
            needsAuthentication = true;
        }

        if (NO_AUTH_ROUTES.contains(route)) {
            needsAuthentication = false;
        }

        // Checking whether the current route needs to be authenticated
        if (needsAuthentication) {
            // Check for authorization header presence
            String authHeader = null;
            if (authorizationHeader == null || authorizationHeader.equalsIgnoreCase("")) {
                if (authenticationHeader == null || authenticationHeader.equalsIgnoreCase("")) {
                    authHeader = null;
                } else {
                    authHeader = authenticationHeader;
                    LOG.info("authentication: " + authenticationHeader);
                }
            } else {
                authHeader = authorizationHeader;
                LOG.info("authorization: " + authorizationHeader);
            }

            if (StringUtils.isBlank(authHeader) || !authHeader.startsWith("Bearer ")) {
                throw new AuthCredentialsMissingException("Missing or invalid Authorization header.");
            }

            final String token = authHeader.substring(7); // The part after "Bearer "
            try {
                final Claims claims = Jwts.parser().setSigningKey(JWT_KEY)
                        .parseClaimsJws(token).getBody();
                request.setAttribute("claims", claims);

                // Now since the authentication process if finished
                // move the request forward
                filterChain.doFilter(request, response);
            } catch (final Exception e) {
                throw new AuthenticationFailedException("Invalid token. Cause:"+e.getMessage());
            }
        } else {
            filterChain.doFilter(request, response);
        }
    }
}

Method that creates the Authentication token:

String token = Jwts.builder().setSubject(user.getEmail())
                .claim("role", user.getRole().name()).setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, JWTTokenAuthFilter.JWT_KEY).compact();
        authResp.put("token", token);
        authResp.put("user", user);

Above i have all the claims that i am using on the JWT , i would like to request that the token is revoked after x ammount of time(of inactivity if possible).

How could i achieve this using JWT / Spring MVC / Angular JS / Spring Security

rjcossa
  • 117
  • 4
  • 18

1 Answers1

2

Set expiration for token

 String token = Jwts.builder()
     .setSubject(user.getEmail())
     .claim("role", user.getRole().name())
     .setIssuedAt(new Date())
     .setExpiration(expirationDate) 
     .signWith(SignatureAlgorithm.HS256, WTTokenAuthFilter.JWT_KEY)
     .compact();

Then, parseClaimsJws will raise ExpiredJwtException if currentTime>expirationDate

To revoke a valid token is a hard technique with no easy solutions:

1) Maintain a blacklist in server and compare for each request

2) Set a small expiration time and issue new token

3) Insert the login time in the token and compare if acomplish your criteria

4) remove the jwt in client side

Ser Invalidating client side JWT session

Community
  • 1
  • 1
pedrofb
  • 37,271
  • 5
  • 94
  • 142