Interface SpnegoAccessControl


  • public interface SpnegoAccessControl
    Defines an object for performing user authorization (authZ). See the javadoc of the UserAccessControl interface and the LdapAccessControl class for more details about the default underlying implementation that this interface relies upon.

    In simple terms, roles are attributes that belong to a user and that an attribute is something that MUST exist in an attribute set. This treatment is somewhat similar to the traditional sense that users are assigned roles and/or role_groups.

    One dissimilarity is that an attribute MUST exist in an attribute set. Another is that users are defined only by their attributes and not by their attribute sets. This is in contrast to the role based approach where roles do not have to belong to a role_group. In addition, a role_group can be concretely assigned to a user, whereas an attribute set can NOT be concretely assigned to a user.

    Some example attribute sets within an Organization might include: Job Title, Company Department, Company Division, Company Location, Active Directory Group, Email Distribution List, etc. An attribute set is unique within the set of all attribute sets. An attribute MUST exist in only one attribute set. Hence, an example where job titles might include titles such as Developer, Manager, Analyst, HR Admin, Account Executive, and Receptionist, any and all job titles MUST exist in only one attribute set AND they MUST all be in the same attribute set.

    In the example above, the source of attribute information is defined as existing in an LDAP/Active Directory Group, User Department, Email Distribution List, etc. A policy is configured to search one of these attribute sets or optionally to search all of these attribute sets. The attribute sets can be mixed to allow for a more expressive policy statement. e.g. 1) A user has access if they are in this AD Group and belong in one of these departments, or 2) a user has access if they are in this email distribution list and in one of these AD Groups or is in one these departments, or 3) a user can see the edit button if they are in this AD Group and in one of these other AD Groups.

    Attribute Set Example Scenario:
    This example will assume Active Directory (AD) as the data store for user information. This example also assumes that in AD there are three AD Groups named File Share Access, Finance London, and Desktop Support. Finally, we assume that the department attribute in AD's user profile is populated for each user. Example values in the Departments attribute set might be IT, Accounting, or HR. Under this scenario, AD Groups would be one attribute set and Departments would be another attribute set.

    Here's another way of illustrating the concepts from the above example scenario (this is NOT example code but instead is only meant to be illustrative of the mental model).

     // this is not code and not even pseudo-code... the only purpose is to help depict a mental model
     final Map<String, List<String>> attributeSet = new HashMap<>();
     
     attributeSet.put("AD Groups"
             , Arrays.asList(new String [] {"File_Share_Access", "Finance_London", "Desktop_Support"}));
     
     attributeSet.put("Departments"
             , Arrays.asList(new String [] {"IT", "Accounting", "HR"}));
     

    Notice that you concretely assign an attribute (e.g. Accounting) to a user instead of assigning an attribute set (e.g. Departments to a user). The reason being is that the the attribute set Departments contains many attributes within it: IT, Accounting, and HR.

    Example Usage 1:
    A web application/service requires authentication (authN) but certain areas must only be accessed by users who are in the HR department OR have been added to the AD Group named File Share Access OR those users who have a value of Desktop Support in their department attribute in AD.

     boolean hasPermission = false;
     
     String[] attributes = new String[] {"HR", "File Share Access", "Desktop Support"};
     
     if (request instanceof SpnegoAccessControl) {
         SpnegoAccessControl accessControl = (SpnegoAccessControl) request;
         
         hasPermission = accessControl.anyRole(attributes);
     } 
     
    In the above example, the method call anyRole will return true if the user is in the department named HR or the AD Group named "File share Access" or is in the department named "Desktop Support".

    Example Usage 2: Certain areas of a web application/service must only be accessed by users who are in the AD Group File Share Access AND who are in the AD Group Finance London or who are in the Accounting department.

     boolean hasPermission = false;
     
     String attributeX = "File Share Access";
     String[] arttributeYs = new String[] {"Finance London", "Accounting"};
     
     if (request instanceof SpnegoAccessControl) {
         SpnegoAccessControl accessControl = (SpnegoAccessControl) request;
         
         hasPermission = accessControl.hasRole(attributeX, attributeYs);
     } 
     
    In the above example, if the user has the attribute File Share Access AND one of the attributeYs (Finance London or Accounting), the method call hasRole will return true.

    User-defined Resource Label Example:

    An alternative to specifying department names, groups, email distribution lists, etc. is to use a user-defined resource label. Resource labels are optional and hence must undergo additional configuration before use.

     boolean hasPermission = false;
     
     if (request instanceof SpnegoAccessControl) {
         SpnegoAccessControl accessControl = (SpnegoAccessControl) request;
         
         hasPermission = accessControl.hasAccess("finance-links");
     } 
     

    In the above example, the attribute(s) that support the policy is abstracted by the user-defined resource label named finance-links. Concretely, given the previous example, the resource label finance-links would be assigned the attributes File Share Access, Finance London, and Accounting.

    The Java HttpServletRequest Interface and it's isUserInRole method

    In addition to how the HttpServletRequest interface defines a getRemoteUser method to retrieve the name of the authenticated (authN) user, the HttpServletRequest interface also defines an isUserInRole method that "returns a boolean indicating whether the authenticated user is included in the specified logical 'role'". In all of the examples above, a Java Cast was necessary to achieve the functionality of the SpnegoAccessControl interface. However, the isUserInRole method obviates the need to perform a Java Cast.

    No java cast example:

     boolean hasPermission = request.isUserInRole("File Share Access");
     

    In the above example, the Java Cast was not necessary because the standard HttpServletRequest Interface defines the isUserInRole method and the SPNEGO Library implements the isUserInRole method of the interface. Although convenient, available, and performs as expected, the isUserInRole method alone may not be as expressive as the methods defined in the SpnegoAccessControl interface.

    For more information regarding implementation details, as well as additional usage examples, please see the javadoc for the UserAccessControl interface as well as the javadoc for the LdapAccessControl class.

    Also, take a look at the reference docs for a complete list of configuration parameters.

    Finally, to see a working example and instructions, take a look at the enable authZ with LDAP guide.

    Author:
    Darwin V. Felix
    • Method Summary

      All Methods Instance Methods Abstract Methods 
      Modifier and Type Method Description
      boolean anyAccess​(String... resources)
      Checks to see if the user has at least one of the passed-in user-defined resource labels
      boolean anyRole​(String... attributes)
      Checks to see if the user has at least one of the passed-in attributes.
      UserInfo getUserInfo()
      Returns the user's info object.
      boolean hasAccess​(String resource)
      Checks to see if the user has access to the user-defined resource label.
      boolean hasAccess​(String resourceX, String... resourceYs)
      Checks to see if the user has the first user-defined resource label AND has at least one of the passed-in user-defined resource labels.
      boolean hasRole​(String attribute)
      Checks to see if the user has the passed-in attribute.
      boolean hasRole​(String attributeX, String... attributeYs)
      Checks to see if the user has the first attribute AND has at least one of the passed-in attributes.
    • Method Detail

      • anyRole

        boolean anyRole​(String... attributes)
        Checks to see if the user has at least one of the passed-in attributes.
         String[] attributes = new String[] {"Developer", "Los Angeles", "Manager"};
         
         if (accessControl.anyRole(attributes)) {
             // will be in here if the user has at least one matching attribute
         }
         
        Parameters:
        attributes - e.g. Team Lead, IT, Developer
        Returns:
        true if the user has at least one of the passed-in roles/features
      • hasRole

        boolean hasRole​(String attribute)
        Checks to see if the user has the passed-in attribute.
         String attribute = "Developer";
         
         if (accessControl.hasRole(attribute)) {
             // will be in here if the user has the matching attribute
         }
         
        Parameters:
        attribute - e.g. Team Lead, IT, Developer
        Returns:
        true if the user has at least one of the passed-in roles/features
      • hasRole

        boolean hasRole​(String attributeX,
                        String... attributeYs)
        Checks to see if the user has the first attribute AND has at least one of the passed-in attributes.
         String attributeX = "Los Angeles";
         String[] attributeYs = new String[] {"Developer", "Manager"};
         
         if (accessControl.hasRole(attributeX, attributeYs)) {
             // will be in here if the user has attributeX 
             // AND has at least one of the attributeYs.
         }
         
        Parameters:
        attributeX - e.g. Information Technology
        attributeYs - e.g. Team Lead, IT-Architecture-DL
        Returns:
        true if the user has featureX AND at least one the featureYs
      • anyAccess

        boolean anyAccess​(String... resources)
        Checks to see if the user has at least one of the passed-in user-defined resource labels
         String[] resources = new String[] {"admin-links", "ops-buttons"};
         
         if (accessControl.anyAccess(resources)) {
             // will be in here if the user has at least one matching resource
         }
         
        Parameters:
        resources - e.g. admin-links, ops-buttons
        Returns:
        true if the user has at least one of the passed-in resources
      • hasAccess

        boolean hasAccess​(String resource)
        Checks to see if the user has access to the user-defined resource label.
         boolean hasPermission = false;
         
         if (request instanceof SpnegoAccessControl) {
             SpnegoAccessControl accessControl = (SpnegoAccessControl) request;
             
             hasPermission = accessControl.hasAccess("finance-links");
         } 
         
        Parameters:
        resource - e.g. admin-buttons
        Returns:
        true if the user has access to the user-defined resource
      • hasAccess

        boolean hasAccess​(String resourceX,
                          String... resourceYs)
        Checks to see if the user has the first user-defined resource label AND has at least one of the passed-in user-defined resource labels.
         String resourceX = "finance-links";
         String[] resourceYs = new String[] {"admin-links", "accounting-buttons"};
         
         if (accessControl.hasAccess(resourceX, resourceYs)) {
             // will be in here if the user has resourceX 
             // AND has at least one of the resourceYs.
         }
         
        Parameters:
        resourceX - e.g. finance-links
        resourceYs - e.g. admin-links, accounting-buttons
        Returns:
        true if the user has resourceX AND at least one the resourceYs
      • getUserInfo

        UserInfo getUserInfo()
        Returns the user's info object.
        Returns:
        the user's info object