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 A4D639E57 for ; Sun, 11 Mar 2012 22:37:24 +0000 (UTC) Received: (qmail 93789 invoked by uid 500); 11 Mar 2012 22:37:24 -0000 Delivered-To: apmail-incubator-deltaspike-dev-archive@incubator.apache.org Received: (qmail 93634 invoked by uid 500); 11 Mar 2012 22:37:22 -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 93615 invoked by uid 99); 11 Mar 2012 22:37:21 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 11 Mar 2012 22:37:21 +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; Sun, 11 Mar 2012 22:37:13 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q2BMaqCT026266 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Sun, 11 Mar 2012 18:36:52 -0400 Received: from [10.11.10.90] (vpn-10-90.rdu.redhat.com [10.11.10.90]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q2BMaonn006527 for ; Sun, 11 Mar 2012 18:36:51 -0400 Message-ID: <4F5D2901.5030900@redhat.com> Date: Mon, 12 Mar 2012 08:36:49 +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" Subject: [DISCUSS] DELTASPIKE-79 Authorization API - Permissions Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-Virus-Checked: Checked by ClamAV on apache.org The Authorization API is used to enforce security restrictions on application resources based on the privileges assigned to the user. I'd like to outline my ideas in this area below and hopefully kickstart a discussion. The entry point for the Permissions API is the Identity bean, which exposes the following method: boolean hasPermission(Object resource, String permission); Here's a simple use case demonstrating how this method could be used in a real application: @Inject Identity identity; @Inject EntityManager em; private Customer customer; public void editCustomer(Long id) { Customer c = em.find(id); if (!identity.hasPermission(c, "EDIT")) { throw new AuthorizationException("User does not have necessary privileges to edit this customer"); } customer = c; } The Identity bean implementation of hasPermission() does very little work itself, it simply delegates the permission check to a PermissionMapper bean: public boolean hasPermission(resource, permission) { return permissionMapper.resolvePermission(resource, permission); } PermissionMapper is an application-scoped bean, that maintains a list of PermissionResolver instances. The PermissionResolver interface defines the following method: public interface PermissionResolver { boolean hasPermission(Object resource, String permission); } When the PermissionMapper.resolvePermission() method is invoked, it simply iterates through its list of available PermissionResolvers, invoking the hasPermission() method on each one. If any one of them returns a result of true, then the permission check is successful. The PermissionMapper can be implemented so that PermissionResolvers that successfully grant permission for a particular class of resource can be invoked first for subsequent permission checks for the same class of resource, to improve performance. I propose that we provide one PermissionResolver implementation (PersistentPermissionResolver, I'll get to it in a moment) with DeltaSpike itself, and leave it up to the user if they wish to implement others. It is also trivial to provide PermissionResolver implementations from another library, for example we offered rule-based security in Seam which was built on top of the Drools rules engine. The Permission API makes it simple to extend by adding new permission resolvers. PersistentPermissionResolver is a PermissionResolver implementation that can be used to read resource permissions from persistent storage, such as a database. It allows ACL-style permissions to be granted for individual resources within the domain of the application, to particular users, groups or roles. Management of these permissions is performed through a PermissionManager bean, which declares the following methods: public interface PermissionManager { List listGrants(Object resource, String permission); List listGrants(Object resource); boolean grantPermission(Permission permission);more boolean grantPermissions(List permissions); boolean revokePermission(Permission permission); boolean revokePermissions(List permissions); List listAvailablePermissions(Object resource); void clearPermissions(Object resource); } A Permission object is a simple JavaBean that represents a permission: public interface Permission { Object getResource(); String getPermission(); public User getUser(); } We can go into finer detail about the storage mechanisms for persistent permissions later, however I'll wrap up this part of the proposal here as I think there's more than enough to digest. I'd like to hear any thoughts or ideas about permissions or the authorization API in general.