SecurityContext doesn't work with @RolesAllowed

jakarta-ee, jax-rs, jersey, tomcat7

Solution

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

Problem

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

Original source