deltaspike-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Shane Bryzak <sbry...@redhat.com>
Subject Re: [DISCUSS] DELTASPIKE-79 Authorization API
Date Wed, 18 Apr 2012 22:02:31 GMT
On 19/04/12 06:35, Bruno Oliveira wrote:
> On Tue, Apr 17, 2012 at 7:52 PM, Shane Bryzak<sbryzak@redhat.com>  wrote:
>
>> I'd like to kick off a discussion around the Authorization API,
>> specifically object permissions.  This API is used to determine whether the
>> currently authenticated user has the necessary privileges to perform an
>> operation on a particular domain object.  I'll start by outlining my
>> proposal covering the simple use cases of this API and we can then proceed
>> from there.
>>
>> First of all, the developer needs a gateway into the permission API so
>> that they can perform permission checks within their own application.  This
>> is provided by the hasPermission() method:
>>
> Hi Shane, good catch start to talk about it. Are you thinking about
> something using CDI interceptors or observers? To permission checks?

Hi Bruno.  Probably both, we definitely need a programmatic API (the 
hasPermission() method below) but I think a security binding type is 
also useful (also detailed below).

>
>>
>> Identity.hasPermission(Object resource, String operation)
>>
> Does 'operation' here means CRUD operations?

CRUD would be supported here but the operation is not limited to CRUD, 
it can potentially be anything.

>
>>
>> A permission has three aspects; 1) The application resource for which the
>> permission is granted, 2) The operation that has been granted for that
>> resource, and 3) The recipient of the permission, which may be either a
>> User, Group or Role.
>>
>> For example, if we wish to check whether the user has permission to edit a
>> Customer instance the code might look like this:
>>
>> @Inject Identity identity;
>>
>> public void editCustomer(Customer customer)
>> {
>>     if (!identity.hasPermission(**customer, "EDIT"))
>>     {
>>         throw new AuthorizationException("**Insufficient privileges to
>> edit this customer");
>>     }
>>
>>     // snip code
>> }
>>
> I like your idea. Currently I'm working on something similar to it with
> interceptors:
>
> @RequestScoped
> public class DummyService {
>
>      @SecurityRole(name = "admin")
>      public void editCustomer(Customer customer) {
>          //Something here
>      }
> }

This is an example of coarse-grained security, whereas ACL is 
fine-grained (object-level) security.

>
>
>> We could potentially also do some clever stuff with method-level
>> annotations here.  Off the top of my head, something like this might work:
>>
>> @CheckPermissions
>> public void editCustomer(@CheckPermission(**"EDIT") Customer customer)
>>
> It would be great to specify "EDIT" on top of the method only
> with @CheckPermission annotation.

How would you support specifying permission checks on multiple 
parameters of different types?

>
>> The @CheckPermissions annotation would be a security binding type with a
>> matching authorizer that would scan the parameter list and perform any
>> checks on parameters annotated with @CheckPermission.  Anyway we can refine
>> this idea in ongoing discussions.
>>
> Do you think that's a good idea do something like this?
>
> @AroundInvoke
>   public Object filterDeniedInvocations(InvocationContext invocationContext)
> throws Exception {
>        //read annotation value here with parameter list and perform checks
> }

Not sure what you're suggesting here - could you please elaborate?

>
>> In the default implementation, the Identity.hasPermission() method
>> essentially contains no code, instead it delegates the permission check to
>> the PermissionMapper bean, an implementation-only bean which contains a
>> list of PermissionResolver instances that are used to perform the
>> permission check.
>>
>> public class DefaultIdentity implements Identity
>> {
>>     // snip code
>>
>>     public boolean hasPermission(Object resource, String operation)
>>     {
>>         return permissionMapper.**resolvePermission(resource, operation);
>>     }
>> }
>>
>> The PermissionMapper bean provides the resolvePermission() method, which
>> basically iterates through the known PermissionResolvers, and if one of
>> them returns true for the permission check, then a true result is returned.
>>
>> public class PermissionMapper
>> {
>>     @Inject Instance<PermissionResolver>  resolvers;
>>
>>     public boolean resolvePermission(Object resource, String operation)
>>     {
>>         for (PermissionResolver resolver : resolvers)
>>         {
>>             if (resolver.hasPermission(**resource, operation)) return true;
>>         }
>>         return false;
>>     }
>> }
>>
>> We can do some clever stuff here, like caching which permission resolver
>> returns a true result for a particular class of resource, and then always
>> using that resolver for that class, etc.
>>
> How do you think to cache it?

This is really just an implementation detail, but I think a 
Map<Class,PermissionResolver> would be sufficient.

>
>> PermissionResolver is an API interface, the implementations of which do
>> the actual work of checking the permission.
>>
>> public interface PermissionResolver
>> {
>>     boolean hasPermission(Object resource, String operation);
>> }
>>
>> We would provide one PermissionResolver implementation out of the box with
>> DeltaSpike; PersistentPermissionResolver would provide permission checks
>> for ACL-style object permissions and provide a key piece of functionality
>> required by a complete permission management API.  Developers can easily
>> provide their own PermissionResolver implementations with custom business
>> logic by simply deploying a PermissionResolver bean in their own
>> application.
>>
>> This pretty much covers the basics of the object permission API, at least
>> on the consuming side.  We can discuss this area first before moving onto
>> the permission management API shortly.
>>
>> What do you think about a separated branch to prototype it? Let me know if
> I could help with something.
>
>

I guess it will depend on whether we introduce any/many changes as a 
result of discussion.  This is just a small part of the authorization 
API and really requires some of the other parts (in particular 
permission management) to be really useful.


Mime
View raw message