Generación y consumo de señales SAML utilizando módulos de inicio de sesión JAAS apilados

Puede utilizar las API GenericSecurityTokenFactory para pasar una señal SAML que ha creado para los módulos SAMLGenerateLoginModule o GenericIssuedTokenGenerateLoginModule. También puede utilizar estas API para obtener señales SAML que los módulos SAMLConsumeLoginModule o GenericIssuedTokenConsumeLoginModule consumen.

Antes de empezar

Debe tener un conjunto de aplicaciones de cliente y proveedor de servicio JAX-WS en funcionamiento donde añadir las clases de módulo de inicio de sesión JAAS nuevas.

Acerca de esta tarea

Esta tarea genera una señal de transporte de SAML 1.1, pero puede ser modificada fácilmente para utilizar sender-vouches y cualquier versión de SAML soportada por el entorno de ejecución.

Aunque puede apilar un módulo de inicio de sesión bajo SAMLGenerateLoginModule para inspeccionar una señal SAML creada por esa clase, no puede modificar la señal SAML obtenida de este modo a menos que la señal no contenga una firma digital. Si modifica una señal SAML que contiene una firma digital, el XML para la señal SAML se ajustará para las actualizaciones; pero, puesto que la señal se ha firmado antes de la actualización, la validación de la firma fallará en el receptor.

Esta tarea genera una señal de portador SAML 1,1, pero puede utilizar cualquier versión de SAML y el tipo que esté soportado por el entorno de ejecución. Para obtener más información sobre la creación y modificación de señales SAML con las API GenericSecurityTokenFactory, consulte Desarrollo de aplicaciones SAML. Para obtener más información sobre cómo colocar la señal en el contexto de la solicitud del cliente en lugar de utilizar un módulo de inicio de sesión JAAS, consulte la información sobre las constantes com.ibm.wsspi.wssecurity.token.tokenHolder y com.ibm.wsspi.wssecurity.token.enableCaptureTokenContext en com.ibm.wsspi.wssecurity.core.Constants.

Debido a que el ejemplo de generador no se puede modificar fácilmente para utilizar el poseedor de clave, al final de esta tarea se proporciona un ejemplo del método createSamlToken() que es específico para el poseedor de clave de SAML.

Procedimiento

  1. Cree el módulo de inicio de sesión JAAS de generador siguiente y haga que esté disponible para el código de aplicación.
    package test.tokens;
    
    import java.util.ArrayList;
    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.GenericSecurityTokenFactory;
    import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
    import com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory;
    import com.ibm.wsspi.wssecurity.saml.config.CredentialConfig;
    import com.ibm.wsspi.wssecurity.saml.config.ProviderConfig;
    import com.ibm.wsspi.wssecurity.saml.config.RequesterConfig;
    import com.ibm.wsspi.wssecurity.saml.data.SAMLAttribute;
    import com.ibm.wsspi.wssecurity.core.config.KeyInformationConfig;
    import com.ibm.wsspi.wssecurity.core.config.KeyStoreConfig;
    import com.ibm.websphere.wssecurity.wssapi.WSSUtilFactory;
    
    public class MySamlGenerator implements LoginModule {
    
      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;
                 try {
          factory = GenericSecurityTokenFactory.getInstance();
        } catch(Exception e) {
          throw new LoginException(e.toString());
        }
        if (factory == null) {
          throw new LoginException("GenericSecurityTokenFactory.getInstance() returned null");
        }
        SAMLToken myToken = null;
                 try {
          myToken = createSamlToken();
        } catch(Exception e) {
          throw new LoginException(e.toString());
        }
        if (myToken == null) {
          throw new LoginException("myToken is null");
        }
    
        //Coloque la señal en una lista en el estado compartido donde estará disponible para ser utilizada por los
        //módulos de inicio de sesión apilados
        factory.putGeneratorTokenToSharedState(_sharedState, myToken);
    
        return true;
      }
    
      private SAMLToken createSamlToken() throws Exception {
        //Ejemplo de portador SAML 
        SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token11);
        RequesterConfig reqData = samlFactory.newBearerTokenGenerateConfig();
        reqData.setAuthenticationMethod("Password"); //Método de autenticación para la Assertion
    
        ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");
    
        CredentialConfig cred = samlFactory.newCredentialConfig ();
        cred.setRequesterNameID("Alice");   // SAML NameIdentifier
    	  
        //Añadir algunos atributos SAML:	
        SAMLAttribute attribute = new SAMLAttribute
          ("email", new String[] {"joe@websphere"},null, "WebSphere", "email", "joe");
        ArrayList<SAMLAttribute> al = new ArrayList<SAMLAttribute>();
        al.add(attribute);
        attribute = new SAMLAttribute("Membership", 
          new String[] {"Super users", "My team"}, null, null, null, null  );
        al.add(attribute);
        cred.setSAMLAttributes(al);
    
        SAMLToken samlToken = samlFactory.newSAMLToken(cred, reqData, samlIssuerCfg);
    
        return samlToken;
      }
    
      public boolean logout() throws LoginException {
        return false;
      } 
      public boolean abort() throws LoginException {
        return false;
      }
      public boolean commit() throws LoginException {
        return true;
      }
    }
  2. Cree el módulo de inicio de sesión JAAS de consumidor siguiente y póngalo a disposición para el código de aplicación.
    package test.tokens;
    
    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 javax.xml.namespace.QName;
    import com.ibm.websphere.wssecurity.wssapi.token.GenericSecurityTokenFactory;
    import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
    import com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory;
    import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
    
    public class MySamlConsumer implements LoginModule {
    
      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;
                 try {
          factory = GenericSecurityTokenFactory.getInstance();
        } catch(Exception e) {
          throw new LoginException(e.toString());
        }
        if (factory == null) {
          throw new LoginException("GenericSecurityTokenFactory.getInstance() returned null");
        }
        //Obtener la señal consumida por GenericIssuedConsumeLoginModule
        SecurityToken myToken = factory.getConsumerTokenFromSharedState(_sharedState, new QName(SAMLTokenFactory.WssSamlV11Token11));
        if (myToken == null) {
            throw new LoginException("myToken is null");
        }
        if (myToken instanceof SAMLToken) {
        	//Examinar la señal SAML con las API SAML
        	SAMLToken samlToken = (SAMLToken)myToken;
        	String id = samlToken.getSamlID();
        	String subjectDns = samlToken.getSubjectDNS();
        	//...    	
        } else {
        	throw new LoginException("Did not receive a SAML token");
        }
        return true;
      }
      public boolean logout() throws LoginException {
        return false;
      } 
      public boolean abort() throws LoginException {
        return false;
      }
      public boolean commit() throws LoginException {
        return true;
      }
    }
  3. Crear una configuración de inicio de sesión JAAS.
    1. En la consola administrativa, vaya a Seguridad > Seguridad global.
    2. En autenticación, vaya a Java Authentication and Authorization Service > Inicios de sesión en el sistema.
    3. Cree el generador de señales SAML.
      1. Pulse Nuevo y, en Alias, especifique test.generate.saml.
      2. En Módulos de inicio de sesión JAAS, pulse Nuevo y, en Nombre de clase de módulo, especifique test.tokens.MySamlGenerator. Seleccione Utilizar proxy de módulo de inicio de sesión y pulse Aceptar.
      3. Pulse Nuevo y, en Nombre de clase de módulo, especifique com.ibm.ws.wssecurity.wssapi.token.impl.SAMLGenerateLoginModule. Pulse Aceptar.
    4. Cree el consumidor de señal SAML.
      1. Pulse JAAS - Inicios de sesión de sistema en los rastros de navegación para volver a la página de inicios de sesión del sistema JAAS.
      2. Pulse Nuevo y, en Alias, especifique test.consume.saml.
      3. En Módulos de inicio de sesión JAAS, pulse Nuevo y, en Nombre de clase de módulo, especifique com.ibm.ws.wssecurity.wssapi.token.impl.SAMLConsumeLoginModule. Seleccione Utilizar proxy de módulo de inicio de sesión y pulse Aceptar.
      4. Pulse Guardar.
  4. Configure el generador de señales SAML que debe utilizar la nueva configuración de inicio de sesión JAAS.
    1. En la consola administrativa, abra la configuración de enlaces que desea cambiar.
    2. Seleccione WS-Security > Autenticación y protección.
    3. En Señales de autenticación, seleccione la señal SAML de salida que desee cambiar.
    4. En Inicio de sesión JAAS, seleccione test.generate.saml.
  5. Configure el consumidor de señal SAML que debe utilizar la nueva configuración de JAAS.
    1. En la consola administrativa, abra la configuración de enlaces que desea cambiar.
    2. Seleccione WS-Security > Autenticación y protección.
    3. En Señales de autenticación, seleccione la señal de entrada SAML que desea cambiar.
    4. En Inicio de sesión JAAS, seleccione test.consume.saml.
  6. Pulse Guardar.
  7. Reinicie el servidor de aplicaciones para aplicar los cambios de configuración JAAS.
  8. Pruebe el servicio.

Ejemplo

El ejemplo siguiente muestra el método createSamlToken() para crear una señal de poseedor de clave asimétrica para SAML 2.0.
private SAMLToken createSamlToken() throws Exception {
  SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV20Token11);

  RequesterConfig reqData =  samlFactory.newAsymmetricHolderOfKeyTokenGenerateConfig();
  reqData.setAuthenticationMethod("Password");  //Método de autenticación para aserción

  ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");

  CredentialConfig cred = samlFactory.newCredentialConfig ();
  cred.setRequesterNameID("Alice");   // SAML NameIdentifier

  // (Opcional) Si desea utilizar propiedades de almacén de claves y de clave distintas de lo que
  // está establecido en el archivo SAMLIssuerConfig.properties, inicialice la información de
  // almacén de claves, almacén de confianza y de alias en el objeto ProviderConfig.
  KeyInformationConfig kic = samlFactory.newKeyInformationConfig("private_key","keypass","CN=Private");

  KeyStoreConfig ksc = samlFactory.newKeyStoreConfig("jks","/keystores/myKeystore.ks","storepass");

  samlIssuerCfg.setKeyStoreConfig(ksc);    //almacén de claves que contiene la clave privada
  samlIssuerCfg.setTrustStoreConfig(ksc);  //almacén de claves que contiene la clave pública

  // Defina el alias del certificado público que debe existir en el almacén de confianza.
  // Este alias no debe necesitar una contraseña.
  reqData.setKeyAliasForRequester("public_cert");  

  SecurityToken samlToken = samlFactory.newSAMLToken(cred, reqData, samlIssuerCfg);     

  // Obtener la clave privada a partir del almacén de claves
  WSSUtilFactory wssufactory = WSSUtilFactory.getInstance();
  java.security.KeyStore ks = wssufactory.getKeyStore("jks","/keystores/myKeystore.ks",
                                                      "storepass".toCharArray());
  java.security.Key privateKey = ks.getKey("private_key", "keypass".toCharArray());

  // Añadir la clave privada a la señal para que la señal se pueda utilizar para firmar
  // elementos en un mensaje SOAP. ((com.ibm.ws.wssecurity.wssapi.token.impl.SecurityTokenImpl)samlToken).
  setKey(SecurityToken.SIGNING_KEY, privateKey);  ((com.ibm.ws.wssecurity.wssapi.token.impl.SecurityTokenImpl)samlToken).
  setKey(SecurityToken.DECRYPTING_KEY, privateKey);

  return samlToken;
}

Icon that indicates the type of topic Task topic



Timestamp icon Last updated: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twbs_gen_con_token_JAAS_mod
File name: twbs_gen_con_token_JAAS_mod.html