jaspic-spec
  1. jaspic-spec
  2. JASPIC_SPEC-24

Servlet profile specific types to increase ease of use

    Details

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

      Description

      JASPIC as it's currently defined has an exceptionally flexible and abstract API. It can handle authentication for different kinds of environments, which are defined in profiles. Profiles demand certain behavior and specific keys to be present in otherwise generic maps that are used throughout the API.

      While this indeed makes the API flexible, it comes at the cost of a reduced ease-of-use. Developers wishing to program for e.g. the Servlet Profile have to read through documentation to see in what way they need to fulfill the contract of the profile and which keys can be inserted or retrieved from the mentioned maps. A certain amount of casting from type Object is also required to work with the profile.

      This required effort can likely be significantly reduced by the introduction of specific Java types for a profile. The Servlet spec uses something similar to this. There is a GenericServlet which is protocol independent and an HtppServlet that's provided as a convenience for HTTP usage (which is overwhelmingly the common usage).

      In practice those specific types are already created by JASPIC users, e.g. JBoss uses WebServerAuthModule as a Servlet Profile specific base class for a ServerAuthModule, and in OmniSecurity we're prototyping a base class as well with HttpServerAuthModule.

      A standardized convenience ServerAuthModule base class for the Servlet Profile could have the following properties:

      • Default implementation of getSupportedMessageTypes returning the two mandated classes.
      • Default initialize that just stores the incoming parameters for later retrieval
      • Default secureResponse just returning a success status
      • Default cleanSubject that just removes the Principals from the given Subject
      • A new validateRequest method that has HttpServletRequest and HttpServletResponse as parameters and perhaps a context object of some kind (e.g. called HttpMsgContext or something similar (just like ServletContext, FacesContext, etc).

      The context object mentioned above can contain a number of convenience methods for working with the Servlet Profile, e.g.

      • an isProtected method corresponding to the javax.security.auth.message.MessagePolicy.isMandatory key.
      • a registerWithContainer(String, List<String>) method as a convenience shortcut for working directly with the CallerPrincipalCallback and GroupPrincipalCallback
      • a setRegisterSession and isRegisterSession corresponding to the javax.servlet.http.registerSession key.
      • getters for the (raw) MessageInfo, Subject parameters of the super validateRequest method and the CallbackHandler that was passed into the initialize method.

      The above mentioned types, names, and semantics are just examples to kickoff a discussion about this matter. Note that the proposed convenience types and methods are just conveniences and should never be the only way to work with the API.

        Activity

        arjan tijms created issue -
        Show
        dblevins added a comment - Note to readers, the HttpServerAuthModule code moved: https://github.com/omnifaces/omnisecurity/blob/master/src/main/java/org/omnifaces/security/jaspic/core/HttpServerAuthModule.java
        Hide
        alex.kosowski added a comment -

        The JSR 375 EG proposes moving JASPIC_SPEC-17 to https://java.net/jira/browse/JAVAEE_SECURITY_SPEC. JSR 375 is focused on Application Development security ease of use, and adding an ease-of-use layer on top of JASPIC seems appropriate for JSR 375.

        Show
        alex.kosowski added a comment - The JSR 375 EG proposes moving JASPIC_SPEC-17 to https://java.net/jira/browse/JAVAEE_SECURITY_SPEC . JSR 375 is focused on Application Development security ease of use, and adding an ease-of-use layer on top of JASPIC seems appropriate for JSR 375.
        Hide
        monzillo added a comment -

        I fully support this idea. And like JBOSS and OmniSecurity, Glassfish and project Nobis have similar abstractions.

        The ServletSamHelper of project Nobis can be seen at the following link. It embodies lots of utilities, some of which depend on other parts of the "relying party utilities" module of NOBIS. I would prefer something smaller as you have suggested...but you might want to take a look at it

        https://java.net/projects/nobis/sources/git/content/Nobis/authentication/relying-party-utilities/src/main/java/org/glassfish/nobis/auth/rp/util/ServletSamHelper.java

        I am not sure I fully understand the need for a new context object, but perhaps you are looking for some form of unification of initialization and request processing contextual objects of the existing SPI,

        Show
        monzillo added a comment - I fully support this idea. And like JBOSS and OmniSecurity, Glassfish and project Nobis have similar abstractions. The ServletSamHelper of project Nobis can be seen at the following link. It embodies lots of utilities, some of which depend on other parts of the "relying party utilities" module of NOBIS. I would prefer something smaller as you have suggested...but you might want to take a look at it https://java.net/projects/nobis/sources/git/content/Nobis/authentication/relying-party-utilities/src/main/java/org/glassfish/nobis/auth/rp/util/ServletSamHelper.java I am not sure I fully understand the need for a new context object, but perhaps you are looking for some form of unification of initialization and request processing contextual objects of the existing SPI,
        Hide
        arjan tijms added a comment -

        .but you might want to take a look at it
        https://java.net/projects/nobis/sources/git/content/Nobis/authentication/relying-party-utilities/src/main/java/org/glassfish/nobis/auth/rp/util/ServletSamHelper.java

        Thanks for the pointer. Yes, that one is indeed a similar kind of helper / ease of use class.

        I am not sure I fully understand the need for a new context object, but perhaps you are looking for some form of unification of initialization and request processing contextual objects of the existing SPI

        The context object is not intended to really introduce any new capabilities, but just encapsulate the various data items a SAM uses in one convenient to use utility class.

        For instance, the proposed AuthStatus notifyContainerAboutLogin(String username, List<String> roles) utility method would need for its implementation at least the (client) subject, and the handler. The idea here is that this context object holds these two data items in addition to things like the message info object and module options.

        That way the user doesn't have to pass these data items to the methods that need them all the time. If the notifyContainerAboutLogin method would be a base class method that naturally wouldn't be needed either, but an additional wish (not stated in this issue) is to not have an HTTP specific base class, but to delegate to an HTTP specific SAM-like type. This type would then get the (subject, handler, module options, message info, ...) via one "holder" (context) object instead of via 5 or more separate parameters.

        I experimented with such context object here: https://github.com/omnifaces/omnisecurity/blob/master/src/main/java/org/omnifaces/security/jaspic/core/HttpMsgContext.java

        It can be seen in action here: http://arjan-tijms.omnifaces.org/2014/11/header-based-stateless-token.html

        (in the delegation variant, the TokenAuthModule would not extend HttpServerAuthModule but probably implement some interface instead and possibly have a CDI qualifier annotation)

        Of course all of the utility/helper code implemented thus far is just to experiment with the various ideas.

        Show
        arjan tijms added a comment - .but you might want to take a look at it https://java.net/projects/nobis/sources/git/content/Nobis/authentication/relying-party-utilities/src/main/java/org/glassfish/nobis/auth/rp/util/ServletSamHelper.java Thanks for the pointer. Yes, that one is indeed a similar kind of helper / ease of use class. I am not sure I fully understand the need for a new context object, but perhaps you are looking for some form of unification of initialization and request processing contextual objects of the existing SPI The context object is not intended to really introduce any new capabilities, but just encapsulate the various data items a SAM uses in one convenient to use utility class. For instance, the proposed AuthStatus notifyContainerAboutLogin(String username, List<String> roles) utility method would need for its implementation at least the (client) subject, and the handler. The idea here is that this context object holds these two data items in addition to things like the message info object and module options. That way the user doesn't have to pass these data items to the methods that need them all the time. If the notifyContainerAboutLogin method would be a base class method that naturally wouldn't be needed either, but an additional wish (not stated in this issue) is to not have an HTTP specific base class, but to delegate to an HTTP specific SAM-like type. This type would then get the (subject, handler, module options, message info, ...) via one "holder" (context) object instead of via 5 or more separate parameters. I experimented with such context object here: https://github.com/omnifaces/omnisecurity/blob/master/src/main/java/org/omnifaces/security/jaspic/core/HttpMsgContext.java It can be seen in action here: http://arjan-tijms.omnifaces.org/2014/11/header-based-stateless-token.html (in the delegation variant, the TokenAuthModule would not extend HttpServerAuthModule but probably implement some interface instead and possibly have a CDI qualifier annotation) Of course all of the utility/helper code implemented thus far is just to experiment with the various ideas.
        alex.kosowski made changes -
        Field Original Value New Value
        Project jaspic-spec [ 12972 ] javaee-security-spec [ 14209 ]
        Key JASPIC_SPEC-17 JAVAEE_SECURITY_SPEC-22
        Workflow classic default workflow [ 123213 ] jira [ 137836 ]
        Hide
        monzillo added a comment -

        I am probably not fully understanding the use case for this context, as I am not sure who you mean by user when you write "That way the user doesn't have to pass these items to the methods that need them all the time. It sounds like you intend to add new interfaces to the auth module, such that they can be called by an application. There may be reasons to do that, but as I think you know, the SAM interfaces and objects are intended to be called by the underlying message processing runtime. The container/message processing runtime is willing to pass its CBH, which may provide access to its private keys and secrets, to the SAM. It would not likely want to provide this capability directly to any application. When a SAM is packaged in an app, these distinctions may appear artificial. nonetheless, I think you should resist the temptation to create new context interfaces that expose public interfaces to what I presume would be the container's CBH. Sorry if I have misunderstood.

        As I have said, I can see the value in making it easier to write a SAM that confroms to the servlet container profile. That seems relatively straight-forward, and there seems to be ample precendent for how to do that.

        In my experiments with packaging SAM's in application archives, I found that what would be a big help would be the definition/standardization of an interface to represent module initialization properties. I was using the Servlet container's handle types facility, and I found that a Servlet Container Intializer could easily detect and configure any SAM packaged in the app, but that there was no convenient/standard to package and find the corresponding SAM initialization properties. What I thought might work was the definition of a new property interface that could be detected by handle types, and such that an implementation could be embedded in the app (and which could then be found by the handle types mechanism).

        I would be interested in your thoughts on how use CDI to obtain instance specific SAM initialization properties, that could then be used (by an embedded AuthContext) to initialize the SAM.

        Show
        monzillo added a comment - I am probably not fully understanding the use case for this context, as I am not sure who you mean by user when you write "That way the user doesn't have to pass these items to the methods that need them all the time. It sounds like you intend to add new interfaces to the auth module, such that they can be called by an application. There may be reasons to do that, but as I think you know, the SAM interfaces and objects are intended to be called by the underlying message processing runtime. The container/message processing runtime is willing to pass its CBH, which may provide access to its private keys and secrets, to the SAM. It would not likely want to provide this capability directly to any application. When a SAM is packaged in an app, these distinctions may appear artificial. nonetheless, I think you should resist the temptation to create new context interfaces that expose public interfaces to what I presume would be the container's CBH. Sorry if I have misunderstood. As I have said, I can see the value in making it easier to write a SAM that confroms to the servlet container profile. That seems relatively straight-forward, and there seems to be ample precendent for how to do that. In my experiments with packaging SAM's in application archives, I found that what would be a big help would be the definition/standardization of an interface to represent module initialization properties. I was using the Servlet container's handle types facility, and I found that a Servlet Container Intializer could easily detect and configure any SAM packaged in the app, but that there was no convenient/standard to package and find the corresponding SAM initialization properties. What I thought might work was the definition of a new property interface that could be detected by handle types, and such that an implementation could be embedded in the app (and which could then be found by the handle types mechanism). I would be interested in your thoughts on how use CDI to obtain instance specific SAM initialization properties, that could then be used (by an embedded AuthContext) to initialize the SAM.
        Hide
        arjan tijms added a comment -


        It sounds like you intend to add new interfaces to the auth module, such that they can be called by an application. There may be reasons to do that, but as I think you know, the SAM interfaces and objects are intended to be called by the underlying message processing runtime.

        No, that's not the intention at all The "user" in this case is "someone writing a SAM". Sorry if I have not explained it clearly.

        The idea is to make it easier for someone writing a SAM to conform to the servlet profile. The "context" object would just be a collection of convenient methods that a SAM writer often uses. It's 100% syntactic sugar. There would be no change whatsoever in the SAM interfaces as called by the runtime.

        As another example; the code to use the handler is now typically something like the following:

          try {
                    handler.handle( new Callback[] {
        	            new CallerPrincipalCallback(clientSubject, "user"),
        	            new GroupPrincipalCallback(clientSubject, new String[] { "role1", "role2", "role3" })
                    );
        
                    return SUCCESS;
                } catch (IOException | UnsupportedCallbackException e) {
                    throw (AuthException) new AuthException().initCause(e);
                }
        

        For more advanced users (vendors, typically) this code is not that bad. However, for many other users this is just a bit too noisy. So we can create a (static) utility method for this to make it somewhat easier:

        return SamUtilities.notifyContainerAboutLogin(
            handler, clientSubject
            "user",
            asList("role1", "role2", "role3")
        );
        

        In this case, the user has to provide the 2 objects that are internally needed to implement this utility method: handler and clientSubject. This is not that bad, but I felt we can do even better by not even requiring that. At this level of ease-of-use, the user is typically not thinking about handlers or subjects, so for this use case these two objects are just noise as well.

        The next step in simplifying the utility method is leaving those objects out, making it:

        return samUtilities.notifyContainerAboutLogin(
            "user",
            asList("role1", "role2", "role3")
        );
        

        In that case the "samUtilities" object stores the handler and clientSubject objects internally, so the user doesn't have to provide them every time.

        That's basically all There's no really deep architectural change or new approach proposed here, and specifically it's absolutely not proposed to (indirectly) expose the container's CBH in any new way.

        A SAM with servlet container profile specific methods (such as validateHttpRequest as opposed to the general validateRequest) could be implemented via sub classing a base class (as I did in my OmniSecurity prototype) OR could be done by delegating to a type with an interface. But this is just an implementation technique. The "type with an interface" would still logically be part of the SAM.

        E.g. without CDI (left out some code for brevity):

        class TestAuthenticationModule implements ServerAuthModule {
        
           HttpAuthModule myModule = new MyHttpAuthModule();
        
           AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) {
               return myModule.validateHttpRequest(
                   (HttpServletRequest)messageInfo.getRequest(),
                   (HttpServletResponse)messageInfo.getResponse(),
                   new SamUtilities(handler, options, messageInfo, clientSubject));
           }
        }
        
        Show
        arjan tijms added a comment - It sounds like you intend to add new interfaces to the auth module, such that they can be called by an application. There may be reasons to do that, but as I think you know, the SAM interfaces and objects are intended to be called by the underlying message processing runtime. No, that's not the intention at all The "user" in this case is "someone writing a SAM". Sorry if I have not explained it clearly. The idea is to make it easier for someone writing a SAM to conform to the servlet profile. The "context" object would just be a collection of convenient methods that a SAM writer often uses. It's 100% syntactic sugar. There would be no change whatsoever in the SAM interfaces as called by the runtime. As another example; the code to use the handler is now typically something like the following: try { handler.handle( new Callback[] { new CallerPrincipalCallback(clientSubject, "user" ), new GroupPrincipalCallback(clientSubject, new String [] { "role1" , "role2" , "role3" }) ); return SUCCESS; } catch (IOException | UnsupportedCallbackException e) { throw (AuthException) new AuthException().initCause(e); } For more advanced users (vendors, typically) this code is not that bad. However, for many other users this is just a bit too noisy. So we can create a (static) utility method for this to make it somewhat easier: return SamUtilities.notifyContainerAboutLogin( handler, clientSubject "user" , asList( "role1" , "role2" , "role3" ) ); In this case, the user has to provide the 2 objects that are internally needed to implement this utility method: handler and clientSubject . This is not that bad, but I felt we can do even better by not even requiring that. At this level of ease-of-use, the user is typically not thinking about handlers or subjects, so for this use case these two objects are just noise as well. The next step in simplifying the utility method is leaving those objects out, making it: return samUtilities.notifyContainerAboutLogin( "user" , asList( "role1" , "role2" , "role3" ) ); In that case the "samUtilities" object stores the handler and clientSubject objects internally, so the user doesn't have to provide them every time. That's basically all There's no really deep architectural change or new approach proposed here, and specifically it's absolutely not proposed to (indirectly) expose the container's CBH in any new way. A SAM with servlet container profile specific methods (such as validateHttpRequest as opposed to the general validateRequest ) could be implemented via sub classing a base class (as I did in my OmniSecurity prototype) OR could be done by delegating to a type with an interface. But this is just an implementation technique. The "type with an interface" would still logically be part of the SAM. E.g. without CDI (left out some code for brevity): class TestAuthenticationModule implements ServerAuthModule { HttpAuthModule myModule = new MyHttpAuthModule(); AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) { return myModule.validateHttpRequest( (HttpServletRequest)messageInfo.getRequest(), (HttpServletResponse)messageInfo.getResponse(), new SamUtilities(handler, options, messageInfo, clientSubject)); } }
        alex.kosowski made changes -
        Project javaee-security-spec [ 14209 ] jaspic-spec [ 12972 ]
        Key JAVAEE_SECURITY_SPEC-22 JASPIC_SPEC-24
        Workflow jira [ 137836 ] classic default workflow [ 137848 ]

          People

          • Assignee:
            Unassigned
            Reporter:
            arjan tijms
          • Votes:
            2 Vote for this issue
            Watchers:
            6 Start watching this issue

            Dates

            • Created:
              Updated: