14 Replies Latest reply on Jan 25, 2011 3:41 PM by barakka

    JBWS-2210 : CXF Username Token JAAS integration

    sergeyb

      Hi

       

      I've been looking recently at resolving JBWS-2210 [1].

       

      The issue is to do with the fact that a WS-Security UsernameToken can not be currently used in JBoss CXF to integrate with the JBoss security subsystem for authentication and authorization decisions be made.

       

      I've done some initial changes in CXF and started a discussion on the cxf dev list [2].

       

      Here is the summary of the proposed approach.

       

      The idea is to override a CXF WSS4JInInterceptor and provide a CallbachHandler to the WSS4J module which will ensure that an authentication occurs but also that a current SecurityContext is properly populated. The CXF interceptor which overrides CXF WSS4JInInterceptor is an abstract one [3], its job is to ensure that irrespectively of whether a current password is digested or not, the concrete subclass is requested to authenticate and populate a Subject.

       

      CXF also includes an abstract AuthorizingInInterceptor[4] which requests a subclass for a list of expected roles and asks SecurityContext if a user is in role.

       

      Given the above, here's how I'm thinking of resolving JBWS-2210 :

       

      - provide a CXF interceptor (to be included in JBoss CXF) which will extend [3] and delegate to JBoss AuthenticationManager to populate a Subject

      - provide a CXF interceptor (to be included in JBoss CXF) which will extend [4] and retrieve a list of expected roles;

       

      JBoss CXF WS-Security UsernameToken-aware endpoints will include the above two interceptors if the authentication & authorization is needed.

       

      At the moment I'm working on a system test validating the above approach.

       

      If you have any comments then please let me know

       

      cheers, Sergey

       

      [1] https://jira.jboss.org/jira/browse/JBWS-2210

      [2] http://old.nabble.com/Using-WS-Security-UsernameToken-to-authenticate-users-and-populate--SecurityContexts-td28165583.html

      [3] http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java
      [4] http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java

       

       

       

        • 1. Re: JBWS-2210 : CXF Username Token JAAS integration
          anil.saldhana

          If you are trying to do the authentication in JBoss AS, you can use PicketBox Api.

          http://community.jboss.org/wiki/PicketBoxOverview

          • 2. Re: JBWS-2210 : CXF Username Token JAAS integration
            dlofthouse

            Hi Sergey - I have worked on some of the similar areas you are looking at here in our Native stack so have been interested to see your comments here.

             

            Looking at your comments regarding the changes needed in CXF it looks like you are along the same lines I would consider, essentially I came to the same conclusion that the UsernameTokenProcessor within WSS4J is making an unsuitable assumption that you can obtain a users password.

             

            Regarding how all of this would fit with the application server there are a couple of other things to consider, when integrating with the application server we are really looking to pass as much back to the application server provided containers as possible and not just have an independent authentication / authorization  process within the web services stack.

             

            The approach of having two interceptors (one for authentication and one for authorization) is probably the biggest part of this problem already solved.

             

            Where this becomes really apparent is where endpoints are deployed as EJB3 session beans, in this case the container can already be configured to perform authentication and authorization - as a deployed session bean can potentially be called from multiple different clients it makes sense for the authorization checks to remain with the bean.

             

            A second requirement would be related to endpoints deployed as POJOs - although these do not have any container security before the invocation there is still the potential that the implementations will call other secured resources so any identity would need to be propagated for these calls.

             

            The point of these two comments really is to highlight that this is not just a case of obtaining a Subject from whatever app server you are running in but actually associating the users identity with the request so that is propagates for further calls within the application server.  Using the APIs suggested from Anil should help with this so this is just something to keep in mind.

             

            A final feature related to this that I know there is user demand for would be the ability to annotate the POJO endpoints with the same role annotations as used on EJB3 sesstion beans - we were unable to do this for our Native implementation of this as we had to support JAX-RPC as well as JAX-WS but as this would be JAX-WS only this could be an option and may help simplify the role configuration.

            • 3. Re: JBWS-2210 : CXF Username Token JAAS integration
              asoldano

              Thanks Darran and Anil for the involvement in this thread.

              The approach of having two interceptors (one for authentication and one for authorization) is probably the biggest part of this problem already solved.

              +1

               

              Where this becomes really apparent is where endpoints are deployed as EJB3 session beans, in this case the container can already be configured to perform authentication and authorization - as a deployed session bean can potentially be called from multiple different clients it makes sense for the authorization checks to remain with the bean.

               

              A second requirement would be related to endpoints deployed as POJOs - although these do not have any container security before the invocation there is still the potential that the implementations will call other secured resources so any identity would need to be propagated for these calls.

               

              I think I've mentioned this to Sergey offline before, but the comments above better clarify the concept, thanks Darran.

               

              A final feature related to this that I know there is user demand for would be the ability to annotate the POJO endpoints with the same role annotations as used on EJB3 sesstion beans - we were unable to do this for our Native implementation of this as we had to support JAX-RPC as well as JAX-WS but as this would be JAX-WS only this could be an option and may help simplify the role configuration.

              Definitely a good idea, that could also simplify the user experience. JAX-RPC endpoints are not going to be deployed using the CXF impl, so it's actually JAX-WS only. We might want to think about a proper roles' configuration with a xml descriptor too later, but the annotation solution is probably the ideal one for the first implementation.

              • 4. Re: JBWS-2210 : CXF Username Token JAAS integration
                sergeyb

                Hi Anil

                 

                thanks for the link. For the moment I tried (with  the help from Alessio) the approach used in JBoss Native,

                where AuthenticationManager is resolved via JNDI lookup. But I'll bear in mind that a newer PicketBox api

                is available now, I may ask for some clarifications a bit later on...

                 

                cheers, Sergey

                 

                 

                • 5. Re: JBWS-2210 : CXF Username Token JAAS integration
                  sergeyb

                  Hi Darran

                   

                  Thanks for the comments.

                   

                  The approach of having two interceptors (one for authentication and one for authorization) is probably the biggest part of this problem already solved.

                   

                  Where this becomes really apparent is where endpoints are deployed as EJB3 session beans, in this case the container can already be configured to perform authentication and authorization - as a deployed session bean can potentially be called from multiple different clients it makes sense for the authorization checks to remain with the bean.

                   

                  I see. Perhaps in some cases no authorization will be required, so just dropping an authorization interceptor will satisfy such requirements.

                   

                  The point of these two comments really is to highlight that this is not just a case of obtaining a Subject from whatever app server you are running in but actually associating the users identity with the request so that is propagates for further calls within the application server.  Using the APIs suggested from Anil should help with this so this is just something to keep in mind.

                   

                  Sure. I saw the following code line in the JBoss Native :

                   

                  > securityAdaptor.pushSubjectContext(subject, principal, credential);

                   

                  this is probably to do with what you explained above.

                   

                  A final feature related to this that I know there is user demand for would be the ability to annotate the POJO endpoints with the same role annotations as used on EJB3 sesstion beans - we were unable to do this for our Native implementation of this as we had to support JAX-RPC as well as JAX-WS but as this would be JAX-WS only this could be an option and may help simplify the role configuration

                  I was thinking of adding (at the CXF level) a utility AuthorizingInInterceptor subclass which would be configured with the name of the annotation such as @RolesAllowed that target POJO classes may be annotated with. This interceptor would introspect a given class and return a list of expected roles for a given method name. Perhaps it might help with addressing this requirement 

                   

                  thanks, Sergey

                  • 6. Re: JBWS-2210 : CXF Username Token JAAS integration
                    dlofthouse
                    I see. Perhaps in some cases no authorization will be required, so just dropping an authorization interceptor will satisfy such requirements.

                    Yes this is where I think your two interceptor approach will help as it gives you the option of dropping the authorization one when not required.

                     

                    Sure. I saw the following code line in the JBoss Native :

                     

                    > securityAdaptor.pushSubjectContext(subject, principal, credential);

                     

                    this is probably to do with what you explained above.

                    Yes that line is where we push the subject onto the ThreadLocal for the request so it is ready for further checks for subsequent calls.

                     

                    Following the existing code will probably help you get something up and running but do keep in mind that it was written at a time the WS stack needed to support JBoss AS 4, 5 and 6 so a final switch to the APIs recommended by Anil would be required at some point.

                    • 7. Re: JBWS-2210 : CXF Username Token JAAS integration
                      sergeyb

                      Hi

                       

                      I've created the initial patch for [1].

                       

                      The reason it has to be a patch is that JBossCXF currently depends on CXF 2.2.6 while the system test which I've added depends on CXF 2.2.8-SNAPSHOT.

                       

                      The [UsernameAuthorizingTestCase] test is quite simple but it demonstrates the idea of separating authentication and authorization actions into separate phases.

                       

                      SubjectCreatingInterceptor extends [2] and authenticates and populates a Subject using a (legacy) JBossSX api which will need to be updated to use PicketBox API. SubjectCreatingInterceptor could've also overridden a createSecurityContext() from its superclass if the default SecurityContext.isUserInRole was not working (but it does in this case). Eventually this interceptor should likely make it into JBossCXF/trunk/src/main. At the moment some of the code required to deal with digests is missing, it is commented out but classes like NonceStore can be ported from JBossNative.

                       

                      Finally, CXF-based interceptor [3] is used to authorize the requests, here is a sample configuration :

                       

                      <util:map id="methodPermissions">
                           <entry key="sayHello" value="friend colleague"/>
                           <entry key="greetMe" value="snoopies"/>
                        </util:map>

                        <bean id="AuthorizeIn" class="org.apache.cxf.interceptor.security.SimpleAuthorizingInterceptor">
                         <property name="methodRolesMap" ref="methodPermissions"/>
                        </bean>

                       

                      Other authorizing interceptors can be added easily. For example, one can extend SimpleAuthorizingInterceptor and set a property identifying a service class on it. The setter would load and introspect a class for @RolesAllowed, @DenyAll, etc and set a roles map on the superclass. [4] can also be extended if say PicketBox AuthorizationManager were to be used.

                       

                      One thing which will need to be addressed at CXF level is a policy-first case, where interceptors are added by the policy runtime, so some work has to be done to ensure interceptors like SubjectCreatingInterceptor can be added when needed too.I'm planning to investigate what needs to be done...

                       

                      Any comments - let me know please

                       

                      cheers, Sergey

                       

                      [1] https://jira.jboss.org/jira/browse/JBWS-2210

                      [2] http://svn.apache.org/repos/asf/cxf/trunk/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/AbstractWSS4JSecurityContextProvidingInterceptor.java

                      [3] http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/SimpleAuthorizingInterceptor.java

                      [4] http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractAuthorizingInInterceptor.java

                      • 8. Re: JBWS-2210 : CXF Username Token JAAS integration
                        asoldano

                        Sergey,

                        thanks a lot for the patch. I'm going to give it a try locally and let you know (hopefully by the end of this week, otherwise next week).

                        • 9. Re: JBWS-2210 : CXF Username Token JAAS integration
                          sergeyb

                          thanks for your help Alessio

                           

                          cheers, Sergey

                          • 10. Re: JBWS-2210 : CXF Username Token JAAS integration
                            asoldano

                            Sergey,

                            I've tried the patch, very good. I agree the interceptor will eventually be moved out of the testsuite and to the src/main. Thank you for the contribution, really appreciated.

                            • 11. Re: JBWS-2210 : CXF Username Token JAAS integration
                              sergeyb

                              I gave it an initial try with trying to move the legacy JNDI code to PicketBox api, given that it is likely I'll need to work with PicketLink too (which sits on top of PocketBox as far as I understand), so the question is how to specify the configuration file :

                               

                              https://community.jboss.org/thread/152423

                               

                               

                              thanks, Sergey

                              • 12. JBWS-2210 : CXF Username Token JAAS integration
                                barakka

                                Hello,

                                 

                                have you figured our a solution for policy-first cases? I'm currently testing with jbossws-cxf 3.4 and it seems that when the policy interceptor analyzes the policy it puts the PolicyBasedWSS4JInInterceptor first in the chain, which makes the SubjectCreatingInterceptor useless.

                                 

                                I'm currently playing around with the WSSecurityPolicyLoader, in order to remove the PolicyBasedWSS4JInInterceptor interceptor and add a new one that would be a mix between the PolicyBasedWSS4JInInterceptor and SubjectCreatingInterceptor, but it seems a bit over-complicated.

                                 

                                Thanks,

                                Riccardo.

                                • 13. JBWS-2210 : CXF Username Token JAAS integration
                                  sergeyb

                                  Please see

                                   

                                  http://svn.apache.org/repos/asf/cxf/trunk/systests/ws-specs/src/test/java/org/apache/cxf/systest/ws/wssec10/server/server_restricted_authorized_2.xml

                                   

                                  for a policy first case, you need to set a "ws-security.ut.no-callbacks" property.

                                  And here is a test SimpleSubjectCreatingInterceptor :

                                   

                                  http://svn.apache.org/repos/asf/cxf/trunk/systests/ws-specs/src/test/java/org/apache/cxf/systest/ws/wssec10/server/SimpleSubjectCreatingInterceptor.java

                                   

                                  it still extends the org.apache.cxf.ws.security.wss4j.AbstractUsernameTokenAuthenticatingInterceptor (just to make sure) the existing code

                                  relying on it works. So setting the property above should fix the issue for the policy first case.

                                   

                                  SimpleSubjectCreatingInterceptor should really extend

                                   

                                  http://svn.apache.org/repos/asf/cxf/trunk/rt/core/src/main/java/org/apache/cxf/interceptor/security/AbstractUsernameTokenInInterceptor.java

                                   

                                  no WSS4J dependency, UsernameToken is a CXF specific class, it can be extended without breaking the subclasses...

                                   

                                  Hope this helps, Sergey

                                  • 14. JBWS-2210 : CXF Username Token JAAS integration
                                    barakka

                                    Thanks a lot!!

                                     

                                    It did help, although not 100%. With the class you have suggested, I then get a caller unauthorized exception in the ejb security interceptors.

                                     

                                    So, instead of that example, I've tried with the org.jboss.wsf.stack.cxf.security.authentication.SubjectCreatingInterceptor pulled from the jbossws-cxf integration libs, and it worked perfectly. In the other case, I believe, the subject or the security context are not propagated to the ejb security interceptors (the call "secAdaptorFactory.newSecurityAdapter().pushSubjectContext(subject, principal, password)" in the SubjectCreatingInterceptor).

                                     

                                    There is still a thing that I'm not getting though: I've been playing both with UsernameToken auth and SAML token auth using the PicketLink trust project. In case of UsernameTokenAuth the login modules get called when the SubjectCreatingInterceptor calls the validate on the AuthenticationManager, which is during the interceptor message handling.

                                     

                                    Instead, the SAML handler only creates the correct credentials and the validation (login) is invoked when the call hits the ejb security interceptor. The SAML handler does have some code that propagates the context (which in the end uses the

                                    SecurityContextAssociation from JBoss security spi to do it).

                                     

                                    This let's me think that, maybe, by just propagating the security context in the SimpleSubjectCreatingInterceptor from the example you gave, and therefore avoid the call to the AuthenticationManager, the credential validation would be triggered directly in the ejb security interceptors. Is this the correct interpretation? I haven't tried it out, as the SubjectCreatingInterceptor just works, but I'm still curious .

                                     

                                    Thanks a lot in any case, as this avoided having to override the WSSecurityPolicy loader and create a mix between SubjectCreatingInterceptor and the PolicyBasedWSS4JInInterceptor, which I already tried, was working, but was also very, very ugly.

                                     

                                    Riccardo.