Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SecurityContext doesn't work with @RolesAllowed

I'm currently creating a backend server using Jersey 2.5.1 in a Tomcat 7. For the security I'm using the @RolesAllowed, @PermitAll etc. annotations, and I have created my custom ContainerRequestFilter and SecurityContext.

My problem is that when my @RolesAllowed annotated resource is requested it always denies permission, even if I force my isUserInRole(role) method to return true. However, my filter method gets called. Do you have any suggestions? I'll paste some relevant code below.

My ContainerRequestFilter implementation:

public class AuthorizationFilter implements ContainerRequestFilter
{
    @Override
    public void filter(ContainerRequestContext request) throws IOException
    {
        request.setSecurityContext(new Authorizer());
    }
}

My SecurityContext implementation:

public class Authorizer implements SecurityContext
{

    @Override
    public String getAuthenticationScheme() {
        return null;
    }

    @Override
    public Principal getUserPrincipal() {
        return null;
    }

    @Override
    public boolean isSecure() {
        return false;
    }

    @Override
    public boolean isUserInRole(String role) {
        return true;
    }

}

My resource:

@Path("/secure")
public class TestSecureResource {

    @GET
    @PermitAll
    @Path("/nonsec_test/{text}")
    public Response nonSecureTest(
            @PathParam("text") String text){

        return Response.status(200).entity(text).build();
    }

    @GET
    @RolesAllowed("admin")
    @Path("/sec_test/{text}")
    public Response secureTest(
            @PathParam("text") String text){

        return Response.status(200).entity(text).build();
    }
}

My ResourceConfig:

@ApplicationPath("/")
public class MyApplication extends ResourceConfig {

    public MyApplication() {
        super(TestSecureResource.class);
        register(RolesAllowedDynamicFeature.class);
        register(AuthorizationFilter.class);
    }
}

Relevant parts of my web.xml:

<servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>

        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>pkg.backend</param-value>
        </init-param>

        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>pkg.backend.MyApplication</param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>
    </servlet>

In this specific case, my access to secureTest is always denied. To clarify things; I'm getting HTTP status code 403 - Forbidden.

Thank you guys in advance

like image 222
tobypls Avatar asked Feb 03 '14 19:02

tobypls


2 Answers

Make sure you have your AuthorizationFilter either registered in your MyApplication (see Registering Resources and Providers in Jersey 2) or annotated with @Provider (to make it discoverable by package scanning).

In order to use security annotations (package javax.annotation.security) to restrict access to your resources you need to register RolesAllowedDynamicFeature.

EDIT 1

Your AuthorizationFilter has to be also annotated with @PreMatching which means that the filter is invoked before matching phase (uri -> resource). Otherwise filters registered by RolesAllowedDynamicFeature (invoked during this phase) won't see the custom SecurityContext.

EDIT 2

Jersey User Guide - Authorization - securing resources

like image 165
Michal Gajdos Avatar answered Oct 27 '22 00:10

Michal Gajdos


In a real application, defining your own ResourceConfig means you have to edit it every time you add a new resource (class).

A nice way to avoid that problem is to register the RolesAllowedDynamicFeature class in an <init-param> to the <servlet> in your web.xml like this:

<servlet>
    <servlet-name>your_servelet_name</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature</param-value>
    </init-param>

If you do that then you can put this in to dynamically register all resources in particular packages:

    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.your-domain.your-packages-1,com.your-domain.your-packages-2</param-value>
    </init-param>
like image 22
Bill Burcham Avatar answered Oct 27 '22 00:10

Bill Burcham