I developed a Spring RESTful service that uses a JWT for authorization. To the validity of this JWT, i used two different implementations.
- Create a filter to intercept every request and validate request, if invalid then reject it.
- Create a annotation to be used in controller methods, this approach is explained below.
The JWT contains user id which is used to identify authenticated user, but if i used a filter, i have to decode this JWT again in controller method, because of this problem i used second implementation.
The question is about annotation approach.
- Is this a good implementation to JWT validation ?
- How can i improve this code ?
Here's the code,
Annotation
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Authorize { String[] value(); }
Implementation of the annotation
public class MethodAccessResolver implements HandlerMethodArgumentResolver { @Override public boolean supportsParameter(MethodParameter parameter) { return (parameter.getMethodAnnotation(Authorize.class) != null) && (parameter.getParameterName().equals("jwt")); } @Override public Object resolveArgument( MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory ) throws Exception { String[] allowedUsers = parameter.getMethodAnnotation(Authorize.class).value(); JwtProperties jwt = JwtUtil.validate(webRequest.getHeader("Authorization")); String currentUser = jwt.getScope().get(0); int no = 0; for (String allowedUser : allowedUsers) { if (!allowedUser.equals(currentUser)) { no++; } } if (no == allowedUsers.length) { throw new UnauthorizedAccessException("Un-authorized access", 0xd1561); } else { return jwt; } } }
Controller method - where the annotation is used
@GetMapping( path = "/api/event/post", produces = MediaType.APPLICATION_JSON_VALUE ) @Authorize(value = {UserSupport.USER, UserSupport.ADMIN, UserSupport.END_USER}) public ResponseEntity<?> getLiveLocations( HttpServletRequest request, JwtProperties jwt ) throws MongoException, ParseException, JwtException, UnsupportedEncodingException, ResourceNotFoundException, UnauthorizedAccessException { //do something }
An Exception
is thrown if token is invalid or the user role contains in token is not allowed to access particular URL.
If token is validated then user details will be injected to method parameter JwtProperties jwt
.