4 Replies Latest reply on Aug 3, 2009 11:23 AM by mgvarley

    Securing params with drools

    mgvarley

      Hi all - I have spent the last 8 hours trying to solve a security issue in my Seam app and whilst I've made a lot of progress I'm not quite there.  I want to prevent a logged in user from manipulating a URL to access something they shouldn't.  I have read the Seam docs thoroughly (multiple times!) and have been searching the forums (including this one) and can't find a clear example of what I need to do - the seamspace example (I'm using v2.1.2) gives some clues but addresses so many different aspects of the security model that it is confusing to the uninitiated.  Dan Allen's excellent Seam in Action got me part of the way but am not quite there.


      My scenario is this: I have a User associated with a Customer entity, they log in (using the seam identityManager) and are redirected to a customer area where they are presented with their list of Bookings, they click on a Booking and are displayed the Booking using standard a seam-gen page backed by a BookingHome object extending EntityHome.  Currently though, any authenticated customer can view any booking (even those which are not there's) by modifying the bookingId parameter in the URL.


      I have the following entry in my components.xml:


      <security:rule-based-permission-resolver security-rules="#{securityRules}" />


      I have created the rule as follows (and included the imports for the referenced classes) in security.drl:


      rule CustomerBooking
        no-loop
        activation-group "permissions"
      when
        $perm: PermissionCheck(name == "customer.booking", action == ("view"), granted == false)
        Role(name == "customer")
        Booking($bookingCustomer: customer)
        User(customer == $bookingCustomer)
      then
        $perm.grant();
      end
      



      Finally, I have added the following in my booking.page.xml file:


      <restrict>#{s:hasPermission('customer.booking','view')}</restrict>



      However, this is not working.  I get the following error: Authorization check failed for expression [#{s:hasPermission('customer.booking','view')}] even though when the customer has the right to view the booking.


      If I exclude the references to Booking it works fine, I have checked with the following rule:


      rule CustomerBooking
        no-loop
        activation-group "permissions"
      when
        $perm: PermissionCheck(name == "customer.booking", action == ("view"), granted == false)
        Role(name == "customer")
        User(username == "myusername")
      then
        $perm.grant();
      end
      



      Any advice as to what I am doing wrong would be very much appreciated.  Or an alternative strategy for securing the param ids in the URL.


      Thanks in advance,


      mark



        • 1. Re: Securing params with drools
          niox.nikospara.yahoo.com

          Hello,


          I haven't used rules for quite some time, but just to make sure: does Customer define equals()? If it does, also try something like:


            Booking($bookingCustomerID: customer.id)
            User(customer.id == $bookingCustomerID)
          



          Where id is the primary key and it is a primitive field.

          • 2. Re: Securing params with drools
            mgvarley

            Thanks for the advice Nikos, have given this a try and whilst it hasn't quite solved my problem it has got me a little closer to understanding what's missing.  I have been debugging using the following:


            when
              $perm: PermissionCheck(name == "customer.booking", action == ("view"), granted == false)
              User($customerId: customer.id)
            then
              $perm.grant();
              System.out.println("Customer: " + $customerId);
            end
            



            Works great, authorizes (doesn't actually check anything) and I get (Customer: 60) in my console output.  However, if I add in this:


            when
              $perm: PermissionCheck(name == "customer.booking", action == ("view"), granted == false)
              User($customerId: customer.id)
              Booking($bookingId: id)
            then
              $perm.grant();
              System.out.println("Customer: " + $customerId);
              System.out.println("Booking: " + $bookingId);
            end
            



            I get a org.jboss.seam.security.AuthorizationException: Authorization check failed for expression [#{s:hasPermission('customer.booking','view')}]


            I thought this may be as the hasPermission expression is being evaluated in my page.xml file at which point the Booking instance may not have been loaded and therefore drools cannot find the Booking object in memory however I have tried moving this into the booking.xhtml file as follows but the Hello Customer title is not displayed and nothing shows in the log so I assume this has failed as before.


            <s:fragment rendered="#{s:hasPermission('customer.booking','read')}">
                 <h1>Hello Customer</h1>
            </s:fragment>
            



            What do I need to do to get drools to find my Booking object?  Is there a config step I have missed?  I have read of the target= annotation for s:hasPermission but this seems to be deprecated in Seam 2.1.2.  This seams like a great technology and would dearly love to get it working, otherwise I will have to resort to the messy alternative which is overriding loadInstance() in my BookingHome class to check for security there.


            Thanks in advance for any assistance.


            • 3. Re: Securing params with drools
              joblini

              Hi Mark,


              Have you tried adding the @Restrict annotation to Booking entity?  The entity manager will then assert the Booking object instance into Drools working memory before performing a permission check during @PostLoad.


              Ingo

              • 4. Re: Securing params with drools
                mgvarley

                Hi Ingo - sorry for the slow reply, I'd given up on this and placed the security checks in the loadInstance() methods of my EntityHome classes - just seen your post and followed your suggestion though and got this working - thanks very much! :o)


                mark