SecurityContext doesn't work with @RolesAllowed

11,786

Solution 1

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

Solution 2

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>
Share:
11,786
tobypls
Author by

tobypls

Software Developer

Updated on August 04, 2022

Comments

  • tobypls
    tobypls almost 2 years

    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