+

Search Tips   |   Advanced Search

(V8502)

Generating and consuming a dynamic X.509 token using a stacked JAAS login module

We can use the GenericSecurityTokenFactory SPIs to create X.509 tokens for use by the WS-Security runtime environment. These security tokens can be used for, but are not limited to, WSSAPIs and JAAS login modules.

When a GenericSecurityTokenFactory SPI is used to create an X.509 token that does not contain XML, the token can only be emitted by the X.509 generator and consumed by the X.509 consumer. Therefore, an X.509 token is considered a simple token, which is only intended for use by its respective token-specific generator or consumer. An X.509 token cannot be emitted by the GenericSecurityTokenLoginModule.

The GenericSecurityTokenFactory provides several SPIs that we can use to create X.509 tokens that can be emitted with the X509GenerateLoginModule or consumed by the X509ConsumeLoginModule. X.509 tokens created using a GenericSecurityTokenFactory SPI contain public and/or private keys that can be used to sign or encrypt an outbound message or decrypt or verify the signature of an inbound message.

We might want to use this type of token:

After an X.509 token is created, the public and private key in the token cannot be modified. Therefore, you must determine the type of token to create, and then issue commands similar to the ones specified in the following steps to create the token and JAAS login module.

  1. Create a simple X.509 token

    Decide the type of simple X.509 token to create, and issue commands similar to one of the following series of commands.

    1. Create a simple X.509 token with a public certificate.
      import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
      import com.ibm.websphere.wssecurity.wssapi.token.X509Token;
      import java.security.cert.X509Certificate;
      ...
       X509Certificate publicCert = null;
       GenericSecurityTokenFactory factory = GenericSecurityTokenFactory.getInstance();
       //implement code to obtain the public certificate  X509Token x509 = factory.getSimpleX509PublicToken(publicCert);

    2. Create a simple X.509 token with a private and optional public key.
      import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
      import com.ibm.websphere.wssecurity.wssapi.token.X509Token;
      import java.security.Key;
      import java.security.cert.X509Certificate;
      ...
       Key privateKey = null;
      X509Certificate publicCert = null;
       GenericSecurityTokenFactory factory = GenericSecurityTokenFactory.getInstance();
       //implement code to obtain the private key //optionally implement code to obtain the public certificate  X509Token x509 = null;
      try {
       x509 = factory.getSimpleX509PrivateToken(publicCert , privateKey);
      } catch (WSSException ex) {
       //throws an exception if privateKey is null }

  2. Create a JAAS login module that can be stacked on top of X509GenerateLoginModule or X509ConsumeLoginModule.
    package test.tokens;
    import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
    import com.ibm.websphere.wssecurity.wssapi.WSSUtilFactory;
    import java.util.Map;
     import javax.security.auth.Subject;
    import javax.security.auth.callback.CallbackHandler;
    import javax.security.auth.login.LoginException;
    import javax.security.auth.spi.LoginModule;
     import com.ibm.websphere.wssecurity.wssapi.token.X509Token;
    import java.security.KeyStore;
    import java.security.cert.X509Certificate;
     public class MyX509LoginModule implements LoginModule {
      //For the sake of readability, this login module does not   //protect against all NPE's
       private Map _sharedState;
      private Map _options;
      private CallbackHandler _handler;
       public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
         this._handler = callbackHandler;
        this._sharedState = sharedState;
        this._options = options;     }
       public boolean login() throws LoginException {
         GenericSecurityTokenFactory factory = null;
        WSSUtilFactory utilFactory = null;
        try {
          factory = GenericSecurityTokenFactory.getInstance();
          utilFactory = WSSUtilFactory.getInstance();
        } catch (Exception e) {
          throw new LoginException(e.toString());
        }
         X509Token x509 = null;
        try {
          x509 = getX509Token(factory, utilFactory);
        } catch (Exception e) {
          throw new LoginException("Exception: "+e.toString());
        }
         //if generating (signing/encrypting):
        factory.putGeneratorTokenToSharedState(this._sharedState, x509);
         //if consuming (decrypting/signature verification):
        factory.putConsumerTokenToSharedState(this._sharedState, x509);
         return true;
      }
       public X509Token getX509Token (GenericSecurityTokenFactory factory,       WSSUtilFactory utilFactory) throws Exception{
        //This sample uses a sample keystore     final String KEYSTORE = "c:/WebSphere/AppServer/profiles/AppSrv01/etc/ws-security/samples/dsig-sender.ks";
        final String KEYSTORE_PASS = "client";
        final String ALIAS = "soaprequester";
        final String ALIAS_PASS = "client";
        final String KEYSTORE_TYPE = "jks";
         X509Certificate publicKey = null;
        java.security.Key privateKey = null;
        java.security.cert.Certificate cert = null;
        X509Token x509 = null;
         //if we need to get the inbound token so that we can do some processing      //to determine which certificate to obtain, get then OMElement for the inbound token     Map wssContext = utilFactory.GetWSSContext(this._handler);
        org.apache.axiom.om.OMElement element = utilFactory.getProcessingElement(wssContext);
         //Open the keystore     java.security.KeyStore keystore = utilFactory.getKeyStore(KEYSTORE_TYPE, KEYSTORE, KEYSTORE_PASS.toCharArray());
         //Get the entry from the keystore     KeyStore.PasswordProtection pwdProtection = null;
        if (ALIAS_PASS != null) {
          pwdProtection = new KeyStore.PasswordProtection(ALIAS_PASS.toCharArray());
        }
        KeyStore.Entry entry = keystore.getEntry(ALIAS, pwdProtection);
         //Get the public and/or private key from the entry
        if (entry instanceof KeyStore.PrivateKeyEntry) {
          //entry is a private key       KeyStore.PrivateKeyEntry pkentry = (KeyStore.PrivateKeyEntry)entry;
          cert = pkentry.getCertificate();
          privateKey = pkentry.getPrivateKey();
        } else if (entry instanceof KeyStore.TrustedCertificateEntry) {
          //entry is a public key       KeyStore.TrustedCertificateEntry tcentry = (KeyStore.TrustedCertificateEntry)entry;
          cert = tcentry.getTrustedCertificate();                }
        if ((cert != null) && (cert instanceof X509Certificate)) {
          publicKey = (X509Certificate)cert;
        } else {
          throw new LoginException("Certificate is not X509Certificate");
        }
         x509 = factory.getSimpleX509Token(publicKey, privateKey);
         if (x509 == null) {
          throw new LoginException("X509Token is null");
        }
         return x509;
      }
     }

  3. Create a JAAS login configuration.

    This step assumes that you are stacking on X509GenerateLoginModule to generate a token. To stack on X509ConsumeLoginModule to consume a token, you must adjust the steps to accommodate this variation.

    1. In the console, go to Security > Global security > Authentication, go to Java Authentication and Authorization Service > System logins.

    2. Click New, and under Alias, enter test.generate.x509.

    3. Under JAAS login modules, click New, and under Module class name, enter test.tokens.MyX509LoginModule. Select Use login module proxy, and click OK.

    4. Click New, and under Module class name, enter com.ibm.ws.wssecurity.wssapi.token.impl.X509GenerateLoginModule. Click OK.

    5. Click JAAS - System logins in the breadcrumbs to return to the JAAS system logins page.

  4. Configure the X.509 token generator to use the new JAAS configuration.

    This step assumes that you are stacking on X509GenerateLoginModule to generate a token. To stack on X509ConsumeLoginModule to consume a token, you must adjust the steps to accommodate this variation.

    1. In the console, open the bindings configuration to change.

    2. Select WS-Security > Authentication and protection > Authentication tokens, select the outbound X.509 token to change.

    3. Under JAAS login, select test.generate.x509.

    4. Click OK, then Save.

  5. Restart the application server to apply the JAAS configuration changes.

  6. Test the service.


Related tasks

  • Create custom security tokens for Web services security using the GenericSecurityTokenFactory SPIs