RESTEasy support for JAX-RS @RolesAllowed
embedded-jetty, jax-rs, resteasy
Solution
With a little help from the RESTEasy documentation, I found out that in order for RESTEasy to honor the `@RolesAllowed` annotations, one must turn on the `resteasy.role.based.security` context parameter switch in the `web.xml` file; or programatically, as I am doing:
final ServletHolder servletHolder = new ServletHolder(new HttpServlet30Dispatcher());
servletHolder.setInitParameter("javax.ws.rs.Application", MyApplication.class.getName());
servletHolder.setInitParameter("resteasy.role.based.security", String.valueOf(true));
contextHandler.addServlet(servletHolder, "/api/*");
Problem
I've spend hours installing a custom login service in embedded Jetty 9.1.0.v20131115 and RESTEasy 3.0.5.Final. My login service will look users up in a database and assign them roles. It looks something like this: ``` final Constraint restConstraint = new Constraint(); restConstraint.setName(Constraint.__BASIC_AUTH); restConstraint.setRoles(new String[]{"user", "admin"); restConstraint.setAuthenticate(true); final ConstraintMapping restConstraintMapping = new ConstraintMapping(); restConstraintMapping.setConstraint(restConstraint); restConstraintMapping.setPathSpec("/api/*"); final ConstraintSecurityHandler restSecurityHandler = new ConstraintSecurityHandler(); final LoginService myLoginService = new MyLoginService(); restSecurityHandler.setAuthenticator(new BasicAuthenticator()); restSecurityHandler.setRealmName(myLoginService.getName()); restSecurityHandler.addConstraintMapping(restConstraintMapping); restSecurityHandler.setLoginService(myLoginService); ``` I have users `joe-user` who has the role of `user`, and `jane-admin` who has both `user` and `admin` roles. I have a REST `GET` resource named `my-resource` marked with: ``` @RolesAllowed("admin") ``` When I do an HTTP `GET` on `my-resource`, the browser correctly requests credentials, and I can login as either `joe-user` or `jane-admin`. The problem is that either user is allowed to `GET` `my-resource`!! I've traced through some of the Jetty code, and indeed, as a result of my login service above, Jetty asks the login user which roles is supported. Unfortunately, Jetty will accept any of the roles I've specified in `restConstraint.setRoles(new String[]{"user", "admin")`, regardless of the user. Apparently it is the RESTEasy layer that is supposed to recognize the `@RolesAllowed("admin")` annotation and validate the user. But how do I get RESTEasy to do that?