1 2 Previous Next 23 Replies Latest reply on Nov 17, 2009 6:00 AM by Morten Andersen

    WSSE UsernameToken without HTTP basic auth?

    Mikael Larsson Newbie

      Hi!
      I've managed to implement a web service + a client that authenticates with WSSE UsernameToken.

      My problem is that the client side is always including the HTTP Authorization header.
      Something like:
      Authorization: Basic a2VybWl0OnRoZWZyb2c=

      Note, the WSSE data in the SOAP header is also included and looking ok.

      How can I keep the client from including the http basic authentication data and only include wsse data? Is this possible? What am I missing?

      My client is configured with

      <config>
       <username/>
       </config>


      I do the following in the client code:
      URL securityURL = new File("resources/jboss-wsse-client.xml").toURI().toURL();
      ((StubExt)myServiceStub).setSecurityConfig(securityURL.toExternalForm());
      ((StubExt)myServiceStub).setConfigName("Standard WSSecurity Client");
      Map<String, Object> reqContext = bp.getRequestContext();
      reqContext.put(BindingProvider.USERNAME_PROPERTY, "kermit");
      reqContext.put(BindingProvider.PASSWORD_PROPERTY, "thefrog");


      I guess that the client libraries will pick up the properties set on the request ctx and therefore assume that basic auth should be applied?
      Is there a way supply the username/pwd info to the WSSecurityDispatcher without having the client libraries adding http auth?

      I do get everything to work if I add the following to web.xml on the server side
      <login-config>
       <auth-method>BASIC</auth-method>
       <realm-name>JBossWS</realm-name>
       </login-config>

      but I would really like to only use wsse and not http basic authentication.

      The following in org/jboss/ws/core/client/RemotingConnectionImpl.java may be what is causing the problem together with implementation of the createRemotingMetaData method:
      static
       {
       metadataMap.put(Stub.USERNAME_PROPERTY, "http.basic.username");
       metadataMap.put(Stub.PASSWORD_PROPERTY, "http.basic.password");
       metadataMap.put(BindingProvider.USERNAME_PROPERTY, "http.basic.username");
       metadataMap.put(BindingProvider.PASSWORD_PROPERTY, "http.basic.password");
       }


      I'm currently using jbossws 2.0.1.GA

      /Mikael

        • 1. Re: WSSE UsernameToken without HTTP basic auth?
          Mikael Larsson Newbie

          So, adding:

          reqContext.put(StubExt.PROPERTY_AUTH_TYPE, StubExt.PROPERTY_AUTH_TYPE_WSSE);
          

          to the client side removed the http auth header.

          Guess this is because the org.jboss.ws.core.client.RemotingConnectionImpl-createRemotingMetaData method is called before the WSSecurityDispatcher calls ctx.put(StubExt.PROPERTY_AUTH_TYPE, StubExt.PROPERTY_AUTH_TYPE_WSSE); ? By setting this property from the client this is avoided.

          The problem now is that I can no longer the the login to work properly on the server side.
          What should I put in web.xml ? I've tried with
          <security-constraint>
           <web-resource-collection>
           <web-resource-name>ProtectedResource</web-resource-name>
           <url-pattern>/*</url-pattern>
           </web-resource-collection>
           <auth-constraint>
           <role-name>friend</role-name>
           </auth-constraint>
           </security-constraint>
           <!-- We do not want http basic authentication
           <login-config>
           <auth-method>BASIC</auth-method>
           <realm-name>JBossWS</realm-name>
           </login-config>
           -->
           <security-role>
           <role-name>friend</role-name>
           </security-role>
          


          But that results in the application not being authorized, I've tried to remove the security-constraint but then I can no longer retrieve the current principal information from within my WS implementation...
          I've tried to retrieve it using:
          Subject caller = (Subject) PolicyContext.getContext(SUBJECT_CONTEXT_KEY);
          

          and:
          @Resource
           javax.xml.ws.WebServiceContext wsCtx;
          java.security.Principal principal = wsCtx.getUserPrincipal();

          But both return null data.

          How should I retrive the principal data when using wsse usernametoken?

          I can see in the traces that the security information is picked up:
          2008-01-14 16:54:37,113 TRACE [org.jboss.security.SecurityAssociation] getSubject, sc=org.jboss.security.SecurityAssociation$SubjectContext@1b6c763{principal=kermit,subject=null}
          But how to retrieve it?


          • 2. Re: WSSE UsernameToken without HTTP basic auth?
            Mikael Larsson Newbie

            Continuing this little discussion between me myself and I...

            Found the following logs:
            2008-01-15 09:19:36,480 DEBUG [org.jboss.wsf.framework.DefaultSPIProvider] class org.jboss.wsf.spi.invocation.SecurityAdaptorFactory Implementation: org.jboss.wsf.container.jboss42.SecurityAdapterFactoryImpl@c774f0
            2008-01-15 09:19:36,482 TRACE [org.jboss.security.SecurityAssociation] setPrincipal, p=kermit, server=true
            2008-01-15 09:19:36,483 TRACE [org.jboss.security.SecurityAssociation] setPrincipal, sc=org.jboss.security.SecurityAssociation$SubjectContext@103c25f{principal=kermit,subject=null}
            2008-01-15 09:19:36,483 TRACE [org.jboss.security.SecurityAssociation] setCredential, sc=org.jboss.security.SecurityAssociation$SubjectContext@103c25f{principal=kermit,subject=null}

            Looks like the principal information is set but subject is not, why?

            When adding:

            System.out.println("Getting principal from SecurityAssociation: " + org.jboss.security.SecurityAssociation.getPrincipal());
            

            to the server side implementation of my WS I do get the following log:

            2008-01-15 09:19:37,135 INFO [STDOUT] Getting principal from SecurityAssociation: kermit

            I would much rather use the standard mechanisms to obtain the principal info.


            • 3. Re: WSSE UsernameToken without HTTP basic auth?
              Mikael Larsson Newbie

              One note on the server side implementation of the WS:
              It is not an SLSB. I've used wsconsume and generated java files based on an existing WSDL file.

              I think that the execution ends up in the org.jboss.ws.extensions.security.ReceiveUsernameOperation class where the following lines are called:

              securityAdaptor.setPrincipal(new SimplePrincipal(user.getUsername()));
              securityAdaptor.setCredential(user.getPassword());


              Also, printing the Principal class gives:
              System.out.println("Getting principal class from SecurityAssociation: " + org.jboss.security.SecurityAssociation.getPrincipal().getClass().getName());
               --
              2008-01-15 14:49:57,734 INFO [STDOUT] Getting principal class from SecurityAssociation: org.jboss.ws.extensions.security.SimplePrincipal


              So... I've probably done something bad causing the application not to be registered with the JBossWS security domain or ?
              I do have <security-domain>java:/jaas/JBossWS</security-domain> in my jboss-web.xml

              I also have a jboss-wsse-server.xml file with the following contents:
              <?xml version="1.0" encoding="UTF-8"?>
              <jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.jboss.com/ws-security/config http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
              </jboss-ws-security>


              I've tried adding:
              <config>
               <username/>
               </config>

              But that did not make it better...

              What am I doing wrong?

              • 4. Re: WSSE UsernameToken without HTTP basic auth?
                Magesh Bojan Master

                JBoss webservices stack supports variety of endpoint deployment models:

                1. Simple JDK5 POJOs that are wrapped in a war file.
                2. EJB3 endpoints that are wrapped in a ejb jar file.
                3. Servlet endpoints wrapped in a war file.
                4. EJB2.1 endpoints using jar archive.


                Now for the Servlet/POJO model endpoints the endpoints are secured for authentication using JAAS or any other means that is supported by Servlet specification. For EJB style endpoints the EJBs are secured for authentication according to the EJB2.1 or EJB3 specifications. Please read our UserGuide for more information

                http://jbws.dyndns.org/mediawiki/index.php?title=JAX-WS_User_Guide#WS-Security

                Basically Security on endpoints is done as above, and HTTP is a transport mechanism used to send your messages. It can be HTTP/HTTPS or whatever methodology you want to choose as. When you use HTTP the SOAP message is wrapped or sent across the wire using HTTP protocol.

                By default when you send in the credentials:

                reqContext.put(BindingProvider.USERNAME_PROPERTY, "kermit");
                reqContext.put(BindingProvider.PASSWORD_PROPERTY, "thefrog");
                


                the default authorization mechanism that is set from the client is AUTH_TYPE_BASIC. See org.jboss.ws.core.client.RemotingConnectionImpl

                 // Get authentication type, default to BASIC authetication
                 String authType = (String)callProps.get(StubExt.PROPERTY_AUTH_TYPE);
                 if (authType == null)
                 authType = StubExt.PROPERTY_AUTH_TYPE_BASIC;
                


                When it reaches the service endpoint in the server, this message is unwrapped from the HTTP or whatever protocol/transport mechanism you used and then supplied to the service endpoint after re-creating the SOAPMessage. The Username token sent in the SOAP Message is the one used by the endpoint server/stack to authenticate the user who is performing this request. This is called MessageLevel Security as defined by UsernameToken profile. If you see, Servlet endpoints can be configured with only basic or digest as per the specs of their deployment model. So setting AUTH_TYPE_WSSE is not and will not be applicable to the servlet deployment model unless you write your own customized implementation for it.

                • 5. Re: WSSE UsernameToken without HTTP basic auth?
                  Mikael Larsson Newbie

                  Hi!

                  Thank you for the answer.
                  I have more questions though:

                  You are saying that:
                  "The Username token sent in the SOAP Message is the one used by the endpoint server/stack to authenticate the user who is performing this request."
                  Good, this is what I want, I want the user to be authenticated based on the UsernameToken.

                  However,I do not want to secure the servlet as such on http level. I do not want to use http basic authentication in addition to the UsernameToken.

                  As you can see in my previous posts I've been trying to set this up without successes. As soon as I remove the HTTP basic auth authentication I can no lnger retrieve the principal information using the standard API. I can see that the WSEE data is parsed because I can get the principal info using: org.jboss.security.SecurityAssociation.getPrincipal() but no authentication seems to take place.

                  Do you have any examples of UsernameToken without http basic auth where the user is athenticated based on the UsernameToken data? The example under /src/test/java/org/jboss/test/ws/jaxws/samples/wssecurity will be using http basic auth since it is default. Will this example work if http basic auth is removed ???

                  There implementation of the server is simply doing

                  Principal principal = wsCtx.getUserPrincipal();
                   log.info("getUsernameToken: " + principal);
                   return principal.toString();
                  
                  But will this really work if http basic auth is not enabled?

                  • 6. Re: WSSE UsernameToken without HTTP basic auth?
                    Alessio Soldano Master

                    I did a bit of tests and investigation..

                    "mageshbk@jboss.com" wrote:
                    The Username token sent in the SOAP Message is the one used by the endpoint server/stack to authenticate the user who is performing this request. This is called MessageLevel Security as defined by UsernameToken profile. If you see, Servlet endpoints can be configured with only basic or digest as per the specs of their deployment model. So setting AUTH_TYPE_WSSE is not and will not be applicable to the servlet deployment model unless you write your own customized implementation for it.


                    mikaeljl, in other words this means you can easily and successfully use the wsse username token profile without basic authentication through EJB3 endpoints.
                    I did this way:
                    @WebService(
                     wsdlLocation = "META-INF/wsdl/WsSecurity10.wsdl",
                     serviceName = "PingService10",
                     name = "IPingService",
                     targetNamespace = "http://InteropBaseAddress/interop",
                     endpointInterface = "org.jboss.test.ws.interop.nov2007.wsse.IPingService",
                     portName = "UserNameOverTransport_IPingService")
                    @EndpointConfig(configName = "Standard WSSecurity Endpoint")
                    @Stateless
                    @SecurityDomain("JBossWS")
                    @WebContext(contextRoot="/nov2007/wsseUsernameTokenHTTPS", urlPattern="/endpoint")
                    public class UsernameTokenHTTPSTestService extends TestService implements IPingService {
                    ...
                    }
                    

                    please note, no authMethod and transportGuarantee in the @WebContext.

                    On the client side:
                    ((BindingProvider)port).getRequestContext().put(StubExt.PROPERTY_AUTH_TYPE, StubExt.PROPERTY_AUTH_TYPE_WSSE);
                    ((BindingProvider)port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "kermit");
                    ((BindingProvider)port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "thefrog");
                    

                    This prevents the stack from using the basic auth and set the user/pwd in the context so that they can be put in the Username token. The principal is set and can be retrieved. Using the wrong user/pwd couple causes an authentication failure due to a javax.ejb.EJBAccessException.
                    Of course you need to set client wsse config the right way:
                    <jboss-ws-security xmlns="http://www.jboss.com/ws-security/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                     xsi:schemaLocation="http://www.jboss.com/ws-security/config http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
                     <config>
                     <username/>
                     <timestamp ttl="300"/>
                     </config>
                    </jboss-ws-security>
                    


                    • 7. Re: WSSE UsernameToken without HTTP basic auth?
                      Mikael Larsson Newbie

                      Hi Alessio!

                      Thank you for investigating this, much appreciated !

                      Unfortunately I do not have an EJB3 endpoint, I'm starting with a WSDL file so I have a POJO endpoint (using wsconsume to do wsdl -2-java).

                      I do not think WSSE UsernameToken authentication is working for POJO endpoints without enabling some form of http level authentication like basic auth? Can you confirm this?

                      I will look into converting my pojo endpoints into ejb3 endpoints because that seems to be the easiest solution right now. I guess it is just a matter of adding @Stateless to my pojo class and packaging/deploying the thing as a jar instead of a war... kind of...

                      Are there any plans for supporting WSSE UsernameToken based authentication for POJO endpoints (without the requirement of any additional http level authentication?

                      /MIkael

                      • 8. Re: WSSE UsernameToken without HTTP basic auth?
                        Alessio Soldano Master

                         

                        "mikaeljl" wrote:
                        I do not think WSSE UsernameToken authentication is working for POJO endpoints without enabling some form of http level authentication like basic auth? Can you confirm this?

                        There's the issue of the principal you described in the previous posts. Btw this also is related to what we're discussing here: http://jira.jboss.org/jira/browse/JBWS-1136

                        I will look into converting my pojo endpoints into ejb3 endpoints because that seems to be the easiest solution right now. I guess it is just a matter of adding @Stateless to my pojo class and packaging/deploying the thing as a jar instead of a war... kind of...

                        Almost yes, I shouldn't be difficult.

                        Are there any plans for supporting WSSE UsernameToken based authentication for POJO endpoints (without the requirement of any additional http level authentication?

                        I don't have a reliable answer for this, sorry.

                        • 9. Re: WSSE UsernameToken without HTTP basic auth?
                          Alessio Soldano Master

                           

                          "alessio.soldano@jboss.com" wrote:
                          "mikaeljl" wrote:
                          Are there any plans for supporting WSSE UsernameToken based authentication for POJO endpoints (without the requirement of any additional http level authentication?

                          I don't have a reliable answer for this, sorry.


                          http://jira.jboss.org/jira/browse/JBWS-1999

                          • 10. Re: WSSE UsernameToken without HTTP basic auth?
                            Mikael Larsson Newbie

                            Ah, that looks useful.
                            Thanks for the update!
                            /Mikael

                            • 11. Re: WSSE UsernameToken without HTTP basic auth?
                              Mikael Larsson Newbie

                              Ah, that looks useful.
                              Thanks for the update!
                              /Mikael

                              • 12. Re: WSSE UsernameToken without HTTP basic auth?
                                Alessio Soldano Master

                                 

                                "alessio.soldano@jboss.com" wrote:
                                I did a bit of tests and investigation..

                                "mageshbk@jboss.com" wrote:
                                The Username token sent in the SOAP Message is the one used by the endpoint server/stack to authenticate the user who is performing this request. This is called MessageLevel Security as defined by UsernameToken profile. If you see, Servlet endpoints can be configured with only basic or digest as per the specs of their deployment model. So setting AUTH_TYPE_WSSE is not and will not be applicable to the servlet deployment model unless you write your own customized implementation for it.


                                mikaeljl, in other words this means you can easily and successfully use the wsse username token profile without basic authentication through EJB3 endpoints.
                                I did this way:
                                
                                @WebService(
                                 wsdlLocation = "META-INF/wsdl/WsSecurity10.wsdl",
                                 serviceName = "PingService10",
                                 name = "IPingService",
                                 targetNamespace = "http://InteropBaseAddress/interop",
                                 endpointInterface = "org.jboss.test.ws.interop.nov2007.wsse.IPingService",
                                 portName = "UserNameOverTransport_IPingService")
                                @EndpointConfig(configName = "Standard WSSecurity Endpoint")
                                @Stateless
                                @SecurityDomain("JBossWS")
                                @WebContext(contextRoot="/nov2007/wsseUsernameTokenHTTPS", urlPattern="/endpoint")
                                public class UsernameTokenHTTPSTestService extends TestService implements IPingService {
                                ...
                                }
                                

                                please note, no authMethod and transportGuarantee in the @WebContext.

                                On the client side:
                                ((BindingProvider)port).getRequestContext().put(StubExt.PROPERTY_AUTH_TYPE, StubExt.PROPERTY_AUTH_TYPE_WSSE);
                                ((BindingProvider)port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "kermit");
                                ((BindingProvider)port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "thefrog");
                                

                                This prevents the stack from using the basic auth and set the user/pwd in the context so that they can be put in the Username token. The principal is set and can be retrieved. Using the wrong user/pwd couple causes an authentication failure due to a javax.ejb.EJBAccessException.
                                Of course you need to set client wsse config the right way:
                                
                                <jboss-ws-security xmlns="http://www.jboss.com/ws-security/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                 xsi:schemaLocation="http://www.jboss.com/ws-security/config http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
                                 <config>
                                 <username/>
                                 <timestamp ttl="300"/>
                                 </config>
                                </jboss-ws-security>
                                


                                Btw I've just added a use case test for the JBWS-1991 issue; it basically use the above described solution.

                                • 13. Re: WSSE UsernameToken without HTTP basic auth?
                                  Mikael Larsson Newbie

                                  For anyone watching/tracking this thread:

                                  Looks like JBWS-1999 has been implemented and is now scheduled for the 3.0.6 release.
                                  Docs updated at:
                                  http://jbossws.jboss.org/mediawiki/index.php?title=WS-Security_options
                                  look for POJO endpoint.

                                  This seems to be exactly what I was looking for when I initially started this thread, looking forward to try this out!

                                  • 14. Re: WSSE UsernameToken without HTTP basic auth?
                                    Alessio Soldano Master

                                    Yes, that has just been implemented on trunk and will be included in the next release. Getting the sources from svn, giving it a try and providing feedback now could be usefu if you have some spare time. Thanks!

                                    1 2 Previous Next