Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jersey custom SecurityContext on EJB jax-rs resource

I am trying to implement my own ContainerRequestFilter and configure SecurityContext. It works well on jax-rs resources but EJB jax-rs throws javax.ejb.AccessLocalException

Only relevant thing I found is 4 years old and the workaround doesn't seem pretty. https://java.net/projects/jersey/lists/users/archive/2010-05/message/265

My custom SecurityContext:

@Provider
@PreMatching
public class SecurityFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext filterContext) throws IOException {
        filterContext.setSecurityContext(new Authorizer());
    }

    public class Authorizer implements SecurityContext {

    public Principal getUserPrincipal() {
        return null;
    }

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

    public boolean isSecure() {
        return false;
    }

    public String getAuthenticationScheme() {
        return null;
    }
}

Tested resource (works without @Stateless)

@Path("test")
@Stateless
public class TestSecureResource {

    @GET
    @RolesAllowed("admin")
    @Path("admin")
    public Response secureTest() {
        return Response.status(200).entity("admin").build();
    }

}

Does someone know how to make this work?

like image 613
Richard Časár Avatar asked Mar 18 '23 02:03

Richard Časár


1 Answers

You can use JAX-RS SecurityContext as an API not SPI. It is uncommon for an application developer to provide a SecurityContext implementation. If you do you have to know that it has only "local JAX-RS validity" since it is a JAX-RS specific API. Neither Servlet/Web container nor EJB container work with it. They don't have to as Java SE and EE have more general security support.

If you want your security checks to works in a Java EE application (i.e. HttpServletRequest.isUserInRole(...), EJBContext.isCallerInRole(...) or javax.annotation.security annotations on EJBs) you need to secure your Servlet layer using Java EE features. This means to use for example <security-constraint> in web.xml. You can use * as <role-name> meaning "all authenticated" user can call the REST API:

<security-constraint>
    <web-resource-collection>
        <url-pattern>/rest/admin/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>adminRole</role-name>
    </auth-constraint>
</security-constraint>
<security-constraint>
    <web-resource-collection>
        <url-pattern>/rest/orders/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>*</role-name> <!-- all authenticated users -->
    </auth-constraint>
</security-constraint>

When your Java EE application is secured as shown above we can enable javax.annotation.security annotations in JAX-RS using the Jersey-specific feature called RolesAllowedDynamicFeature.

Register the feature:

@ApplicationPath("/rest")
public class MyApplication extends ResourceConfig {
    public MyApplication() {
        super(AdminResource.class);
        register(RolesAllowedDynamicFeature.class);
    }
}

Secure your resources:

@Path("/admin")
@RolesAllowed("adminRole")
public class AdminResource {
    @GET
    public String get() { return "GET"; }
    ...
}

See Jersey User guide for more details about securing JAX-RS applications.

So you were close. You don't need to implement a SecurityContext yourself. You must not implement it if you deal with secured EJBs. And finally you need to secure your JAX-RS layer as common Web/Servlet application. I'm sure you already have secured your Web/HTML pages.

like image 55
shamoh Avatar answered Mar 31 '23 11:03

shamoh