0

I'm trying to define and use a custom security binding type called BasicRolesAllowed, as has been demonstrated in the Picketlink quickstarts here.

The only different between my type the ones in the quickstart, is that my annotation has to accept an array of strings (we want to secure methods using not just one but possibly combinations of roles), and thus my annotation is defined thus:

public @interface BasicRolesAllowed {
    String[] value() default {};
}

Following the quickstart, I've tried to define how this decorator authenticates as such:

@Secures
@BasicRolesAllowed
public boolean doAdminCheck(Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {
    /*
     Sample usage of @BasicRolesAllowed is like:
      @BasicRolesAllowed(value = RoleConstants.CREATE_USER)
      TODO: need to get these from the @BasicRolesAllowed annotation instance/usage
      */

    String[] requiredRoles = {};// get these from annotation
    boolean isAuthorized = true;

    for (String role : requiredRoles)
        isAuthorized = isAuthorized && hasRole(relationshipManager, identity.getAccount(), getRole(identityManager, role));

    return isAuthorized;
}

And as can be seen in the snippet, the trick part is:

        String[] requiredRoles = {};// get these from annotation

How do I get the string constants passed to the annotation on the decorated method so I can use them in looking up roles?

Some Hints:

There's an answer to a similar question here, but the problem is that in that solution; one needs to know the name of the decorated function or class - which in my case is impossible given that the decorator will be used just about anywhere, and I don't know how to get these via the method shown in the Picketlink quickstart.

Also, the solution only shows how to obtain the value passed to an annotation expecting only 1 string - maybe I could try using values(), but the above limitation still stands in my way.

Thanks in advance to anyone who can help.

Community
  • 1
  • 1
JWL
  • 13,591
  • 7
  • 57
  • 63

1 Answers1

0

Thanks to @pedroigor over at #picketlink (freenode), the solution can be gleaned from an example of such a use-case in the picketlink quickstart here. In that file, a method getAnnotation() is defined, which has the signature:

private <T extends Annotation> T getAnnotation(InvocationContext invocationContext, Class<T> annotationType)

So, using this method, I'm able to introspect and obtain the values passed to my annotation as can be seen in my new implementation of the roles checking method here:

@Secures
@BasicRolesAllowed
public boolean hasBasicRolesCheck(InvocationContext invocationContext, Identity identity, IdentityManager identityManager, RelationshipManager relationshipManager) throws Exception {
    BasicRolesAllowed basicRolesAllowed = getAnnotation(invocationContext,BasicRolesAllowed.class);

    String[] requiredRoles = basicRolesAllowed.value();// get these from annotation
    boolean isAuthorized = true;

    for (String role : requiredRoles)
        isAuthorized = isAuthorized && hasRole(relationshipManager, identity.getAccount(), getRole(identityManager, role));

    return isAuthorized;
}

The essential modifications being:

  1. I had to pass an instance of the invocation context InvocationContext invocationContext by adding this as a parameter to my method definition (CDI magic takes care of all else I hear).
  2. I then obtain the annotation instance by calling:

    BasicRolesAllowed basicRolesAllowed = getAnnotation(invocationContext,BasicRolesAllowed.class);
    
  3. And then get the values/parameters passed to the annotation thus:

    String[] requiredRoles = basicRolesAllowed.value();// get these from annotation
    

This solves my problem :-)

JWL
  • 13,591
  • 7
  • 57
  • 63