Version 16

    Using Labs Auth Service

     

    Understanding the principles

     

    Labs Authentication service is designed having in mind that service developer shouldn't care about user roles and granting or revoking privileges from/to a user. All of this is done by separate view designed only for granting/revoking roles.

     

    That is why the service introduces separate role system called Service Roles. They can be bound to user roles but this isn't anything you, service/view developer, should worry about.

     

    Below you can see architecture with an example permission check.

     

     

    There are two services you're going to use - org.jboss.labs.auth.RoleBinderService and org.jboss.labs.auth.AuthenticationService. First one is for exposing Service Roles (see below) and the second one is to check if given user has access to something. We'll show details later on; let's start with analyzing how a request is done.

     

    In our example we've designed 3 Service Roles. Those roles are bound to implementation - we have ADMIN, CLERK and USER. Let's assume we're writing view for internet shop. ADMIN can do everything including managing users, setting rates for workers etc; CLERK can add or remove products and access orders; USER can browse products and place orders.

     

    User that's browsing our shop (Important: it's not a USER from service roles) clicked on "Edit product" on a cauliflower. We need to check if "User A" that's browsing the shop can access part of it reserved for CLERKs. Here's what happens:

     

    1. Our view checks isAllowedProject on AuthenticationService for our User A, Service Role CLERK and our project fooProject /in labs we have different projects so it doesn't fit really to a shop. This could have been "groceries", so only CLERKs from "groceries" division would have access/

    2. System checks if the user is one of the global SuperUsers (those guys can do anything. It could've been shop owner or CEO). In this case User A is not a SuperUser.

    3. Next system checks if User A is SuperUser for a project. In this case fooProject/groceries. Still he's not a project SuperUser.

    4. Last thing system does is checking if there is a binding for three parameters: User Role, being one of those our User A has (as you can see he has three roles RoleA, RoleB, RoleC), Service Role (here: CLERK) and projectID (fooProject/groceries). System found this binding and returns true.

     

    That's it. Simple, huh ?

     

    Integrating your application

     

    First thing you have to do as a developer is figure out what Service Roles you're going to use in your application. Divide it into a number of roles and create an Enum out of it. On top of that this Enum needs to implement org.jboss.labs.auth.ServiceDescriptor. This interface has just two methods used by binding auth view to show them in an understandable way.

     

         /**
          * Gets description for role
          * 
          * @param <E>
          *            Role from Enum.
          * @param role
          *            Role to get description for
          * @return Description for role
          */
         public <E extends Enum<E> & ServiceDescriptor> String getDescription(E role);
    
         /**
          * @return Returns description for this service
          */
         public String getServiceDescription();
    

     

     

    It's a good idea to implement them properly.getDescription(E role) might be just a switch with a number of returned Strings.

     

    And that's it. For our shop example from above we could do something like:

         public enum ShopRoles implements ServiceDescriptor {
         ADMIN, CLERK, USER;
    
         public <E extends Enum<E> & ServiceDescriptor> String getDescription(E role) {
              if (role.equals(ADMIN)) {
                   return "Administrator of a shop";
              }
              else if (role.equals(CLERK)) {
                   return "Clerk of a shop division";
              }
              else if (role.equals(USER)) {
                   return "Guy that makes shopping";
              }
    
              return null;
         }
    
         public String getServiceDescription() {
              return "Internet shop";
         }
    
    }
    

     

    Application that has authentication separated to projects

     

    If you're going to use your application with authentication separated to number of projects, that's the way you're going to use Auth service (this doesn't mean of course you can't mix it with CustomID approach).

     

    First thing is that you have to register your Service Roles. Just execute RoleBinderService.exposeServiceRoles(serviceRoleList) when your application is started. This will register Service Roles with descriptions and switch off those Service Roles you decided stop using.

     

    Every permission check will be checked against Service Role, user and specified project. For example in admin view when a user clicks on "Edit project" we're going to check some "Admin Service Role" for a project he clicked on. To check permissions in that way just call

     

    AuthenticationService.isAllowedProject(user, serviceRole, projectId) and that's it. You'll get single boolean telling you if he is or is not allowed to do it.

     

    Application that is not connected with project

     

    Similarly as above you have to register your Service Roles by executing RoleBinderService.exposeServiceRolesAndRegisterCustomIDProvider(serviceRoleList, customIDProvider) on application start. What is a customIDProvider ? It's something that provides ids :-).

     

    So first of all what is a CustomID ? CustomID is equivalent of projectID (both can be used in bindings User Role + Service Role + ID) but for application that have nothing to do with projects. So, again, what is it ? It's something in your application you wanna manage permissions for. It can be forum topic or entry, wiki page, shop item, shop category etc. etc. Those customID are generated by your application and can be managed the same way as projects in auth binding view (but you may want to do it yourself).

     

    To generate CustomIDs you need CustomIDProvider registered when starting your application. There are two types of CustomIDProvider. When implementing CustomIDProvider you need to implement at least one method

    Set<CustomID> getCustomIDs() . The way it's going to be used depends on the type of a provider.

     

    1. Buffered

     

    Buffered provider executes getCustomIDs() only when it's registered and buffers CustomIDs. To add new ones or remove old ones you need to call void addCustomIDs(CustomID... newIds or void removeCustomIDs(CustomID... ids.

     

    So getCustomIDs() will be executed only once and then when new id is created you have to add it by hand. This approach is more efficient then the next one therefore it's suggested.

     

    2. Non-buffered

     

    Sometimes you wish to return whole set of available CustomIDs every time someone is checking permissions. In this case you're going to use non-buffered provider. To make a provider non-buffered overwrite boolean isBuffered() and make it return FALSE.

     

    In this case you're not allowed to use addCustomIDs(...) at all - it will throw RuntimeException. You can, however, run removeCustomIDs(CustomID... ids) to remove old ones from data base.

     

    So getCustomIDs() will get executed every time someone checks permissions in your application.

     

    One last thing is that you might want to have some logic executed for every addCustomIDs (buffered) or removeCustomIDs (both types). You can achieve it by implementing void addCustomIDsOps(CustomID... newIds) and/or void removeCustomIDs(CustomID... ids)

     

    Finally when you want to check permissions just call

    AuthenticationService.isAllowedCustom(user, serviceRole, customId). You'll get a boolean.