Details

    • Type: New Feature New Feature
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Component/s: None
    • Labels:
      None

      Description

      Many Java EE implementations (but not all), require a process that's often called "group to role mapping". The idea here is that authentication/login modules (either proprietary or the standardized JASPIC SAMs) never return "roles", but return "groups". A deployer then maps the roles that the application uses to the groups that the authentication module returns.

      This mechanism is useful for when a single authentication module is used to provide security for a number of different applications that each use different names for the same logical role. The way this group to role mapping is done is almost the same for every Java EE implementation, but uses incompatible syntax in proprietary deployment descriptors.

      For instance, mapping a single role for GlassFish, WebLogic, WebSphere and Geronimo looks as follows:

      GlassFish 3.1.2.2
      WEB-INF/sun-web.xml 
      
      <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" 
          "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
      <sun-web-app>
       
          <security-role-mapping>
              <role-name>architect</role-name>
              <group-name>architect</group-name>
          </security-role-mapping>
       
      </sun-web-app>
      
      WebLogic 12c (12.1.1)
      WEB-INF/weblogic.xml 
      
      <weblogic-web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-web-app.xsd"
          xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
       
          <security-role-assignment>
              <role-name>architect</role-name>
              <principal-name>architect</principal-name>
          </security-role-assignment>
       
      </weblogic-web-app>
      
      WebSphere 8.5
      [EAR]/META-INF/ibm-application-bnd.xml 
      
      <application-bnd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-application-bnd_1_1.xsd"
          xmlns="http://websphere.ibm.com/xml/ns/javaee"
          version="1.1">
       
          <security-role name="architect"> 
              <group name="architect" />
          </security-role>
           
      </application-bnd>
      
      Geronimo v3.0
      WEB-INF/geronimo-web.xml 
      
      <web:web-app
          xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0"
      >
       
          <sec:security>
              <sec:role-mappings>
                  <sec:role role-name="architect">
                      <sec:principal
                          class="org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal"
                          name="architect"
                      />
                  </sec:role>
              </sec:role-mappings>
          </sec:security>
           
      </web:web-app>
      

      Having a different syntax for basically the same thing hurts portability and makes it unnecessarily difficult for a Java EE developer to transfer his or her skills to a different Java EE implementation.

      Further more, although role mapping can be an essential feature for some use cases, it can be totally unnecessary for others. If there's nothing to map, then requiring the developer to provide a group to role mapping anyway isn't exactly following the ease-of-use theme that Java EE 5 started.

      I would therefor like to propose the introduction of a standardized syntax for group to role mapping with the special case of a standard way to declare that no such mapping should be done.

      Standardized group to role mapping can possibly take advantage of the existing security-role-ref in deployers such as web.xml.

      E.g.: when the full double indirection is used:

      <security-role-ref>
          <!-- Role name as set/returned by Authentication Module -->
          <role-group>Management</role-group>
      
          <!-- Role name for mapping -->
          <role-name>MGR</role-name>
          
          <!-- Role name used in code -->
          <role-link>manager</role-link>
      </security-role-ref>
      

      When single indirection is used:

      <security-role-ref>
          <!-- Role name as set/returned by Authentication Module -->
          <role-group>Management</role-group>
      
          <!-- Role name used in code -->
          <role-name>MGR</role-name>
      </security-role-ref>
      

      When no indirection is used:

      <security-role-ref groupToRoleMapping="false" />
      

      The last fragment could become the default to be more consistent with the situation when no role-link is used (e.g. a developer also doesn't have to explicitly specify that a "roleToLink" mapping should not be done).

      Optionally the two steps of role mapping could be separated as follows:

      <security-role-ref>
          <!-- Role name as set/returned by Authentication Module -->
          <role-group>Management</role-group>
      
          <!-- Role name for mapping -->
          <role-name>MGR</role-name>
      </security-role-ref>
      
      <security-role-ref>
          <!-- Role name for mapping -->
          <role-name>MGR</role-name>
          
          <!-- Role name used in code -->
          <role-link>manager</role-link>
      </security-role-ref>
      

      An additional benefit of standardized group to role mapping could be that it can automatically take advantage of the configuration efforts done in Java EE 8 (see also JAVAEE_SPEC-19).

        Activity

        Hide
        arjan tijms added a comment -

        Note that in the security-role-ref samples above I accidentally switched role-name and role-link (unfortunately it's not possible to edit your own issue's description).

        The assumption was also that the security-role-ref element would be re-used outside the servlet element, but on second thought that's perhaps not really clear and it would be better to introduce a new element.

        The given syntax at any length is of course just an example, the key requirement is that role mapping is standardized (in whatever way) and there's the option to turn role mapping completely off (in whatever way).

        Show
        arjan tijms added a comment - Note that in the security-role-ref samples above I accidentally switched role-name and role-link (unfortunately it's not possible to edit your own issue's description). The assumption was also that the security-role-ref element would be re-used outside the servlet element, but on second thought that's perhaps not really clear and it would be better to introduce a new element. The given syntax at any length is of course just an example, the key requirement is that role mapping is standardized (in whatever way) and there's the option to turn role mapping completely off (in whatever way).
        Hide
        arjan tijms added a comment -

        Example of people running into this issue: http://stackoverflow.com/questions/2230717/dynamic-roles-on-a-java-ee-server

        For the particular use case described in that link it's not only important that an application can indicate there's no mapping required, but also that roles don't need to be declared upfront. Indeed, if the main reason for declaring roles upfront is to the make the job of the person who does role mapping easier, then this too will not be needed if there's no role mapping at all.

        Show
        arjan tijms added a comment - Example of people running into this issue: http://stackoverflow.com/questions/2230717/dynamic-roles-on-a-java-ee-server For the particular use case described in that link it's not only important that an application can indicate there's no mapping required, but also that roles don't need to be declared upfront. Indeed, if the main reason for declaring roles upfront is to the make the job of the person who does role mapping easier, then this too will not be needed if there's no role mapping at all.
        Hide
        alex.kosowski added a comment -

        I understand the point that group-to-role mapping should not be required for simple cases where groups and roles map one-to-one.

        However, regarding "dynamic" roles:

        1. Are you referring to applications being able to change roles of users during runtime? Would a Java EE API allowing applications to create users and change roles assigned satisfy this?

        OR

        2. Are you referring to consuming dynamic roles in the authorization checking? That is, not requiring all roles declared upfront (via web.xml or @DeclareRoles) and conditioning the authorization on the result of a calculation using an arbitrary role name?
        For example:
        The application assigns roles like <Customer>_ADMIN or "ACME_ADMIN" and the authorization logic is like this pseudocode:
        if ( isAuthorized( subject.getRole().contains( "_ADMIN" ) ) )

        { // Do privileged stuff }

        Is this a common use case? Would you please provide a use case for this?

        Thanks,
        Alex

        Show
        alex.kosowski added a comment - I understand the point that group-to-role mapping should not be required for simple cases where groups and roles map one-to-one. However, regarding "dynamic" roles: 1. Are you referring to applications being able to change roles of users during runtime? Would a Java EE API allowing applications to create users and change roles assigned satisfy this? OR 2. Are you referring to consuming dynamic roles in the authorization checking? That is, not requiring all roles declared upfront (via web.xml or @DeclareRoles) and conditioning the authorization on the result of a calculation using an arbitrary role name? For example: The application assigns roles like <Customer>_ADMIN or "ACME_ADMIN" and the authorization logic is like this pseudocode: if ( isAuthorized( subject.getRole().contains( "_ADMIN" ) ) ) { // Do privileged stuff } Is this a common use case? Would you please provide a use case for this? Thanks, Alex
        Hide
        arjan tijms added a comment -

        Are you referring to applications being able to change roles of users during runtime? Would a Java EE API allowing applications to create users and change roles assigned satisfy this?

        Although that wasn't what I meant with the above, that functionality is most definitely needed as well. I created a separate issue some time ago for that: JASPIC_SPEC-22

        That is, not requiring all roles declared upfront (via web.xml or @DeclareRoles) and conditioning the authorization on the result of a calculation using an arbitrary role name?

        Yes, that's it

        Would you please provide a use case for this?

        There are actually two use cases for this.

        The first is about convenience and simplifications. The problem here is that "registering things in XML" is a kind of universal pain that Java EE users have had to endure, and I'm convinced it's one of the things that gave Java EE a bad name. JSF users had to register components, converters, validators and what have you in XML before they could be used. Early EJB users had to do a similar thing. An ongoing effort to make Java EE simpler is to omit these registrations or make them optional, especially if they don't really serve a purpose from the point of view of the end-user.

        Role registration in Java EE is just like that. Suppose a SAM sets the authenticated result to consist of a user "Pete" with roles "foo" and "bar". Then having to register "foo" and "bar" in some XML file is just a nuisance to the user. It's hard to explain to them why the registration is needed. Older explanations used to say in very formal language about the 'deployer' being able to 'obtain a security view of the application' and then be able to 'map it to the runtime environment'.

        Many users I'm afraid would just stare at that for a moment, shrug, and then just don't use Java EE security.

        If no role mapping is used, then there's no security view for a deployer needed for mapping the roles, hence declaration would not be needed. While at the topic of security view for a deployer. I haven't really seen this happening in practice. Deploys are mostly automated via something like Jenkins these days. There's no actual person that during deployment uses some tooling that gives a list back of all roles in the app, then at the spot goes on mapping names on this list to roles in the environment. While theoretically maybe useful in practice to deploy unknown externally obtained apps, I don't think this is how modern software development cycles work in practice.

        So requiring roles to be declared makes what I think is a minor use case possible, while causing much pain for a larger amount of people.

        The other use case concerns systems where pages are added dynamically and external users register with the system (e.g. a typical public Wordpress or Wiki scenario). In such systems it might be wanted to create roles dynamically at run-time and then access them to users dynamically at run-time (note that it's not required for this mechanism to let users get those roles while logged-in; a log-out/log-in would be okay here). Examples of such roles might be "ACCESS_COMPUTERS_PAGE" or "EDIT_COMPUTERS_PAGE", etc.

        Of course there are plenty of other mechanisms to realize the above, but I've seen people who wanted to do stuff like that.

        There's one big complication to the dynamic role mapping, and that complication is called JACC.

        From my article on this:

        Typically JACC providers will create the total list of WebRoleRefPermission instances when an application is deployed and then return a sub-selection based on the Principals that we (indirectly) passed in our call to Policy#getPermissions. This however requires that all roles are statically and upfront declared. But a JASPIC auth module can dynamically return any amount of roles to the container and via HttpServletRequest#isUserInRole() an application can dynamically query for any such role without anything needing to be declared. Unfortunately such dynamic role usage typically doesn't work when JACC is used (the Java EE specification also forbids this, but on servers like JBoss it works anyway).

        See: http://arjan-tijms.blogspot.com/2014/03/implementing-container-authorization-in.html

        The most important purpose of this issue remains the standardized role mapping itself (which incidentally can also be used then to plug a major hole in JACC) with the special case of no role mapping.

        Not having to declare roles is a nice bonus that makes things a lot easier to many users, but may things difficult for JACC. While I think JACC isn't used that much by users, servers like GlassFish use it internally.

        Show
        arjan tijms added a comment - Are you referring to applications being able to change roles of users during runtime? Would a Java EE API allowing applications to create users and change roles assigned satisfy this? Although that wasn't what I meant with the above, that functionality is most definitely needed as well. I created a separate issue some time ago for that: JASPIC_SPEC-22 That is, not requiring all roles declared upfront (via web.xml or @DeclareRoles) and conditioning the authorization on the result of a calculation using an arbitrary role name? Yes, that's it Would you please provide a use case for this? There are actually two use cases for this. The first is about convenience and simplifications. The problem here is that "registering things in XML" is a kind of universal pain that Java EE users have had to endure, and I'm convinced it's one of the things that gave Java EE a bad name. JSF users had to register components, converters, validators and what have you in XML before they could be used. Early EJB users had to do a similar thing. An ongoing effort to make Java EE simpler is to omit these registrations or make them optional, especially if they don't really serve a purpose from the point of view of the end-user. Role registration in Java EE is just like that. Suppose a SAM sets the authenticated result to consist of a user "Pete" with roles "foo" and "bar". Then having to register "foo" and "bar" in some XML file is just a nuisance to the user. It's hard to explain to them why the registration is needed. Older explanations used to say in very formal language about the 'deployer' being able to 'obtain a security view of the application' and then be able to 'map it to the runtime environment'. Many users I'm afraid would just stare at that for a moment, shrug, and then just don't use Java EE security. If no role mapping is used, then there's no security view for a deployer needed for mapping the roles, hence declaration would not be needed. While at the topic of security view for a deployer. I haven't really seen this happening in practice. Deploys are mostly automated via something like Jenkins these days. There's no actual person that during deployment uses some tooling that gives a list back of all roles in the app, then at the spot goes on mapping names on this list to roles in the environment. While theoretically maybe useful in practice to deploy unknown externally obtained apps, I don't think this is how modern software development cycles work in practice. So requiring roles to be declared makes what I think is a minor use case possible, while causing much pain for a larger amount of people. The other use case concerns systems where pages are added dynamically and external users register with the system (e.g. a typical public Wordpress or Wiki scenario). In such systems it might be wanted to create roles dynamically at run-time and then access them to users dynamically at run-time (note that it's not required for this mechanism to let users get those roles while logged-in; a log-out/log-in would be okay here). Examples of such roles might be "ACCESS_COMPUTERS_PAGE" or "EDIT_COMPUTERS_PAGE", etc. Of course there are plenty of other mechanisms to realize the above, but I've seen people who wanted to do stuff like that. There's one big complication to the dynamic role mapping, and that complication is called JACC. From my article on this: Typically JACC providers will create the total list of WebRoleRefPermission instances when an application is deployed and then return a sub-selection based on the Principals that we (indirectly) passed in our call to Policy#getPermissions. This however requires that all roles are statically and upfront declared. But a JASPIC auth module can dynamically return any amount of roles to the container and via HttpServletRequest#isUserInRole() an application can dynamically query for any such role without anything needing to be declared. Unfortunately such dynamic role usage typically doesn't work when JACC is used (the Java EE specification also forbids this, but on servers like JBoss it works anyway). See: http://arjan-tijms.blogspot.com/2014/03/implementing-container-authorization-in.html The most important purpose of this issue remains the standardized role mapping itself (which incidentally can also be used then to plug a major hole in JACC) with the special case of no role mapping. Not having to declare roles is a nice bonus that makes things a lot easier to many users, but may things difficult for JACC. While I think JACC isn't used that much by users, servers like GlassFish use it internally.

          People

          • Assignee:
            alex.kosowski
            Reporter:
            arjan tijms
          • Votes:
            14 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated: