Laupheer Laupheer - 1 year ago 136
reST (reStructuredText) Question

EJB: custom authentication and authorisation

I’m trying to add my own authentication and authorisation to Java EE REST application. I’ve managed to get working version with JAX-RS’s

implementation (with JWT) and
annotations on end-point methods. But I need EJBs, and they don’t use JAX-RS’s SecurityContext at all (I’m getting
regardless of user roles), so I need another solution.

Is there anything like
in EJBs possible to implement? Or should I use a library like Shiro? I want to manage users from the application itself, so container- or LDAP-provided user management is not an option. I'm using JPA to authenticate and authorise a user.

So, the main question is:

How do I implement my own authentication and role-based authorisation mechanisms working in EJBs (using @RolesAllowed annotations), based on JAX-RS filters? How do I tell EJB that a request is related to that concrete authenticated user with these roles?

One more thing – I’d rather avoid vendor-specific solutions, but if I had to, I’d go with JBoss/Wildfly.

Answer Source

I’ve been working on this for a while and ended up with my own solution. It is implemented at JAX-RS interface level (as suggested by Pradeep Pati) – so if you need to access your beans by EJB, it won’t work.

So, as I've found here, ContainerRequestFilter can access the resource method (or class) annotations, so all I needed to do is:

1. Implement my own @RolesAllowed annotation:

@Target( {ElementType.TYPE, ElementType.METHOD})
public @interface RolesAllowed {
    String[] value();

2. Implement ContainerRequestFilter with custom authentication and authorization:

public class SecurityFilter implements ContainerRequestFilter {

    private ResourceInfo resourceInfo;

    public void filter(ContainerRequestContext context) throws IOException {
        // here we have access to headers:
        String authorizationHeader = context.getHeaderString("Authorization");

        // and, thanks to injected resourceInfo, to annotations:
        RolesAllowed annotation = resourceInfo
                .getResourceClass() // or getResourceMethod(), I've used both
        // and, finally, to the roles (after a null-check)
        String[] roles = annotation.value();

        // then you can authenticate and authorize everything on your own using any method (I’ve used Basic Auth and JWT)
        // and, if something fails, you can abort the request:
        if (!isAuthenticated) {
        } else if (!isAuthorized) {

However, I’ve evaluated Avishai’s solution (to use PicketLink) too. While this is a little harder to implement and sometimes could be complicated (for example basic JPA scenario needs about 7-8 JPA entities), it would be better choice if you need solid, extensible security system with a lot of options (like LDAP or JPA, or even both at the same time) or with various authentication options (like Basic and JWT auth at the same time, but with different headers, for example). There are probably hundreds of pros and/or cons on the topic, so that's not an easy choice.

Funny thing is, PicketLink uses it’s own @org.picketlink.authorization.annotations.RolesAllowed annotation instead of javax.annotation one. Still, it should work well with EJB calls because it uses EJB interceptors, not JAX-RS filters to check the roles.

But for me it had seemed like an overkill, so I came up with my own, not-so-sophisticated (but working) solution.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download