0
votes

I am using Spring boot + Spring Security + Jersey.

I am trying to do something always that an Unathorized error happens with an ExceptionMapper, but it doesn't seem to work. However, other Mappers that I've done work perfectly.

This is my code:

Unauthorized Excepcion:

package com.ulises.usersserver.rest.exceptionsmappers;

import com.ulises.usersserver.rest.dto.ErrorDTO;
import com.ulises.usersserver.rest.dto.ErrorDTOBuilder;

import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;

import static com.ulises.usersserver.constants.Constants.REQUEST_ERROR_UNATHORIZED;

public class NotAuthorizedMapper implements ExceptionMapper<NotAuthorizedException> {
    @Override
    public Response toResponse(NotAuthorizedException e) {
        final ErrorDTO errorDTO = ErrorDTOBuilder.builder()
                .message(REQUEST_ERROR_UNATHORIZED)
                .build();
        return Response.status(Response.Status.UNAUTHORIZED)
                .type(MediaType.APPLICATION_JSON_TYPE)
                .entity(errorDTO)
                .build();
    }
}

Other custom mapper that works perfectly:

package com.ulises.usersserver.rest.exceptionsmappers;

import com.ulises.usersserver.rest.dto.ErrorDTO;
import com.ulises.usersserver.rest.dto.ErrorDTOBuilder;
import com.ulises.usersserver.services.exceptions.UserNotFoundException;

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;

import static com.ulises.usersserver.constants.Constants.REQUEST_ERROR_USER_DOESNT_EXIST;

public class UserNotFoundExceptionMapper implements ExceptionMapper<UserNotFoundException> {
    @Override
    public Response toResponse(UserNotFoundException e) {
        final ErrorDTO errorDTO = ErrorDTOBuilder.builder()
                .message(REQUEST_ERROR_USER_DOESNT_EXIST)
                .build();
        return Response.status(Response.Status.NOT_FOUND).entity(errorDTO).build();
    }
}

They are of course registered in Jersey's config:

@Bean
public ResourceConfig jerseyConfig() {
    final ResourceConfig resourceConfig = new ResourceConfig();
                      ...
    resourceConfig.register(NotFoundMapper.class);
    resourceConfig.register(NotAuthorizedMapper.class);
                      ...

    return resourceConfig;
}

I don't seem to be able to map other exceptions such as InternalServerErrorException (I managed to map this one by doing ExceptionMapper<Exception>, which doesn't look very correct to me.

Anyone knows why is this happening? I've checked all possible questions here and none of them solved this.

Thanks in advance.

1
Where is the NotAuthorizedException being thrown? - Paul Samsotha
I don't really know, it's Spring Security who throws if the user's login info is wrong. However, it doesn't really matter. As I understand, by registering that mapper Jersey should go there and do what I want it to do as it says here: makeinjava.com/… - Wrong

1 Answers

0
votes

Okay, it seems Jersey has no control over Spring Security's exceptions.

The way to solve this (had to dig alot) is to override the method from AuthenticationEntryPoint that S-Security uses to return the 401 response if an user isn't authorized.

So I created the following class implementing that interface:

public class CustomEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest request,
                         HttpServletResponse response, AuthenticationException authException) throws IOException {
        JSONObject json = new JSONObject();
        json.put("Message", "You don't have access to view this section. Please, log in with an authorized account.");
        response.addHeader("Content-Type", "application/json");
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().println(json);
    }
}

And then just add this configuration to S-Security to use this class as entry point:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.httpBasic().authenticationEntryPoint(new CustomEntryPoint());
         ..... any other config you had .....
}