Protecting Spring Boot Rest Services with JWT Token Authentication

Lets use jsonweb token

<dependency>
	<groupId>io.jsonwebtoken</groupId>
	<artifactId>jjwt</artifactId>
	<version>0.9.1</version>
</dependency>

Lets use Handler Interceptor

@Component
public class TokenRequiredInterceptor extends HandlerInterceptorAdapter {

	@Autowired
	private TokenService tokenService;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		HandlerMethod handlerMethod = (HandlerMethod) handler;
		TokenRequired tokenRequired = handlerMethod.getMethod().getAnnotation(TokenRequired.class);

		if (tokenRequired == null) {
			return true;
		}

		String auth = request.getHeader(HttpHeaders.AUTHORIZATION);

        if(auth == null) {
        	response.reset();
        	response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "{ auth: false, message: 'No token provided.' }");
        	return false;
        }

        processToken(request, auth);

		return true;
	}

	private void processToken(HttpServletRequest request, String auth) {
		String token = auth.split(SPACE)[1];

        ActiveUser activeUser = tokenService.getActiveUser(token);

        request.setAttribute(REQ_ATTR_ACTIVE_USER, activeUser);
	}
}

Here is the getActiveUser() Implementation

public ActiveUser getActiveUser(String token) {
		Claims body = Jwts.parser()
                .setSigningKey(jwtSecret)
                .parseClaimsJws(token)
                .getBody();

        return new ActiveUser((String) body.get(CLAIM_EMAIL), ((List<String>) body.get(CLAIM_ROLES)));
	}

Lets register the interceptor

@Configuration
public class AppConfig implements WebMvcConfigurer {

	@Autowired
	private TokenRequiredInterceptor tokenRequiredInterceptor;

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(tokenRequiredInterceptor);
	}
}

The API Implementation

@RestController
@RequestMapping("/api/v1")
public class ApiController {

	@Autowired
	private TokenService tokenService;

	@GetMapping("/notsecured")
	@ResponseBody
	public ResponseEntity<String> notsecured() {
		return new ResponseEntity<String>("not secured", HttpStatus.OK);
	}

	@TokenRequired
	@GetMapping("/test")
	@ResponseBody
	public ResponseEntity<String> test(@RequestAttribute(REQ_ATTR_ACTIVE_USER) ActiveUser activeUser) {
		return new ResponseEntity<String>("secured", HttpStatus.OK);
	}
}

Testing

Not Secured

Secured

Lets create JWT token

Payload data

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "email": "[email protected]",
  "roles": ["developer","admin"]
}

No token provided

Token Provided

Also See