hi @ all,
> @SecurityRole(name = "admin")
if i remember correctly, we agreed on improving @SecurityBindingType to
allow such a (custom) annotation easily.
> PermissionResolver + PermissionType:
that wouldn't be a resolver. a resolver just resolves the information.
a voter or evaluator should do the calculation (right now we have a
AccessDecisionVoter in place - we can refactor it and add the concepts
of ResourceIdentifier and Operation to AccessDecisionVoterContext or
ResourceAwareAccessDecisionVoterContext).
> ResourceIdentifier:
+1 (but it should be an interface)
and we should do the same with the operation/action - e.g.:
public interface Operation
{
}
public enum CrudOperation implements Operation
{
CREATE, READ, UPDATE, DELETE
}
->
identity.hasPermission(new CustomerResourceIdentifier(customer),
CrudOperation.UPDATE)
> el use-case:
imo we don't need it right now. the upcoming jsf-module (or
el-security-module) can provide a helper which provides it.
we can even keep the bean-name "identity", because the security-module
doesn't need to provide such a named bean.
regards,
gerhard
2012/4/19 Bruno Oliveira <[email protected]>
> Hi Shane, if I'm following your thought the idea is to have security on
> object-level and not just check methods (resource level) as I was thinking
> with @CheckPermissions on the method level.
>
> About filterDeniedInvocations I got it borrowed from SecurityInterceptor.
> I'm checking permissions on the method level only without going too deep
> with object-level.
>
> Thanks for clarify.
>
> On Wed, Apr 18, 2012 at 7:02 PM, Shane Bryzak <[email protected]> wrote:
>
> > On 19/04/12 06:35, Bruno Oliveira wrote:
> >
> >> On Tue, Apr 17, 2012 at 7:52 PM, Shane Bryzak<[email protected]>
> 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.
> >
> >
>