Return-Path: X-Original-To: apmail-incubator-deltaspike-dev-archive@minotaur.apache.org Delivered-To: apmail-incubator-deltaspike-dev-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 18245933B for ; Wed, 18 Apr 2012 22:03:06 +0000 (UTC) Received: (qmail 79776 invoked by uid 500); 18 Apr 2012 22:03:06 -0000 Delivered-To: apmail-incubator-deltaspike-dev-archive@incubator.apache.org Received: (qmail 79742 invoked by uid 500); 18 Apr 2012 22:03:06 -0000 Mailing-List: contact deltaspike-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: deltaspike-dev@incubator.apache.org Delivered-To: mailing list deltaspike-dev@incubator.apache.org Received: (qmail 79734 invoked by uid 99); 18 Apr 2012 22:03:05 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 18 Apr 2012 22:03:05 +0000 X-ASF-Spam-Status: No, hits=-5.0 required=5.0 tests=RCVD_IN_DNSWL_HI,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (nike.apache.org: domain of sbryzak@redhat.com designates 209.132.183.28 as permitted sender) Received: from [209.132.183.28] (HELO mx1.redhat.com) (209.132.183.28) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 18 Apr 2012 22:02:58 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q3IM2Zgb005759 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 18 Apr 2012 18:02:35 -0400 Received: from [10.11.9.172] (vpn-9-172.rdu.redhat.com [10.11.9.172]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q3IM2WCf015136; Wed, 18 Apr 2012 18:02:33 -0400 Message-ID: <4F8F39F7.8030200@redhat.com> Date: Thu, 19 Apr 2012 08:02:31 +1000 From: Shane Bryzak User-Agent: Mozilla/5.0 (X11; Linux i686; rv:9.0) Gecko/20111222 Thunderbird/9.0 MIME-Version: 1.0 To: deltaspike-dev@incubator.apache.org CC: Bruno Oliveira Subject: Re: [DISCUSS] DELTASPIKE-79 Authorization API References: <4F8DF44A.9020704@redhat.com> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 On 19/04/12 06:35, Bruno Oliveira wrote: > On Tue, Apr 17, 2012 at 7:52 PM, Shane Bryzak 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 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 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.