Génération et consommation de jetons SAML à l'aide de modules de connexion JAAS empilés

Vous pouvez utiliser les API GenericSecurityTokenFactory pour transmettre un jeton SAML que vous avez créé aux modules SAMLGenerateLoginModule ou GenericIssuedTokenGenerateLoginModule. Vous pouvez également utiliser ces API pour obtenir des jetons SAML qui sont consommés par les modules SAMLConsumeLoginModule ou GenericIssuedTokenConsumeLoginModule.

Avant de commencer

Vous devez disposer d'un ensemble d'applications client fournisseur JAX-WS auxquelles vous ajoutez de nouvelles classes de module de connexion JAAS.

Pourquoi et quand exécuter cette tâche

Cette tâche génère un jeton bearer (porteur) SAML 1.1, mais il peut facilement être modifié pour utiliser des $$$sender-vouches et toute version SAML prise en charge par l'environnement d'exécution.

Même si vous pouvez empiler un module de connexion sous SAMLGenerateLoginModule pour inspecter un jeton SAML qui a été créé pour cette classe, vous ne pouvez pas modifier le jeton SAML obtenu ainsi, sauf si le jeton ne contient pas de signature numérique. Si vous modifiez un jeton SAML qui contient une signature numérique, le code XML pour le jeton SAML sera ajusté pour vos mises à jour. Par contre, comme le jeton a été signé avant la mise à jour, la validation de la signature échouera sur le récepteur.

Cette tâche génère un jeton bearer (porteur) SAML 1.1, mais vous pouvez utiliser toute version et tout type pris en charge par l'environnement d'exécution. Pour plus d'informations sur la création et la modification de jetons SAML avec les API GenericSecurityTokenFactory API, voir Développement d'applications SAML. Pour plus d'informations sur comment placer le jeton sur le contexte de demande du client au lieu d'utiliser un module de connexion JAAS, reportez-vous aux constantes com.ibm.wsspi.wssecurity.token.tokenHolder et com.ibm.wsspi.wssecurity.token.enableCaptureTokenContext dans com.ibm.wsspi.wssecurity.core.Constants.

Dans la mesure où un exemple de générateur n'est pas facilement modifiable pour utiliser un jeton holder-of-key, un exemple de méthode createSamlToken() spécifique au jeton SAML holder-of-key est fourni à la fin de cette tâche.

Procédure

  1. Créez le module de connexion JAAS générateur suivant et rendez-le accessible au code d'application.
    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");
        }
    
        //Placer le jeton dans une liste d'état partagé où il sera accessible
        //aux modules de connexion empilés
        factory.putGeneratorTokenToSharedState(_sharedState, myToken);
    
        return true;
      }
    
      private SAMLToken createSamlToken() throws Exception {
        //exemple de bearer SAML 
        SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token11);
        RequesterConfig reqData = samlFactory.newBearerTokenGenerateConfig();
        reqData.setAuthenticationMethod("Password"); //Méthode d'authentification de l'assertion
    
        ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");
    
        CredentialConfig cred = samlFactory.newCredentialConfig ();
        cred.setRequesterNameID("Alice");   // NameIdentifier SAML
    	  
        //Ajouter des attributs 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", "Mon équipe"}, 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. Créez le module de connexion JAAS consommateur suivant et rendez-le accessible au code d'application.
    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");
        }
        //Obtenir le jeton qui doit être consommé par le module de connexion GenericIssuedConsumeLoginModule
        SecurityToken myToken = factory.getConsumerTokenFromSharedState(_sharedState, new QName(SAMLTokenFactory.WssSamlV11Token11));
        if (myToken == null) {
            throw new LoginException("myToken is null");
        }
        if (myToken instanceof SAMLToken) {
        	//Examiner le jeton SAML avec les API SAML
        	SAMLToken samlToken = (SAMLToken)myToken;
        	String id = samlToken.getSamlID();
        	String subjectDns = samlToken.getSubjectDNS();
        	//...    	
        } else {
        	throw new LoginException("Aucun jeton SAML reçu");
        }
        return true;
      }
      public boolean logout() throws LoginException {
        return false;
      } 
      public boolean abort() throws LoginException {
        return false;
      }
      public boolean commit() throws LoginException {
        return true;
      }
    }
  3. Créez une configuration de connexion JAAS.
    1. Dans la console d'administration, accédez à Sécurité > Sécurité globale.
    2. Sous Authentification, accédez à Service d'authentification et d'autorisation Java > Connexions au système.
    3. Créez le générateur de jeton SAML.
      1. Cliquez sur Nouveau et, sous Alias, entrez test.generate.saml.
      2. Sous Modules de connexion JAAS, cliquez sur Nouveau et, sous Nom de la classe du module, entrez test.tokens.MySamlGenerator. Sélectionnez Utiliser le proxy de module de connexion et cliquez sur OK.
      3. Cliquez sur Nouveau et, sous Nom de la classe du module, entrez com.ibm.ws.wssecurity.wssapi.token.impl.SAMLGenerateLoginModule. Cliquez sur OK.
    4. Créez le consommateur de jeton SAML.
      1. Cliquez sur JAAS - Connexions de système dans les éléments de navigation pour revenir à la page de connexions système JAAS.
      2. Cliquez sur Nouveau et, sous Alias, entrez test.consume.saml.
      3. Sous Modules de connexion JAAS, cliquez sur Nouveau et, sous Nom de la classe du module, entrez com.ibm.ws.wssecurity.wssapi.token.impl.SAMLConsumeLoginModule. Sélectionnez Utiliser le proxy de module de connexion et cliquez sur OK.
      4. Cliquez sur Sauvegarder.
  4. Configurez le générateur de jetons SAML pour qu'il utilise la nouvelle configuration de connexion JAAS.
    1. Dans la console d'administration, ouvrez la configuration de liaisons à modifier.
    2. Sélectionnez WS-Security > Authentification et protection.
    3. Sous Jetons d'authentification, sélectionnez le jeton sortant SAML à modifier.
    4. Sous Connexion JAAS, sélectionnez test.generate.saml.
  5. Configurez le consommateur de jeton SAML pour qu'il utilise la nouvelle configuration de connexion JAAS.
    1. Dans la console d'administration, ouvrez la configuration de liaisons à modifier.
    2. Sélectionnez WS-Security > Authentification et protection.
    3. Sous Jetons d'authentification, sélectionnez le jeton entrant SAML à modifier.
    4. Sous Connexion JAAS, sélectionnez test.consume.saml.
  6. Cliquez sur Sauvegarder.
  7. Redémarrez le serveur d'applications pour appliquer les modifications à la configuration JAAS.
  8. Testez le service.

Exemple

L'exemple suivant illustre la méthode createSamlToken() permettant de créer un jeton holder-of-key SAML 2.0 asymétrique :
private SAMLToken createSamlToken() throws Exception {
  SAMLTokenFactory samlFactory =  SAMLTokenFactory.getInstance (SAMLTokenFactory.WssSamlV20Token11);

  RequesterConfig reqData =  samlFactory.newAsymmetricHolderOfKeyTokenGenerateConfig();
  reqData.setAuthenticationMethod("Password"); //Méthode d'authentification de l'assertion 

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

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

  // (Facultatif) Si vous souhaitez utiliser des propriétés de magasin de clés et de clé autres que celles 
  // définies dans le fichier SAMLIssuerConfig.properties, réinisialisez les informations de magasin de clés, 
  // de magasin de clés de confiance et d'alias dans l'objet ProviderConfig.
  KeyInformationConfig kic = samlFactory.newKeyInformationConfig("private_key","keypass","CN=Private");

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

  samlIssuerCfg.setKeyStoreConfig(ksc);    //magasin de clés qui contient la clé privée    
  samlIssuerCfg.setTrustStoreConfig(ksc);  //magasin de clés qui contient la clé publique

  // Définir l'alias du certificat public qui doit exister dans le magasin de clés de confiance.
  // Cet alias ne doit pas nécessiter un mot de passe.
  reqData.setKeyAliasForRequester("public_cert");  

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

  // Obtenir la clé privée à partir du magasin de clés
  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());

  // Ajouter la clé privée au jeton de sorte que celui-ci puisse être utilisé pour signer des 
  // éléments dans un message 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;
}

Icône indiquant le type de rubrique Rubrique de tâche



Icône d'horodatage Dernière mise à jour: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twbs_gen_con_token_JAAS_mod
Nom du fichier : twbs_gen_con_token_JAAS_mod.html