Question

I am creating an application that runs in Karaf as OSGi container, and uses the OSGi HTTP Service and Jersey for exposing REST APIs. I need to add SAML2 authentication and permissions-based authorization. I would like to use the annotation based approach in Shiro for this, as spring seems to be moving away from OSGi. My questions:

  1. Is Shiro with SAML jars a good fit in OSGi environments?
  2. I want to use WSO2 as the identity provider. Are there any caveats of Shiro and WSO2 working together?
  3. For using annotations, the Shiro docs indicate I need to put AspectJ/Spring/Guice jars - Is this still valid in OSGi environments? I would prefer Guice for all my DI needs.

Would be great to have some insights from Shiro users.

UPDATE

I'm using this project: osgi-jax-rs-connector. So, I use Guice-Peaberry to register OSGi services with the interfaces annotated with @Path or @Provider, and the tool takes care of converting them into a REST resource. (Similar to pax-whiteboard?). I was planning to similarly expose my filters as OSGi services, and then dynamically add them along with the resources.

I have had headaches with AspectJ in OSGi in a previous project where I had to switch to vanilla Equinox from Karaf because the equinox weaving hook was not agreeing with Karaf (stack traces from Aries were seen, among other things). So, would doing something like shiro-jersey be better?

Was it helpful?

Solution 2

In the interest of readers, I'm sharing the solution I arrived at after some research of existing tools. First, the easy part: Using Shiro annotations in an OSGi environment. I ended up writing the below class since most Shiro-Jersey adapters shared by developers is based on Jersey 1.x.

    @Provider
    public class ShiroAnnotationResourceFilter implements ContainerRequestFilter {

        private static final Map, AuthorizingAnnotationHandler> ANNOTATION_MAP = new HashMap, AuthorizingAnnotationHandler>();

        @Context
        private ResourceInfo resourceInfo;

        public ShiroAnnotationResourceFilter() {
            ANNOTATION_MAP.put(RequiresPermissions.class,
                    new PermissionAnnotationHandler());
            ANNOTATION_MAP.put(RequiresRoles.class, new RoleAnnotationHandler());
            ANNOTATION_MAP.put(RequiresUser.class, new UserAnnotationHandler());
            ANNOTATION_MAP.put(RequiresGuest.class, new GuestAnnotationHandler());
            ANNOTATION_MAP.put(RequiresAuthentication.class,
                    new AuthenticatedAnnotationHandler());
        }

        public void filter(ContainerRequestContext context) throws IOException {

            Class resourceClass = resourceInfo.getResourceClass();
            if (resourceClass != null) {
                Annotation annotation = fetchAnnotation(resourceClass
                        .getAnnotations());
                if (annotation != null) {
                    ANNOTATION_MAP.get(annotation.annotationType())
                            .assertAuthorized(annotation);
                }
            }

            Method method = resourceInfo.getResourceMethod();
            if (method != null) {
                Annotation annotation = fetchAnnotation(method.getAnnotations());
                if (annotation != null) {
                    ANNOTATION_MAP.get(annotation.annotationType())
                            .assertAuthorized(annotation);
                }
            }
        }

        private static Annotation fetchAnnotation(Annotation[] annotations) {
            for (Annotation annotation : annotations) {
                if (ANNOTATION_MAP.keySet().contains(annotation.annotationType())) {
                    return annotation;
                }
            }
            return null;
        }
    }

The complete project is here. The above took care of Part 3 of my question.

For Shiro with SAML, I am using the Servicemix wrapped openSAML jar, and it seems to be working okay till now. I did however had to write a bit of code to make Shiro work with SAML2. It's almost on the same lines as shiro-cas, but is a bit more generic to be used with other IdPs. The code is kind of big so sharing a link to the project instead of copying classes to SO. It can be found here.

Now that I have some abstraction between my code and my IdP, WSO2 integration looks a bit simpler.

P.S. Thanks Achim for your comments and suggestions.

OTHER TIPS

I'm sure it is doable, though I already see some restrictions/issues poping up. for 1) haven't tried it, though you need to make sure that you tell the pax-web and jetty about it, it'll require adding this to the jetty.xml and it might even need to add a fragment bundle to pax-web-jetty so the desired class can be loaded. This will most likely be your first classnotfound issue.
2) don't know of WSO2 so no idea
3) if you want to use annotations, be careful. For Guice you'll mostlikely will need to use Peaberry since afaik Guice isn't "OSGi-fied" yet. Using AspectJ isn't really a good idea in a OSGi environment due to the classloader restrictions. If you have a compile-time weaving it should be fine, but run-time weaving will be a challange.

UPDATE: Completely forgot about it, but there is a Pax Shiro Project available, maybe this can be a good starting point to get your setup in a correct lineup.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top