javaee-security-spec
  1. javaee-security-spec
  2. JAVAEE_SECURITY_SPEC-10

Simplify and standardize authentication & role mapping

    Details

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

      Description

      In Java EE declaring security constraints via e.g. @RolesAllowed, programmatically checking them via e.g. HttpServletRequest#isUserInRole and triggering a container login via HttpServletRequest#login is all relatively straightforward.

      Unfortunately, providing the logic for the actual authentication and role mapping/retrieval remains a cumbersome exercise. This is especially painful for simple applications which don't need elaborate security abstractions. JASPI/JASPIC (JSR 196) did provide a means to make authentication modules portable in Java EE 6, but actually using those remains a fairly tedious and vendor specific process.

      For instance, JBoss AS 7 requires the following steps:

      1. Create a named security domain outside the application in a vendor specific way, that's tied to a specific AS instance.
      2. Connect the JASPI authentication module to this security domain in a vendor specific way.
      3. Declare in web.xml that JASPI is the realm.
      4. Link the (web) application itself to the global security domain using a vendor specific descriptor.
      5. In the vendor specific descriptor, specify an internal vendor specific class name that's internally needed to activate JASPI.

      (See https://community.jboss.org/wiki/JBossAS7EnablingJASPIAuthenticationForWebApplications)

      GlassFish requires the user to take different, but similar steps including interacting with a graphical UI (see http://www-02.imixs.com/roller/ralphsjavablog/entry/openid_serverauthmodule_jsr_196_with)

      Not only are these steps anti ease-of-use, they are also notoriously non-portable despite JASPI's promise of portability. Furthermore, having the authentication logic outside the application itself prohibits the developer to easily make use of application domain models and code for the authentication process (which is typical for applications that manage their users internally and don't need to integrate with an overall user directory system of e.g. an enterprise).

      I therefor would like to propose standardizing how JASPI authentication modules can be embedded in (simple) applications in a portable way, and additionally address the use case that for small/test applications even a JASPI module is too much and something even simpler is needed. This is especially true when the application already makes use of a custom mechanism (typically a Servlet Filter) in combination with HttpServletRequest#login.

      Example of simplified authentication/role mapping:

      @AppLoginModule
      public class MyAuthenticator implements PasswordLoginModule {
      
          private User user;
      
          @Inject
          private UserService userService;
      
          public void authenticate(String name, String password) {
              user = userService.getByNameAndPassword(name, password);
              if (user == null) {
                  throw new FailedLoginException();
              }
          }
      
          public String getUserName() {
              return user.getName();
          }
      
          public List<String> getApplicationRoles() {
              return user.getRoles();
          }
      }
      

      Following the presence of such simplified login module in the application, the following should hold:

      • The application is considered to be in a default security realm.
      • The application will make use of this security realm (no explicit mention in web.xml required).
      • Whenever a container login is triggered, MyAuthenticator is used for authentication (only username/password supported of course)
      • If authentication succeeds, the String returned by getUserName will be what HttpServletRequest#getUserPrincipal.getName() and corresponding methods in EJB etc return.
      • For each String inside the list returned by getApplicationRoles, methods like HttpServletRequest#isUserInRole will return true, and annotations like @RolesAllowed referencing those will be considered satisfied.
      • No upfront declaration of roles in any descriptor is required.
      • The roles returned by getApplicationRoles should be directly useable in the application. Specifically, things as (vendor specific) group to role mappings (such as what happens in GlassFish) should not be required.

      Example of standardized installation of a JASPI authentication module in application.xml or web.xml:

      <server-auth-module>
          <class-name>my.example.HTTPBasicServerAuthModule</class-name>
          <property>
              <name>usersProperties</name>
              <value>somepath/users.properties</value>
           </property>
      </server-auth-module>
      

      Alternatively, the presence of a JASPI authentication module inside the application annotated with a special annotation (perhaps the same one as used for the simplified login module), can have the same effect of having the module automatically installed.

      Like the simplified login module, when such a JASPI authentication module is declared in an application, no further configuration, role mapping or role declarations should be required, other than those that are specific for the authentication module itself.

        Activity

        arjan tijms created issue -
        Hide
        perissf added a comment - - edited

        Arjan, I support your feature request, and would like to add my point of view. When developing a "Remember me" feature, the application needs to authenticate the user in the absence of a password. The same application, wants to authenticate with username & password on the first login attempt, and wants to have a container-managed authentication through HttpServletRequest#login. This is clearly not possible in the "Remember me" situation, unless the application stores the password somewhere in clear text. Or unless developing a custom authentication module. Please correct me if I am wrong.

        Show
        perissf added a comment - - edited Arjan, I support your feature request, and would like to add my point of view. When developing a "Remember me" feature, the application needs to authenticate the user in the absence of a password. The same application, wants to authenticate with username & password on the first login attempt, and wants to have a container-managed authentication through HttpServletRequest#login. This is clearly not possible in the "Remember me" situation, unless the application stores the password somewhere in clear text. Or unless developing a custom authentication module. Please correct me if I am wrong.
        Hide
        rmonzillo added a comment -

        common configuration of SAM's in compatible Servlet containers is something that JASPIC facilitates, but we need to give better guidance on how to accomplish that (by registering a common AuthConfigProvider at the target platform). The Glassfish RI includes the JAASServletAuthConfigProvider as one such AuthConfigProvider. We are creating examples of the portable use the JASPIC methodology under the Nobis Project see:
        http://java.net/projects/nobis/sources/git/show/Nobis/authentication

        I am still considering your proposal above, and I intend to comment further. Generally speaking I think that most of the pieces are in place to support the authentication aspects of your use case; but that we should consider how we might provide applications with interfaces to create application users and/or to assign them privileges (i.e., to roles). As part of our work on the Java Identity API interfaces we would like to make such interfaces available to java apps (although at the current time, our focus is mostly on lookup style interactions).

        I also added a comment on the thread in the JBOSS forum see:
        https://community.jboss.org/wiki/JBossAS7EnablingJASPIAuthenticationForWebApplications#comment-10581

        regarding support for "remember me", we might consider adding a control flag to HttpServletRequest.login. However it would likely be sufficient to collect this control information as part of the authentication dialog with the user, and apply it in the underlying authentication mechanism. Moreover to facilitate that for FBL, we might consider defining a corresponding optional parameter to accompany j_username and j_password. Where we are using a jsr 196 sam for container authentication, the extraction of the indicated remember me effect from the HttpServletRequest messages could be handled by the pluggable auth module.

        Show
        rmonzillo added a comment - common configuration of SAM's in compatible Servlet containers is something that JASPIC facilitates, but we need to give better guidance on how to accomplish that (by registering a common AuthConfigProvider at the target platform). The Glassfish RI includes the JAASServletAuthConfigProvider as one such AuthConfigProvider. We are creating examples of the portable use the JASPIC methodology under the Nobis Project see: http://java.net/projects/nobis/sources/git/show/Nobis/authentication I am still considering your proposal above, and I intend to comment further. Generally speaking I think that most of the pieces are in place to support the authentication aspects of your use case; but that we should consider how we might provide applications with interfaces to create application users and/or to assign them privileges (i.e., to roles). As part of our work on the Java Identity API interfaces we would like to make such interfaces available to java apps (although at the current time, our focus is mostly on lookup style interactions). I also added a comment on the thread in the JBOSS forum see: https://community.jboss.org/wiki/JBossAS7EnablingJASPIAuthenticationForWebApplications#comment-10581 regarding support for "remember me", we might consider adding a control flag to HttpServletRequest.login. However it would likely be sufficient to collect this control information as part of the authentication dialog with the user, and apply it in the underlying authentication mechanism. Moreover to facilitate that for FBL, we might consider defining a corresponding optional parameter to accompany j_username and j_password. Where we are using a jsr 196 sam for container authentication, the extraction of the indicated remember me effect from the HttpServletRequest messages could be handled by the pluggable auth module.
        Hide
        arjan tijms added a comment -

        Ron, I've created a blog post about this very topic at: http://arjan-tijms.blogspot.com/2012/11/implementing-container-authentication.html

        There I tried to programmatically register an example SAM on 4 different servers in a portable way. One of the major problems I run into is with the appContext. The spec certainly provides a definition for this for the Servlet Profile, but it's still not clear what an application doing registration should provide here. Different application server implementations also seem to want different things here. Most want "server [application context path]", but JBoss AS/EAP wants ["ServletRequest#getLocalName" [application context path]" here.

        The other major problem is that every application server still insists on the user providing a proprietary deployment descriptor, mostly for things like role mapping and the specification of a domain/realm.

        Above I asked that the roles returned by the proposed @AppLoginModule would be accepted without requiring to be mapped, but maybe we can go a step further and demand that the roles a JASPIC SAM puts into the JAAS Subject are useable without any required vendor specific mapping?

        I think the ideal is that without any vendor specific deployment descriptor present (like WEB-INF/sun-web.xml), roles would be directly accepted. Then if there is such a deployment descriptor present, it can be used to optionally map some or all of the roles. Of course, it's at the vendor's discretion if further options are provided to e.g. completely turn off mapping or to mandate mapping for all roles, etc. This is fine, as long as those options are never the default for any application server.

        The ultimate goal is to have basic security working without the need of any kind of vendor specific configuration, deployment descriptors, or whatever. Currently users having such requirements often just completely ignore Java EE security and implement their own solution based on ServletFilters and objects in the HTTP session. When the app grows to a point that it does need the more advanced things that Java EE security offers, it's a pain to replace the homegrown system.

        That's why I think Java EE security (as a broad term), should also support the most simple and basic use case.

        Show
        arjan tijms added a comment - Ron, I've created a blog post about this very topic at: http://arjan-tijms.blogspot.com/2012/11/implementing-container-authentication.html There I tried to programmatically register an example SAM on 4 different servers in a portable way. One of the major problems I run into is with the appContext . The spec certainly provides a definition for this for the Servlet Profile, but it's still not clear what an application doing registration should provide here. Different application server implementations also seem to want different things here. Most want "server [application context path] ", but JBoss AS/EAP wants ["ServletRequest#getLocalName" [application context path] " here. The other major problem is that every application server still insists on the user providing a proprietary deployment descriptor, mostly for things like role mapping and the specification of a domain/realm. Above I asked that the roles returned by the proposed @AppLoginModule would be accepted without requiring to be mapped, but maybe we can go a step further and demand that the roles a JASPIC SAM puts into the JAAS Subject are useable without any required vendor specific mapping? I think the ideal is that without any vendor specific deployment descriptor present (like WEB-INF/sun-web.xml ), roles would be directly accepted. Then if there is such a deployment descriptor present, it can be used to optionally map some or all of the roles. Of course, it's at the vendor's discretion if further options are provided to e.g. completely turn off mapping or to mandate mapping for all roles, etc. This is fine, as long as those options are never the default for any application server. The ultimate goal is to have basic security working without the need of any kind of vendor specific configuration, deployment descriptors, or whatever. Currently users having such requirements often just completely ignore Java EE security and implement their own solution based on ServletFilters and objects in the HTTP session. When the app grows to a point that it does need the more advanced things that Java EE security offers, it's a pain to replace the homegrown system. That's why I think Java EE security (as a broad term), should also support the most simple and basic use case.
        Bill Shannon made changes -
        Field Original Value New Value
        Assignee Craig Perez [ crperez ]
        Hide
        arjan tijms added a comment -

        In the meantime I've prototyped a server auth module that approximately does what this issue asks at: http://code.google.com/p/omnisecurity/source/browse/src/org/omnifaces/security/jaspic/OmniServerAuthModule.java

        Slightly abbreviated this will allow an application to define a class like the following that handles both the initial name/password authentication and the "remember me":

        @SessionScoped
        public class KickoffAuthenticator implements UsernamePasswordAuthenticator, TokenAuthenticator {
        
            @EJB
            private UserService userService;
        
            private User user;
        
            @Override
            public void authenticate(String name, String password) {
                user = userService.getUserByCredentials(name, password);
            }
            
            @Override
            public void authenticate(String loginToken) {
                user = userService.getUserByLoginToken(loginToken);
            }
        
            @Override
            public String generateLoginToken() {
                return userService.generateLoginToken(user.getEmail());
            }
            
            @Override
            public void removeLoginToken() {
                userService.removeLoginToken(user.getEmail());
            }    
        
            @Override
            public String getUserName() {
                return user.getEmail();
            }
        
            @Override
            public List<String> getApplicationRoles() {
                return user.getRoles();
            }
        
            @Produces @Named("activeUser")
            public User getUser() {
                return user;
            }
        }
        

        In broad lines it follows the approach outlined by Ron above, but instead of j_username, j_password and a new optional parameter, it works with a programmatic HttpServletRequest#authenticate call that passes there parameters via request attributes. This approach works better for a JSF environment, but for JSP/HTML & Servlet apps an additional parameter next to j_username, j_password for the standard FORM based authentication would surely be needed as well.

        The SAM I prototyped assumes the user has a service available to retrieve the credentials from by name/password (as in the original proposal), as well as (optionally) a service that can do the same thing for "tokens" that are used for the "remember me".

        As of the major problems mentioned above, the appContext issue has been solved by Ron in JASPIC MR2 via JASPIC_SPEC-1.

        I've created JAVAEE_SPEC-20 to address the most problematic aspect of the required proprietary deployment descriptor.

        A very practical problem I encountered when prototyping the above solution is that CDI and the JNDI component namespaces (java:comp etc) are not setup when a JSR 196 SAM is called before a resource invocation. For this I've created JASPIC_SPEC-14.

        Show
        arjan tijms added a comment - In the meantime I've prototyped a server auth module that approximately does what this issue asks at: http://code.google.com/p/omnisecurity/source/browse/src/org/omnifaces/security/jaspic/OmniServerAuthModule.java Slightly abbreviated this will allow an application to define a class like the following that handles both the initial name/password authentication and the "remember me": @SessionScoped public class KickoffAuthenticator implements UsernamePasswordAuthenticator, TokenAuthenticator { @EJB private UserService userService; private User user; @Override public void authenticate( String name, String password) { user = userService.getUserByCredentials(name, password); } @Override public void authenticate( String loginToken) { user = userService.getUserByLoginToken(loginToken); } @Override public String generateLoginToken() { return userService.generateLoginToken(user.getEmail()); } @Override public void removeLoginToken() { userService.removeLoginToken(user.getEmail()); } @Override public String getUserName() { return user.getEmail(); } @Override public List< String > getApplicationRoles() { return user.getRoles(); } @Produces @Named( "activeUser" ) public User getUser() { return user; } } In broad lines it follows the approach outlined by Ron above, but instead of j_username, j_password and a new optional parameter, it works with a programmatic HttpServletRequest#authenticate call that passes there parameters via request attributes. This approach works better for a JSF environment, but for JSP/HTML & Servlet apps an additional parameter next to j_username, j_password for the standard FORM based authentication would surely be needed as well. The SAM I prototyped assumes the user has a service available to retrieve the credentials from by name/password (as in the original proposal), as well as (optionally) a service that can do the same thing for "tokens" that are used for the "remember me". As of the major problems mentioned above, the appContext issue has been solved by Ron in JASPIC MR2 via JASPIC_SPEC-1 . I've created JAVAEE_SPEC-20 to address the most problematic aspect of the required proprietary deployment descriptor. A very practical problem I encountered when prototyping the above solution is that CDI and the JNDI component namespaces (java:comp etc) are not setup when a JSR 196 SAM is called before a resource invocation. For this I've created JASPIC_SPEC-14 .
        alex.kosowski made changes -
        Assignee Craig Perez [ crperez ] alex.kosowski [ alex.kosowski ]
        Hide
        alex.kosowski added a comment -

        Hi Arjan,

        For EE 8, we are adding a new JSR focusing on making the Security API simpler and more portable.

        We are trying to determined whether we should standardize something like the simple authenticator UsernamePasswordAuthenticator you suggested. A question that came up was: Would a "typical" app developer using "simple" authentication really want to implement the authenticate method? It seems username/password or token authentication would be a service that an app developer would want the server to handle. How would an application domain model change the typical username/password verification?

        Is the real driver behind a simple authenticator API the ability to have an app manage its own users, groups, and roles dynamically? What if we added portable APIs for user, group, and role management? Would that eliminate the "typical" need for an app developer to implement an authenticator?

        That said, there are obviously special authentication mechanisms beyond username/password that an application may want portable access to. Perhaps improvements to JASPIC to fix the portability problems would be the way to address the broader authentication API.

        But, for the "simple" case, would adding the following APIs address the need for a simple authenticator?

        1. Standardized User Service API, with:

        • CRUD operations on Users
        • CRUD operations on Groups (of Users)
        • Ability to declare (annotation, DD) that a User Service instance is to be used by the server for authentication within the application
          2. Standardized Role (Authority) Service API, with
        • Ability to assign Users or Groups to roles
        • Conditional assignment, of Users or Groups to roles, based on Boolean EL expressions
        • Ability to declare one-to-one Group to Role mapping
        • Ability to declare (annotation, DD) that a Role Service instance is to be used by the server for authorization within the application

        No surprises here, as this is reflecting suggestions made in this and other JIRAs. But does the ability to manage users, groups, roles achieve the goal desired by implementing "KickoffAuthenticator"? It seems the value of this authenticator is in the KickoffAuthenticator.getApplicationRoles(). It seems KickoffAuthenticator.authenticate() would be boiler-plate code.

        A concern with requiring applications to implement UsernamePasswordAuthenticator.authenticate() is it provides an opportunity for insecure code and vulnerabilities.

        Please respond with your thoughts.

        Thanks,
        Alex

        Show
        alex.kosowski added a comment - Hi Arjan, For EE 8, we are adding a new JSR focusing on making the Security API simpler and more portable. We are trying to determined whether we should standardize something like the simple authenticator UsernamePasswordAuthenticator you suggested. A question that came up was: Would a "typical" app developer using "simple" authentication really want to implement the authenticate method? It seems username/password or token authentication would be a service that an app developer would want the server to handle. How would an application domain model change the typical username/password verification? Is the real driver behind a simple authenticator API the ability to have an app manage its own users, groups, and roles dynamically? What if we added portable APIs for user, group, and role management? Would that eliminate the "typical" need for an app developer to implement an authenticator? That said, there are obviously special authentication mechanisms beyond username/password that an application may want portable access to. Perhaps improvements to JASPIC to fix the portability problems would be the way to address the broader authentication API. But, for the "simple" case, would adding the following APIs address the need for a simple authenticator? 1. Standardized User Service API, with: CRUD operations on Users CRUD operations on Groups (of Users) Ability to declare (annotation, DD) that a User Service instance is to be used by the server for authentication within the application 2. Standardized Role (Authority) Service API, with Ability to assign Users or Groups to roles Conditional assignment, of Users or Groups to roles, based on Boolean EL expressions Ability to declare one-to-one Group to Role mapping Ability to declare (annotation, DD) that a Role Service instance is to be used by the server for authorization within the application No surprises here, as this is reflecting suggestions made in this and other JIRAs. But does the ability to manage users, groups, roles achieve the goal desired by implementing "KickoffAuthenticator"? It seems the value of this authenticator is in the KickoffAuthenticator.getApplicationRoles(). It seems KickoffAuthenticator.authenticate() would be boiler-plate code. A concern with requiring applications to implement UsernamePasswordAuthenticator.authenticate() is it provides an opportunity for insecure code and vulnerabilities. Please respond with your thoughts. Thanks, Alex
        Hide
        arjan tijms added a comment -

        For EE 8, we are adding a new JSR focusing on making the Security API simpler and more portable.

        This by itself is really good news

        Would a "typical" app developer using "simple" authentication really want to implement the authenticate method?

        I think the answer to this would be "yes" when looking at how often I've seen developers do this. Because Java EE doesn't offer anything to help them with this, I'd mostly see them avoiding Java EE security completely and just implementing something using Servlet Filters.

        It seems username/password or token authentication would be a service that an app developer would want the server to handle.

        The problem with this is that those usernames and passwords for simple applications are not in the server, and that the way the server handles this is different for each and every server. This makes it incredibly hard to explain how one should do this task in "Java EE". Instead, one has to explain that one part is done using Java EE code, and the other part is done using JBoss code. But then the user happens to be using Hitachi Cosminexus, and who knows how proprietary login modules are configured for Hitachi Cosminexus?

        There's a similar problem with doing cloud deployments, where often everything has to come from the war (or ear) and there's no option to configure anything at the side of the server.

        How would an application domain model change the typical username/password verification?

        An application often has a number of domain entities. E.g. for an online advertising application there could be an Advertisement which is owned by an Advertiser. Such an Advertisement can be put on a Website owned by a Publisher.

        In such application, Advertiser is a user who can register with the system and then login. Same goes for Publisher.

        It's thus an impediment if authenticating can only be done via users that are somehow magically present inside some store managed by the application server, since those users are primarily entities that exist within the application. They register with the application via a webpage that's integrated with the main application.

        Application server vendors have long recognized this particular use case, since many of them come with "DatabaseLoginModules". This often boils down to pointing such login module with vendor specific configuration to the same database that happens to store the above mentioned users, and then fabricate a (SQL) query via which a username and (hashed) password can be extracted from the table(s) that store those users.

        This often means that the data source has to be defined twice, and there has to be separate logic, often even separate from the application code, that has to have internal knowledge of how the user is mapped to the database tables. If the application changes the user layout, this query will break.

        That said, there are obviously special authentication mechanisms beyond username/password that an application may want portable access to.

        Absolutely, hence the idea to have a couple of interfaces for a small and finite number of well known use cases. If the application's need can not be met by using once of those, then there's always full blown JASPIC which by virtue of its immensely generic API could theoretically do "anything".

        Perhaps improvements to JASPIC to fix the portability problems would be the way to address the broader authentication API.

        For sure, and maybe even up to the point that having the simplified authenticator might be less needed.

        Basically, having a SAM registrable via a simple annotation instead of having to go through 4 factories, having CDI and Java EE component namespaces available in it, and providing a convenience base class and methods (see JASPIC_SPEC-17 , HttpMsgContext and HttpServerAuthModule) could come a long way.

        • CRUD operations on Users
        • CRUD operations on Groups (of Users)

        If you mean low level CRUD operations, then I'm not so sure about this. There's JPA and EJB for that after all. If you're talking about a specific API for CRUD operations on whatever "user repository" that is used by a SAM or LoginModule, then this may be an interesting feature to look at. However, I think not all repositories are able to support CRUD operations easily. In-memory, .properties, database and LDAP probably can, but OAuth (Facebook, Twitter etc) probably can't.

        I'm afraid it also still wouldn't solve the case where the user that's logging in is primarily an application entity. If I understand what you mean with "CRUD operations" correctly, then an application would always have to call two APIs. E.g. when creating a user it would have to call both JPA and this new API, just so the authentication system also knows about the new user. In such case transactions are critical, but this will probably make the entire thing way more complicated, both for implementors of the spec as for users of the spec.

        Ability to declare (annotation, DD) that a User Service instance is to be used by the server for authentication within the application

        What would the interface of such User Service look like? Wouldn't this basically be the same as the interface proposed here and in JAVAEE_SPEC-25? E.g. a service where you call a method and pass in a username and password, and get back a "user" represented by a name and set of roles. Essentially it's a simpler and more modern version of the JAAS LoginModule.

        Ability to assign Users or Groups to roles

        This is like the CRUD operations on Users, right? There may be some merit here for some applications and some "repositories", but I don't think this will solve the general case. I think the general case is that the application has already stored users and role associations in some format using whatever existing API (JDBC, JPA, etc). In that case it doesn't need a new API to store anything, but just a way to return a name + roles to Java EE.

        What I think you are proposing (correct me if I'm wrong) is another persistence API (next to JDBC and JPA among others) specifically tailored for storing Users, Groups and associations between these two. While it could indeed be handy to have a universal API for these things for say LDAP when there's an LDAP login module configured, or to an XML file when there's some XML file based login module configured, I think it's solving a different (and rather complex) problem.

        A concern with requiring applications to implement UsernamePasswordAuthenticator.authenticate() is it provides an opportunity for insecure code and vulnerabilities.

        But isn't that the same opportunity that's there now when applications implement a full blown JASPIC SAM? And simple applications will now most of the times implement something much worse in a Servlet Filter.

        The idea is that simple applications could start with implementing something like UsernamePasswordAuthenticator.authenticate(), and could then later on fairly transparently swap it out for a more secure implementation (of which the Java EE standard could provide a number of default ones like proposed by JAVAEE_SPEC-28).

        All in all I think it might be a good idea to get all the separate ideas together once this new security JSR has really started in a kind of big picture issue, e.g.

        • JASPIC SAM as the clear overall authentication module that takes care of the user interaction/message dialog (among others JAVAEE_SPEC-22)
        • Existing authentication methods implemented as JASPIC SAMs (see also JAVAEE_SPEC-37)
        • Several simplifications / easy of use improvements for SAMs (among others JASPIC_SPEC-17)
        • Simplified interface for just bare authentication that a standard SAM can call in addition to the existing JAAS LoginModule (this issue and JAVAEE_SPEC-25, see also JASPIC bridge profile)
        • Several default implementations of this simplified interface for the most common cases (JAVAEE_SPEC-28)
        • Standardized group to role mapping (JAVAEE_SPEC-20)
        Show
        arjan tijms added a comment - For EE 8, we are adding a new JSR focusing on making the Security API simpler and more portable. This by itself is really good news Would a "typical" app developer using "simple" authentication really want to implement the authenticate method? I think the answer to this would be "yes" when looking at how often I've seen developers do this. Because Java EE doesn't offer anything to help them with this, I'd mostly see them avoiding Java EE security completely and just implementing something using Servlet Filters. It seems username/password or token authentication would be a service that an app developer would want the server to handle. The problem with this is that those usernames and passwords for simple applications are not in the server, and that the way the server handles this is different for each and every server. This makes it incredibly hard to explain how one should do this task in "Java EE". Instead, one has to explain that one part is done using Java EE code, and the other part is done using JBoss code. But then the user happens to be using Hitachi Cosminexus, and who knows how proprietary login modules are configured for Hitachi Cosminexus? There's a similar problem with doing cloud deployments, where often everything has to come from the war (or ear) and there's no option to configure anything at the side of the server. How would an application domain model change the typical username/password verification? An application often has a number of domain entities. E.g. for an online advertising application there could be an Advertisement which is owned by an Advertiser. Such an Advertisement can be put on a Website owned by a Publisher. In such application, Advertiser is a user who can register with the system and then login. Same goes for Publisher. It's thus an impediment if authenticating can only be done via users that are somehow magically present inside some store managed by the application server, since those users are primarily entities that exist within the application. They register with the application via a webpage that's integrated with the main application. Application server vendors have long recognized this particular use case, since many of them come with "DatabaseLoginModules". This often boils down to pointing such login module with vendor specific configuration to the same database that happens to store the above mentioned users, and then fabricate a (SQL) query via which a username and (hashed) password can be extracted from the table(s) that store those users. This often means that the data source has to be defined twice, and there has to be separate logic, often even separate from the application code, that has to have internal knowledge of how the user is mapped to the database tables. If the application changes the user layout, this query will break. That said, there are obviously special authentication mechanisms beyond username/password that an application may want portable access to. Absolutely, hence the idea to have a couple of interfaces for a small and finite number of well known use cases. If the application's need can not be met by using once of those, then there's always full blown JASPIC which by virtue of its immensely generic API could theoretically do "anything". Perhaps improvements to JASPIC to fix the portability problems would be the way to address the broader authentication API. For sure, and maybe even up to the point that having the simplified authenticator might be less needed. Basically, having a SAM registrable via a simple annotation instead of having to go through 4 factories , having CDI and Java EE component namespaces available in it, and providing a convenience base class and methods (see JASPIC_SPEC-17 , HttpMsgContext and HttpServerAuthModule ) could come a long way. CRUD operations on Users CRUD operations on Groups (of Users) If you mean low level CRUD operations, then I'm not so sure about this. There's JPA and EJB for that after all. If you're talking about a specific API for CRUD operations on whatever "user repository" that is used by a SAM or LoginModule, then this may be an interesting feature to look at. However, I think not all repositories are able to support CRUD operations easily. In-memory, .properties, database and LDAP probably can, but OAuth (Facebook, Twitter etc) probably can't. I'm afraid it also still wouldn't solve the case where the user that's logging in is primarily an application entity. If I understand what you mean with "CRUD operations" correctly, then an application would always have to call two APIs. E.g. when creating a user it would have to call both JPA and this new API, just so the authentication system also knows about the new user. In such case transactions are critical, but this will probably make the entire thing way more complicated, both for implementors of the spec as for users of the spec. Ability to declare (annotation, DD) that a User Service instance is to be used by the server for authentication within the application What would the interface of such User Service look like? Wouldn't this basically be the same as the interface proposed here and in JAVAEE_SPEC-25 ? E.g. a service where you call a method and pass in a username and password, and get back a "user" represented by a name and set of roles. Essentially it's a simpler and more modern version of the JAAS LoginModule. Ability to assign Users or Groups to roles This is like the CRUD operations on Users, right? There may be some merit here for some applications and some "repositories", but I don't think this will solve the general case. I think the general case is that the application has already stored users and role associations in some format using whatever existing API (JDBC, JPA, etc). In that case it doesn't need a new API to store anything, but just a way to return a name + roles to Java EE. What I think you are proposing (correct me if I'm wrong) is another persistence API (next to JDBC and JPA among others) specifically tailored for storing Users, Groups and associations between these two. While it could indeed be handy to have a universal API for these things for say LDAP when there's an LDAP login module configured, or to an XML file when there's some XML file based login module configured, I think it's solving a different (and rather complex) problem. A concern with requiring applications to implement UsernamePasswordAuthenticator.authenticate() is it provides an opportunity for insecure code and vulnerabilities. But isn't that the same opportunity that's there now when applications implement a full blown JASPIC SAM? And simple applications will now most of the times implement something much worse in a Servlet Filter. The idea is that simple applications could start with implementing something like UsernamePasswordAuthenticator.authenticate() , and could then later on fairly transparently swap it out for a more secure implementation (of which the Java EE standard could provide a number of default ones like proposed by JAVAEE_SPEC-28 ). All in all I think it might be a good idea to get all the separate ideas together once this new security JSR has really started in a kind of big picture issue, e.g. JASPIC SAM as the clear overall authentication module that takes care of the user interaction/message dialog (among others JAVAEE_SPEC-22 ) Existing authentication methods implemented as JASPIC SAMs (see also JAVAEE_SPEC-37 ) Several simplifications / easy of use improvements for SAMs (among others JASPIC_SPEC-17 ) Simplified interface for just bare authentication that a standard SAM can call in addition to the existing JAAS LoginModule (this issue and JAVAEE_SPEC-25 , see also JASPIC bridge profile) Several default implementations of this simplified interface for the most common cases ( JAVAEE_SPEC-28 ) Standardized group to role mapping ( JAVAEE_SPEC-20 )
        Hide
        alex.kosowski added a comment -

        Hi Arjan,

        Thanks for your prompt response.

        Let me explain the UserService and RoleService a bit.

        UserService is an application-scoped service for an application to manage its own users. User data would be supplied by a UserSource, which may point to an application-supplied persistence store or the server user store. This user collection may be completely independent from the server users, or may be the same, depending on configuration. The components may look something like this:

        UserInfo <-> UserService <-> UserSource <-> {some user source}
        

        UserInfo properties:
        + Username
        + Password
        + AccountExpired
        + AccountLocked
        + PasswordExpired
        + Enabled
        + Attributes

        UserService operations:
        + UserInfo:loadUserByUsername(username)
        + changePassword
        + createUser
        + deleteUser
        + updateUser
        + userExists
        + createGroup
        + addUserToGroup
        + removeUserFromGroup
        + isUserInGroup

        Standardized UserSource types:
        LdapUserSource: Points to an application supplied LDAP server
        ServerUserSource: Bridges to the server users
        Jsr351UserSource: Bridges to the JSR 351 Identity API
        DataSourceUserSource: Points to an application supplied DataSource
        MemoryUserSource: Code-embedded users, or read from file (JSON, XML, or Properties)
        CustomUserSource: Application definable

        Usage:

        @LdapUserSourceDefinition(name=“java:app/prodUserSource”, ldapUrl=“ldap://blah”, ldapUser=“ElDap”, ldapPassword=“#{ALIAS_LDAP}”)
        
        public class MyAuthenticator {	
          @Resource(lookup=“java:app/prodUserSource”)	
          private UserService userService;	
          private boolean isAccountEnabled(String username) {		
            return userService.loadUserByUsername(username).isEnabled();	
          } …
        }
        

        The UserSource would be defined as a resource. The UserService would be a persistence API for storing Users, Groups, and associations, however the underlying repository may be application supplied. The users supplied by the UserService would be local to the application, however multiple applications could access the same user repository to share users.

        We could have a read-only and read-write version of UserService, or otherwise determine the capability of a UserService. That is, some repositories are read-only. Also, we may split out the Password into a separate service/repository.

        The UserSourceDefinition annotation would be the default, overridable via standard deployment descriptor, and programmatically via standard APIs.

        =======

        RoleService would have a similar architecture as the UserService. RoleService would also be a resource, and defines role mappings local to an application, but may be configured to use the server role mapper. The components may look something like this:

        RoleService <-> RoleMapper <-> {some role mapper}
        

        RoleService operations:
        + grantRoleToUser(username, role)
        + revokeRoleFromUser(username, role)
        + hasRoleForUser(username, role, includeGroups)
        + getRolesForUser(username, includeGroups)
        + getUsersWithRole(role, includeGroups)
        + grantRoleToGroup(group, role)
        + revokeRoleFromGroup(group, role)
        + hasRoleForGroup(group, role)
        + getRolesForGroup(group)
        + getGroupsWithRole(role)

        Standardized RoleMapper types:
        LdapRoleMapper: Points to an application supplied LDAP server
        ServerRoleMapper: Bridges to the server role mapper
        MemoryRoleMapper: Code-embedded role mappings, or read from file (JSON, XML, or Properties)
        DataSourceRoleMapper: Points to an application supplied DataSource
        CustomRoleMapper: Application definable
        GroupIsRoleMapper: Role is one-to-one mapping to user group

        Usage:

        @MemoryRoleMapperDefinition(
          name=“java:app/devRoleMapper”,	
          users={
            @RoleMap(user=“foo”,roles=“admin”),		
            @RoleMap(group=“admin”,roles={“admin”,”staff”})
          } 
        )
        public class MyServlet {
          @Resource(lookup=“java:app/devRoleMapper”)
          private RoleService roleService;
          private List<String> getRoles(String username) {
            return roleService.getRolesForUser(username,true);
          }
          …
        }
        

        The RoleMapperDefinition annotation would be the default, overridable via standard deployment descriptor, and programmatically via standard APIs.

        =======

        Finally, the application server discovers which UserSource and RoleMapper to use for an application by processing the Authenticator annotation:

        @Authenticator(userSourceName=“java:app/prodUserSource”,roleMapperName=“java:app/OneToOneRoleMapper”)
        

        The Authenticator annotation would apply to the application scope, be overridable via standard deployment descriptor, and be overridable programmatically via standard APIs.

        =======

        The UserService and RoleService attempt to provide simple and portable user and role management to applications.

        Regarding:

        It's thus an impediment if authenticating can only be done via users that are somehow magically present inside some store managed by the application server, since those users are primarily entities that exist within the application.

        Applications would be able to bind their own user repositories into a server's authentication process for that application. The "simple" authenticator API could just be the @Authenticator annotation. More advanced/custom authentication mechanisms could use JASPIC, which as you mentioned, needs some work.

        Regarding:

        I think the general case is that the application has already stored users and role associations in some format using whatever existing API (JDBC, JPA, etc). In that case it doesn't need a new API to store anything, but just a way to return a name + roles to Java EE.

        The UserService, Role Service, and binding Authenticator could be a way to do that.

        Please respond with your thoughts.

        Thanks,
        Alex

        Show
        alex.kosowski added a comment - Hi Arjan, Thanks for your prompt response. Let me explain the UserService and RoleService a bit. UserService is an application-scoped service for an application to manage its own users. User data would be supplied by a UserSource, which may point to an application-supplied persistence store or the server user store. This user collection may be completely independent from the server users, or may be the same, depending on configuration. The components may look something like this: UserInfo <-> UserService <-> UserSource <-> {some user source} UserInfo properties: + Username + Password + AccountExpired + AccountLocked + PasswordExpired + Enabled + Attributes UserService operations: + UserInfo:loadUserByUsername(username) + changePassword + createUser + deleteUser + updateUser + userExists + createGroup + addUserToGroup + removeUserFromGroup + isUserInGroup Standardized UserSource types: LdapUserSource: Points to an application supplied LDAP server ServerUserSource: Bridges to the server users Jsr351UserSource: Bridges to the JSR 351 Identity API DataSourceUserSource: Points to an application supplied DataSource MemoryUserSource: Code-embedded users, or read from file (JSON, XML, or Properties) CustomUserSource: Application definable Usage: @LdapUserSourceDefinition( name=“java:app/prodUserSource”, ldapUrl=“ldap: //blah”, ldapUser=“ElDap”, ldapPassword=“#{ALIAS_LDAP}” ) public class MyAuthenticator { @Resource(lookup=“java:app/prodUserSource”) private UserService userService; private boolean isAccountEnabled( String username) { return userService.loadUserByUsername(username).isEnabled(); } … } The UserSource would be defined as a resource. The UserService would be a persistence API for storing Users, Groups, and associations, however the underlying repository may be application supplied. The users supplied by the UserService would be local to the application, however multiple applications could access the same user repository to share users. We could have a read-only and read-write version of UserService, or otherwise determine the capability of a UserService. That is, some repositories are read-only. Also, we may split out the Password into a separate service/repository. The UserSourceDefinition annotation would be the default, overridable via standard deployment descriptor, and programmatically via standard APIs. ======= RoleService would have a similar architecture as the UserService. RoleService would also be a resource, and defines role mappings local to an application, but may be configured to use the server role mapper. The components may look something like this: RoleService <-> RoleMapper <-> {some role mapper} RoleService operations: + grantRoleToUser(username, role) + revokeRoleFromUser(username, role) + hasRoleForUser(username, role, includeGroups) + getRolesForUser(username, includeGroups) + getUsersWithRole(role, includeGroups) + grantRoleToGroup(group, role) + revokeRoleFromGroup(group, role) + hasRoleForGroup(group, role) + getRolesForGroup(group) + getGroupsWithRole(role) Standardized RoleMapper types: LdapRoleMapper: Points to an application supplied LDAP server ServerRoleMapper: Bridges to the server role mapper MemoryRoleMapper: Code-embedded role mappings, or read from file (JSON, XML, or Properties) DataSourceRoleMapper: Points to an application supplied DataSource CustomRoleMapper: Application definable GroupIsRoleMapper: Role is one-to-one mapping to user group Usage: @MemoryRoleMapperDefinition( name=“java:app/devRoleMapper”, users={ @RoleMap(user=“foo”,roles=“admin”), @RoleMap(group=“admin”,roles={“admin”,”staff”}) } ) public class MyServlet { @Resource(lookup=“java:app/devRoleMapper”) private RoleService roleService; private List< String > getRoles( String username) { return roleService.getRolesForUser(username, true ); } … } The RoleMapperDefinition annotation would be the default, overridable via standard deployment descriptor, and programmatically via standard APIs. ======= Finally, the application server discovers which UserSource and RoleMapper to use for an application by processing the Authenticator annotation: @Authenticator(userSourceName=“java:app/prodUserSource”,roleMapperName=“java:app/OneToOneRoleMapper” ) The Authenticator annotation would apply to the application scope, be overridable via standard deployment descriptor, and be overridable programmatically via standard APIs. ======= The UserService and RoleService attempt to provide simple and portable user and role management to applications. Regarding: It's thus an impediment if authenticating can only be done via users that are somehow magically present inside some store managed by the application server, since those users are primarily entities that exist within the application. Applications would be able to bind their own user repositories into a server's authentication process for that application. The "simple" authenticator API could just be the @Authenticator annotation. More advanced/custom authentication mechanisms could use JASPIC, which as you mentioned, needs some work. Regarding: I think the general case is that the application has already stored users and role associations in some format using whatever existing API (JDBC, JPA, etc). In that case it doesn't need a new API to store anything, but just a way to return a name + roles to Java EE. The UserService, Role Service, and binding Authenticator could be a way to do that. Please respond with your thoughts. Thanks, Alex
        Hide
        arjan tijms added a comment -

        Thanks a lot for the thorough explanation. There are a lot of interesting ideas there.

        I do think it's especially important to establish some terminology and to take a look at how all individual ideas come together as a whole.

        Specifically there are two concepts that often come up and actually exist, but haven't got real clear distinguishing names:

        • The (user) interaction method via which credentials are obtained (form, basic, etc)
        • The store where users/callers and optionally the group/role data resides.

        The first item is what's more or less called "auth-method" in the Servlet spec, and "auth module" in the JASPIC spec. The second item is very indirectly called "realm" in the Servlet spec, but you'll often see the terms "repository" and "store" as well. JASPIC (optionally) delegates this functionality to a JAAS "LoginModule". JAVAEE_SPEC-28 calls these "security providers".

        The reason I'm bringing this up here is that if I understood correctly this second item corresponds to what you call a "UserSource" and a "UserService" (and in the running text refer to using "repository")

        A second issue, directly related to the above is that I'm wondering what the difference is between a UserSource and a UserService. In the example code they seem to be the same thing. There, a variable of type UserService is injected with a UserSource:

        @Resource(lookup=“java:app/prodUserSource”)
        private UserService userService;
        

        One thing I'm missing in the examples and API is a way to retrieve the groups/roles. This information is not in your UserInfo and the LdapUserSourceDefinition doesn't show any attribute used to hold the groups/roles query.

        In practice, there are often two queries defined for repositories. Eg for both SQL/DB and LDAP repositories you define one query to obtain just the user and another one to obtain the roles associated with a user. Some repositories, like a file based one, have their own internal format to store both users and their roles and no separate queries are needed. Yet other repositories, such as the increasingly popular OAuth based ones (Facebook, Twitter, ...) don't return roles at all (the app typically stores roles locally instead).

        As for the RoleMapper examples, here too I wonder what the difference is between the RoleMapper and RoleService; they seem to be the same thing as a RoleService variable is injected with a RoleMapper.

        I also wonder if LDAP can actually be used for (local) role mapping. It's sure used for role retrieval, but is it really used for local application role mapping? I don't think I've ever seen that.

        Finally, we may consider if the terms "group" and "role" are really needed. As you of course know, there's a third level of role mapping possible between the global application level roles and the roles of a single Java EE component (EJB bean or web module). There both source and target keeps using the term "role". I recognise that "group to role mapping" is an existing and reasonably well known term, but going forward with simplifying security it might be worth it to reconsider if those two terms are really needed.

        The problem I'm seeing is that in practice people dream up all kinds of fancy semantics related to the terms "group" and "role", thinking group is really like a group in normal English, while a role is more akin to a right, and what have you. Never ever have I seen anyone who intuitively understood that "group" is the "thing" returned by the auth module/login module and "role" is the "thing" after the mapping as required by some servers.

        With standardised role mapping one thing in favour of keeping the group / role terms though is that people could now start using it as the names intuitively imply; coarse grained / fine grained permissions.

        Well, just something to think about

        As for the authenticator example as given below:

        @Authenticator(userSourceName=“java:app/prodUserSource”,roleMapperName=“java:app/OneToOneRoleMapper” )
        

        I think there are a few things to remark here.

        Given the above mentioned distinction between the auth "method" and the "repository", I think the first one should be put here too. The method is after all not an alternative to the repository but a higher layer in a way; the method may decide not to call into a repository, but a repository always needs to be called by a method.

        A small cosmetic thing is that in JNDI it's a kind of de facto standard that "name" is an overloaded mess that both sets a name when a resource is defined and injects a name into the ENC (if any) when referenced. For referencing an existing name "lookup" seems to be more common.

        Another thing is that while for the example OneToOneRoleMapper is great, in practice I think this could better be the default for this kind of ease of use facility.

        Finally, I wonder if the API for this annotation would not be better off using CDI names and/or qualifyers instead of or in addition to JNDI.

        Anyway, keeping JNDI and the default role mapper it would then be something like this:

        @Authenticator(
        authMethodLookup="java:app/prodAuthMethod",
        userSourceLookup=“java:app/prodUserSource”,
        roleMapperLookup=“java:app/OneToOneRoleMapper” )
        

        In this example java:app/prodAuthMethod would refer to a configuration of a JASPIC module or one of the standard auth methods (like FORM). Bonus points for if there would not be a difference between those two and FORM was just a standardised JASPIC module.

        We now have the method which uses eg a form to get a username and password from the actual user, we have a userSource that retrieves the user (and presumably the roles) and we tell the server to use the roles directly.

        There's now just one thing missing (apart from the role retrieval mentioned above); what code is responsible for comparing the submitted password against the actual password? This has to be custom code too, as in general the server cannot assume any specific format or hash method/salt etc of the password (or any other type of credential).

        Show
        arjan tijms added a comment - Thanks a lot for the thorough explanation. There are a lot of interesting ideas there. I do think it's especially important to establish some terminology and to take a look at how all individual ideas come together as a whole. Specifically there are two concepts that often come up and actually exist, but haven't got real clear distinguishing names: The (user) interaction method via which credentials are obtained (form, basic, etc) The store where users/callers and optionally the group/role data resides. The first item is what's more or less called "auth-method" in the Servlet spec, and "auth module" in the JASPIC spec. The second item is very indirectly called "realm" in the Servlet spec, but you'll often see the terms "repository" and "store" as well. JASPIC (optionally) delegates this functionality to a JAAS "LoginModule". JAVAEE_SPEC-28 calls these "security providers". The reason I'm bringing this up here is that if I understood correctly this second item corresponds to what you call a "UserSource" and a "UserService" (and in the running text refer to using "repository") A second issue, directly related to the above is that I'm wondering what the difference is between a UserSource and a UserService. In the example code they seem to be the same thing. There, a variable of type UserService is injected with a UserSource: @Resource(lookup=“java:app/prodUserSource”) private UserService userService; One thing I'm missing in the examples and API is a way to retrieve the groups/roles. This information is not in your UserInfo and the LdapUserSourceDefinition doesn't show any attribute used to hold the groups/roles query. In practice, there are often two queries defined for repositories. Eg for both SQL/DB and LDAP repositories you define one query to obtain just the user and another one to obtain the roles associated with a user. Some repositories, like a file based one, have their own internal format to store both users and their roles and no separate queries are needed. Yet other repositories, such as the increasingly popular OAuth based ones (Facebook, Twitter, ...) don't return roles at all (the app typically stores roles locally instead). As for the RoleMapper examples, here too I wonder what the difference is between the RoleMapper and RoleService; they seem to be the same thing as a RoleService variable is injected with a RoleMapper. I also wonder if LDAP can actually be used for (local) role mapping. It's sure used for role retrieval, but is it really used for local application role mapping? I don't think I've ever seen that. Finally, we may consider if the terms "group" and "role" are really needed. As you of course know, there's a third level of role mapping possible between the global application level roles and the roles of a single Java EE component (EJB bean or web module). There both source and target keeps using the term "role". I recognise that "group to role mapping" is an existing and reasonably well known term, but going forward with simplifying security it might be worth it to reconsider if those two terms are really needed. The problem I'm seeing is that in practice people dream up all kinds of fancy semantics related to the terms "group" and "role", thinking group is really like a group in normal English, while a role is more akin to a right, and what have you. Never ever have I seen anyone who intuitively understood that "group" is the "thing" returned by the auth module/login module and "role" is the "thing" after the mapping as required by some servers. With standardised role mapping one thing in favour of keeping the group / role terms though is that people could now start using it as the names intuitively imply; coarse grained / fine grained permissions. Well, just something to think about As for the authenticator example as given below: @Authenticator(userSourceName=“java:app/prodUserSource”,roleMapperName=“java:app/OneToOneRoleMapper” ) I think there are a few things to remark here. Given the above mentioned distinction between the auth "method" and the "repository", I think the first one should be put here too. The method is after all not an alternative to the repository but a higher layer in a way; the method may decide not to call into a repository, but a repository always needs to be called by a method. A small cosmetic thing is that in JNDI it's a kind of de facto standard that "name" is an overloaded mess that both sets a name when a resource is defined and injects a name into the ENC (if any) when referenced. For referencing an existing name "lookup" seems to be more common. Another thing is that while for the example OneToOneRoleMapper is great, in practice I think this could better be the default for this kind of ease of use facility. Finally, I wonder if the API for this annotation would not be better off using CDI names and/or qualifyers instead of or in addition to JNDI. Anyway, keeping JNDI and the default role mapper it would then be something like this: @Authenticator( authMethodLookup= "java:app/prodAuthMethod" , userSourceLookup=“java:app/prodUserSource”, roleMapperLookup=“java:app/OneToOneRoleMapper” ) In this example java:app/prodAuthMethod would refer to a configuration of a JASPIC module or one of the standard auth methods (like FORM). Bonus points for if there would not be a difference between those two and FORM was just a standardised JASPIC module. We now have the method which uses eg a form to get a username and password from the actual user, we have a userSource that retrieves the user (and presumably the roles) and we tell the server to use the roles directly. There's now just one thing missing (apart from the role retrieval mentioned above); what code is responsible for comparing the submitted password against the actual password? This has to be custom code too, as in general the server cannot assume any specific format or hash method/salt etc of the password (or any other type of credential).
        Hide
        alex.kosowski added a comment -

        I'm wondering what the difference is between a UserSource and a UserService

        The UserSource would be an adapter between the repository and the UserService. We would standardize UserSource implementations for various repository types (LDAP, DataSource, etc). The UserService would provide user operations, delegating repository access to the UserSource. I suppose we could simplify and merge UserSource and UserService, perhaps standardize some service helper methods.

        One thing I'm missing in the examples and API is a way to retrieve the groups/roles.

        Sorry, missed that in the reply. Groups are just groups of users, with no authorization semantics without RoleService. To get groups from UserService:
        boolean isUserInGroup(String username, String group);
        List<String> getUserGroups(String username);

        Roles provide authority. To get role from RoleService:
        boolean hasRoleForUser(String username, String role, boolean includeGroups);
        List<String> getRolesForUser(String username, boolean includeGroups);
        List<String> getUsersWithRole(String role, boolean includeGroups);
        boolean hasRoleForGroup(String group, String role);
        List<String> getRolesForGroup(String group);
        List<String> getGroupsWithRole(String role);

        Note that the GroupIsRoleMapper would represent groups as roles.

        there are often two queries defined for repositories

        I would expect the standardized LDAPUserSource, DataSourceUserSource, etc, would be configurable for apps to declare queries for specific required operations.

        Yet other repositories, such as the increasingly popular OAuth based ones (Facebook, Twitter, ...) don't return roles at all (the app typically stores roles locally instead).

        UserService would be meant for applications to manage users. For OpenID Connect user repositories, I would expect a JASPIC SAM to cover that.

        I wonder what the difference is between the RoleMapper and RoleService

        Yup, perhaps we should simplify this terminology and just have RoleService implementations.

        I also wonder if LDAP can actually be used for (local) role mapping. It's sure used for role retrieval, but is it really used for local application role mapping? I don't think I've ever seen that.

        I was not sure if that was actually used, although I think it is possible. No need to standardize an uncommon use case.

        One idea we were considering was having role mapping be rule based. We could have the role mapping rules be based on EL, incorporating managed beans. We could store the rules inline or externally in file or LDAP. The rules would be evaluated before authorization decisions.

        I recognise that "group to role mapping" is an existing and reasonably well known term, but going forward with simplifying security it might be worth it to reconsider if those two terms are really needed.

        Group to role mapping arguably is needed for deployments where the enterprise is using applications developed by a third party. The mapping allows application authorization roles to be assigned from enterprise users. The one to one role mapper would provide a simplification for applications not requiring the mapping. I am not sure how to get away from role mapping and still accommodate the common Java EE security use cases.

        Another thing is that while for the example OneToOneRoleMapper is great, in practice I think this could better be the default for this kind of ease of use facility.

        Agreed

        I wonder if the API for this annotation would not be better off using CDI names and/or qualifyers instead of or in addition to JNDI.

        I think using JNDI is the current standard for referring to resources. Although CDI seems like the "hammer for everyone's nail", I could not find any standards for using CDI names to refer to resources.

        @Authenticator(
        authMethodLookup="java:app/prodAuthMethod",
        userSourceLookup=“java:app/prodUserSource”,
        roleMapperLookup=“java:app/OneToOneRoleMapper” )

        I agree with this. authMethodLookup would make sense if JASPIC were updated to be configurable with standardized SAMs. The absence of authMethodLookup infers the currently determined authmethod (e.g., via web.xml) would use the specified UserSource and RoleMapper for authentication within the application.

        what code is responsible for comparing the submitted password against the actual password? This has to be custom code too, as in general the server cannot assume any specific format or hash method/salt etc of the password (or any other type of credential).

        Since the UserService internally hashes/encrypts the password, I think the UserService should encapsulate that decision. For example, we could remove the Password attribute from UserInfo and add a UserService operation which would encapsulate the password check, like:
        boolean isValid( username, password )

        That said, we are also considering separating Password into a separate service: PasswordService or CredentialService. This would facilitate having a separate, more secure credential repository.

        Show
        alex.kosowski added a comment - I'm wondering what the difference is between a UserSource and a UserService The UserSource would be an adapter between the repository and the UserService. We would standardize UserSource implementations for various repository types (LDAP, DataSource, etc). The UserService would provide user operations, delegating repository access to the UserSource. I suppose we could simplify and merge UserSource and UserService, perhaps standardize some service helper methods. One thing I'm missing in the examples and API is a way to retrieve the groups/roles. Sorry, missed that in the reply. Groups are just groups of users, with no authorization semantics without RoleService. To get groups from UserService: boolean isUserInGroup(String username, String group); List<String> getUserGroups(String username); Roles provide authority. To get role from RoleService: boolean hasRoleForUser(String username, String role, boolean includeGroups); List<String> getRolesForUser(String username, boolean includeGroups); List<String> getUsersWithRole(String role, boolean includeGroups); boolean hasRoleForGroup(String group, String role); List<String> getRolesForGroup(String group); List<String> getGroupsWithRole(String role); Note that the GroupIsRoleMapper would represent groups as roles. there are often two queries defined for repositories I would expect the standardized LDAPUserSource, DataSourceUserSource, etc, would be configurable for apps to declare queries for specific required operations. Yet other repositories, such as the increasingly popular OAuth based ones (Facebook, Twitter, ...) don't return roles at all (the app typically stores roles locally instead). UserService would be meant for applications to manage users. For OpenID Connect user repositories, I would expect a JASPIC SAM to cover that. I wonder what the difference is between the RoleMapper and RoleService Yup, perhaps we should simplify this terminology and just have RoleService implementations. I also wonder if LDAP can actually be used for (local) role mapping. It's sure used for role retrieval, but is it really used for local application role mapping? I don't think I've ever seen that. I was not sure if that was actually used, although I think it is possible. No need to standardize an uncommon use case. One idea we were considering was having role mapping be rule based. We could have the role mapping rules be based on EL, incorporating managed beans. We could store the rules inline or externally in file or LDAP. The rules would be evaluated before authorization decisions. I recognise that "group to role mapping" is an existing and reasonably well known term, but going forward with simplifying security it might be worth it to reconsider if those two terms are really needed. Group to role mapping arguably is needed for deployments where the enterprise is using applications developed by a third party. The mapping allows application authorization roles to be assigned from enterprise users. The one to one role mapper would provide a simplification for applications not requiring the mapping. I am not sure how to get away from role mapping and still accommodate the common Java EE security use cases. Another thing is that while for the example OneToOneRoleMapper is great, in practice I think this could better be the default for this kind of ease of use facility. Agreed I wonder if the API for this annotation would not be better off using CDI names and/or qualifyers instead of or in addition to JNDI. I think using JNDI is the current standard for referring to resources. Although CDI seems like the "hammer for everyone's nail", I could not find any standards for using CDI names to refer to resources. @Authenticator( authMethodLookup="java:app/prodAuthMethod", userSourceLookup=“java:app/prodUserSource”, roleMapperLookup=“java:app/OneToOneRoleMapper” ) I agree with this. authMethodLookup would make sense if JASPIC were updated to be configurable with standardized SAMs. The absence of authMethodLookup infers the currently determined authmethod (e.g., via web.xml) would use the specified UserSource and RoleMapper for authentication within the application. what code is responsible for comparing the submitted password against the actual password? This has to be custom code too, as in general the server cannot assume any specific format or hash method/salt etc of the password (or any other type of credential). Since the UserService internally hashes/encrypts the password, I think the UserService should encapsulate that decision. For example, we could remove the Password attribute from UserInfo and add a UserService operation which would encapsulate the password check, like: boolean isValid( username, password ) That said, we are also considering separating Password into a separate service: PasswordService or CredentialService. This would facilitate having a separate, more secure credential repository.
        Hide
        arjan tijms added a comment -

        UserService would be meant for applications to manage users. For OpenID Connect user repositories, I would expect a JASPIC SAM to cover that.

        Hmmm, hopefully it will be possible to come to an abstraction where there will be no need for one group of authentication methods to have a different API/SPI.

        Group to role mapping arguably is needed for deployments where the enterprise is using applications developed by a third party.

        Yes, of course. But that wasn't what I meant Group to role mapping is a key requirement for the above use case and definitely shouldn't be done away with. What I meant is that the term group may not be necessary and could just be called role as well.

        E.g. we now have:

        Term Meaning
        Group Organization wide role
        Role Application wide role
        Role ref Component wide role

        The term group specifically is a source of confusion. People dream up all kinds of meanings for it, EXCEPT the meaning "organization wide role". I wasted so many hours trying to explain to different developers and in the end I think they still felt that group meant something else than it actually means.

        group is also not entirely consistently used. JASPIC recognizes the term and uses it in its API/SPI but JACC does not.

        Role ref is a problematic term too, but in practice not a big issue since it defaults to Role anyway and I think in practice people don't really use it (correct me if I'm wrong).

        Although longer, I feel calling the process something like "organization role to application role mapping" or somewhat shorter "organization to application role mapping" is quite a bit clearer. Alternatively, "global" could be used instead of "organization" as well, and "application" could be abbreviated leading to: "global to app role mapping". The new role hierarchy (wrt terminology) could then become:

        Term Meaning
        Global role Organization wide role
        Application Role Application wide role
        Component Role Component wide role

        I could not find any standards for using CDI names to refer to resources.

        CDI beans can be explicitly named (@Named annotation in user code, or the getName method in the Bean type for extensions).
        More common would however be the usage of bean types (i.e. Java interfaces) and/or qualifiers, which is a type safe approach.

        I think the UserService should encapsulate that decision.

        Should applications always subclass the UserService then, or do you envision a configurable choice of some well known standard hash/encrypt methods and a subclass or plug-in type if the algorithm the user uses is not among the standard choices?

        Show
        arjan tijms added a comment - UserService would be meant for applications to manage users. For OpenID Connect user repositories, I would expect a JASPIC SAM to cover that. Hmmm, hopefully it will be possible to come to an abstraction where there will be no need for one group of authentication methods to have a different API/SPI. Group to role mapping arguably is needed for deployments where the enterprise is using applications developed by a third party. Yes, of course. But that wasn't what I meant Group to role mapping is a key requirement for the above use case and definitely shouldn't be done away with. What I meant is that the term group may not be necessary and could just be called role as well. E.g. we now have: Term Meaning Group Organization wide role Role Application wide role Role ref Component wide role The term group specifically is a source of confusion. People dream up all kinds of meanings for it, EXCEPT the meaning "organization wide role". I wasted so many hours trying to explain to different developers and in the end I think they still felt that group meant something else than it actually means. group is also not entirely consistently used. JASPIC recognizes the term and uses it in its API/SPI but JACC does not. Role ref is a problematic term too, but in practice not a big issue since it defaults to Role anyway and I think in practice people don't really use it (correct me if I'm wrong). Although longer, I feel calling the process something like "organization role to application role mapping" or somewhat shorter "organization to application role mapping" is quite a bit clearer. Alternatively, "global" could be used instead of "organization" as well, and "application" could be abbreviated leading to: "global to app role mapping". The new role hierarchy (wrt terminology) could then become: Term Meaning Global role Organization wide role Application Role Application wide role Component Role Component wide role I could not find any standards for using CDI names to refer to resources. CDI beans can be explicitly named ( @Named annotation in user code, or the getName method in the Bean type for extensions). More common would however be the usage of bean types (i.e. Java interfaces) and/or qualifiers, which is a type safe approach. I think the UserService should encapsulate that decision. Should applications always subclass the UserService then, or do you envision a configurable choice of some well known standard hash/encrypt methods and a subclass or plug-in type if the algorithm the user uses is not among the standard choices?
        Hide
        yosshi2008 added a comment -

        In order to create the application with more strong user authentication,
        we would like to insert the password as SSHA(Salted SHA).
        And there was no way to implement it as standard.
        (It depends on the Application Server.)

        Thus could you also consider to implement the API which support the SSHA ?
        I assume that It may be influence following API.

        UserInfo properties:

        + Password
        
+ Attributes

        UserService operations:

        + UserInfo:loadUserByUsername(username)

        + changePassword

        + createUser

        + updateUser
        
+ addUserToGroup


        Show
        yosshi2008 added a comment - In order to create the application with more strong user authentication, we would like to insert the password as SSHA(Salted SHA). And there was no way to implement it as standard. (It depends on the Application Server.) Thus could you also consider to implement the API which support the SSHA ? I assume that It may be influence following API. UserInfo properties:
 + Password 
+ Attributes UserService operations:
 + UserInfo:loadUserByUsername(username)
 + changePassword
 + createUser
 + updateUser 
+ addUserToGroup

        ldemichiel made changes -
        Project javaee-spec [ 11928 ] javaee-security-spec [ 14209 ]
        Key JAVAEE_SPEC-9 JAVAEE_SECURITY_SPEC-10
        Workflow classic default workflow [ 114186 ] jira [ 136837 ]

          People

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

            Dates

            • Created:
              Updated: