2 Replies Latest reply on May 3, 2012 2:19 PM by robert.d.ritchie

    Transition from JBoss 4.2.3.GA to 5.1.0.GA

    robert.d.ritchie

      I am currently working on transitioning a Seam 2.2.0 application that I work on from JBoss 4.2.3.GA to 5.1.0.GA (due to a short turnaround IA issue) and have ran into a problem with my secure SOAP web services.  The web services were secured using an LdapLoginModule and requiring a plain-text UsernameToken (was planning on going to a digest with the move to JBoss 5.1.0.GA).  This worked well in JBoss 4.2.3.GA, but my soapui test suites that validate that bad passwords are rejected all fail now in JBoss 5.1.0.GA.

       

      Doing some searching my initial path to correct was to change the @SecurityDomain annotation from org.jboss.annotation.security.SecurityDomain to org.jboss.ejb3.annotation.SecurityDomain per the guidance found here: https://community.jboss.org/thread/157593.

       

      After making that switch I recieved an IllegalStateException on startup, which also seems to be a common error in the JBoss 5.1.0 community.  The prescribed workarounds for this issue seemed to imply that you must annotate EVERY EJB in your application with the same security domain if you annotate any of them.  I attempted this solution annotating every EJB in my application with the security domain, however, JBoss still failed during startup due to the Seam EJB's missing the annotation.  At that point I felt that this was an unacheivable solution path with Seam applications (short of overriding every Seam EJB with install precedence and adding the annotation).

       

      Right now what I am "settling on" is creating my own request handler that does LDAP authentication and inserting that in the top of my handler chain for the endpoints that I want to be secure.

       

      Obviously I would prefer if there were a way to not do this in 5.1.0.GA by just using the configuration/pattern that worked so well in 4.2.3.GA.

       

      Has anyone solved this problem in JBoss 5.1.0.GA with a Seam 2.2.X application?

        • 1. Re: Transition from JBoss 4.2.3.GA to 5.1.0.GA
          robert.d.ritchie

          I have come up with a solution that I am happy with as it allows my service tier authentication authorization to take advantage of the identity-store I have defined for seam in components.xml.

           

          By inserting my own request handler in the handler chain, grabbing the username and password out of the soap header, and then looking up the Seam Identity component to perform the authentication I keep a decoupling from authentication method in my workaround (no specific tie to LDAP or DB or JCIFS auth) and only had to change one configuration file (standard-jaxws-endpoint-config.xml to insert my handler in the handler chain).  This also prevents me from having to duplicate my LDAP configuration in components.xml and login-config.xml.

           

          I am not sure if this solution will work beyond 5 as I have not worked with jbossws-cxf in 6.1.0.Final yet, but since we are not funded to make the transition to Java EE 6, JPA 2, arquillian for testing yet that will be factored in as a "migration risk" for future migration efforts.

           

          Here is my code if anyone else is interested in doing something like this:

           

          public class SeamUsernamePasswordWSSecurityHandlerServer extends WSSecurityHandlerServer {

           

              /** The log. */

              private Logger log = Logger.getLogger(SeamUsernamePasswordWSSecurityHandlerServer.class);

           

              /*

               * (non-Javadoc)

               *

               * @see org.jboss.ws.extensions.security.jaxws.WSSecurityHandler#

               * handleInboundSecurity(javax.xml.ws.handler.MessageContext)

               */

              @Override

              protected boolean handleInboundSecurity(MessageContext msgContext) {

                  try {

                      authenticate(((CommonMessageContext) msgContext));

                  } catch (SOAPException ex) {

                      // if recieving a SOAP exception during authenticate

                      // then fail fast

                      log.error("Cannot handle inbound ws-security", ex);

                      return false;

                  }

                  // otherwise let the underlying security handler

                  // attach the principle to the WebServiceContext

                  return super.handleInboundSecurity(msgContext);

              }

           

              /**

               * Authenticate.

               *

               * @param message the message

               * @param configuration the configuration

               * @throws SOAPException the sOAP exception

               * @throws org.jboss.ws.extensions.security.WSSecurityException

               */

              private void authenticate(CommonMessageContext msgContext) throws SOAPException {

                  EndpointMetaData epMetaData = ((CommonMessageContext)msgContext).getEndpointMetaData();

                  ServiceMetaData serviceMetaData = epMetaData.getServiceMetaData();

                  WSSecurityConfiguration configuration = serviceMetaData.getSecurityConfiguration();

                  SOAPHeader soapHeader = msgContext.getSOAPMessage().getSOAPHeader();

                  QName secQName = new QName(Constants.WSSE_NS, "Security");

                  Element secHeaderElement = (soapHeader != null) ? Util.findElement(

                          soapHeader, secQName) : null;

                  if(secHeaderElement != null) {

                      try {

                          // create a SecurityHeader element

                          SecurityStore securityStore = new SecurityStore(configuration.getKeyStoreURL(), configuration.getKeyStoreType(), configuration.getKeyStorePassword(),

                                                 configuration.getKeyPasswords(), configuration.getTrustStoreURL(), configuration.getTrustStoreType(), configuration.getTrustStorePassword());

                          SecurityHeader header = new SecurityHeader(secHeaderElement, securityStore);

                          String username = null;

                          String password = null;

                          UsernameToken usernameToken = getUsernameToken(header);

                          if(usernameToken != null) {

                              username = usernameToken.getUsername();

                              password = usernameToken.getPassword();

                          }

                          // get the identity component from Seam

                          Identity identity = (Identity) Component.getInstance("org.jboss.seam.security.identity");

                          identity.getCredentials().setUsername(username);

                          identity.getCredentials().setPassword(password);

                          // authenticate the credentials

                          identity.authenticate();

                      } catch (Exception e) {

                          throw createFault(new WSSecurityException(e.getLocalizedMessage()));

                      }

                  } else {

                      // if no security header, fail fast

                      throw createFault(new InvalidSecurityHeaderException("This service requires wsse:Security, which is missing."));

                  }

              }

             

              /**

               * Gets the username token.

               *

               * @param header the header

               * @return the username token

               */

              private UsernameToken getUsernameToken(SecurityHeader header) {

                  for(Token token : header.getTokens()) {

                      if(token instanceof UsernameToken) {

                          return (UsernameToken) token;

                      }

                  }

                  // no username token found

                  return null;

              }

           

              /**

               * Creates the fault.

               *

               * @param e the e

               * @return the common soap fault exception

               */

              private CommonSOAPFaultException createFault(WSSecurityException e) {

                  return new CommonSOAPFaultException(e.getFaultCode(), e.getFaultString());

              }

          1 of 1 people found this helpful
          • 2. Re: Transition from JBoss 4.2.3.GA to 5.1.0.GA
            robert.d.ritchie

            related JIRA's:

             

            https://issues.jboss.org/browse/JBAS-7037 - refers to issue where EJB security is not being applied on a per-EJB basis (just for the whole application)

             

            https://issues.jboss.org/browse/JBWS-2535 - refers to an issue if you attempt to use the new suggested JBoss 5.x @SecurityDomain annotation on some EJB’s in your application it breaks