Gerando e Consumindo Tokens SAML Usando Módulos de Login JAAS Empilhados

É possível usar as APIs GenericSecurityTokenFactory para passar um token SAML criado para os módulos SAMLGenerateLoginModule ou GenericIssuedTokenGenerateLoginModule. Também é possível usar essas APIs para obter tokens SAML que são consumidos pelos módulos SAMLConsumeLoginModule ou GenericIssuedTokenConsumeLoginModule.

Antes de Iniciar

Você deverá ter um conjunto de funções de aplicativos clientes e provedores de serviço do JAX-WS no qual poderão ser incluídas classes de módulo de login do JAAS.

Sobre Esta Tarefa

Esta tarefa gera um token de acesso SAML 1.1, mas pode ser facilmente modificada para usar sender-vouches e qualquer versão do SAML suportada pelo ambiente de tempo de execução.

Apesar de ser possível empilhar um módulo de login sob SAMLGenerateLoginModule para inspecionar um token SAML que foi criado por essa classe, não é possível modificar o token SAML que é obtido dessa maneira, a menos que o token não contenha uma assinatura digital. Se você modificar um token SAML que contém uma assinatura digital, o XML do token SAML será ajustado para suas atualizações, mas porque o token foi assinado antes de ser atualizado, a validação da assinatura falhará no destinatário.

Essa tarefa gera um token de acesso SAML 1.1, mas não é possível usar nenhuma versão e tipo SAML suportados pelo ambiente de tempo de execução. Para obter informações adicionais sobre como criar e modificar tokens SAML com as APIs GenericSecurityTokenFactory, consulte Desenvolvendo Aplicativos SAML. Para obter informações adicionais sobre como colocar o token no contexto de solicitação do cliente em vez de usar um módulo de login do JAAS, consulte as constantes com.ibm.wsspi.wssecurity.token.tokenHolder e com.ibm.wsspi.wssecurity.token.enableCaptureTokenContext em com.ibm.wsspi.wssecurity.core.Constants.

Como o exemplo de gerador não pode ser facilmente modificado para usar holder-of-key, um exemplo do método createSamlToken() específico para o holder-of-key SAML é fornecido no término desta tarefa.

Procedimento

  1. Crie o módulo de login do JAAS a seguir e disponibilize-o para o código do aplicativo.
    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");
        }
    
        //Put the token in a list on the shared state where it will be available to be used by
        //stacked login modules
        factory.putGeneratorTokenToSharedState(_sharedState, myToken);
    
        return true;
      }
    
      private SAMLToken createSamlToken() throws Exception {
        //SAML Bearer example 
        SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token11);
        RequesterConfig reqData = samlFactory.newBearerTokenGenerateConfig();
        reqData.setAuthenticationMethod("Password"); //Método de autenticação para Asserção
    
        ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("self-issue");
    
        CredentialConfig cred = samlFactory.newCredentialConfig ();
        cred.setRequesterNameID("Alice");   // NameIdentifier do SAML
    	  
        //Add some SAML attributes:	
        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. Crie o módulo de login do JAAS do consumidor a seguir e disponibilize-o ao código do aplicativo.
    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");
        }
        //Get the token that was consumed by the GenericIssuedConsumeLoginModule
        SecurityToken myToken = factory.getConsumerTokenFromSharedState(_sharedState, new QName(SAMLTokenFactory.WssSamlV11Token11));
        if (myToken == null) {
            throw new LoginException("myToken is null");
        }
        if (myToken instanceof SAMLToken) {
        	//Examine the SAML token with SAML APIs
        	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. Crie uma configuração de login do JAAS.
    1. No console administrativo, acesse Segurança > Segurança Global.
    2. Sob Autenticação, acesse Java Authentication and Authorization Service > Logins no Sistema.
    3. Crie o gerador de token SAML.
      1. Clique em Novo e, sob Alias, insira test.generate.saml.
      2. Sob Módulos de Login do JAAS, clique em Novo e sob Nome da Classe do Módulo, insira test.tokens.MySamlGenerator. Selecione Usar Proxy do Módulo de Login e clique em OK.
      3. Clique em Novo e, sob Nome da Classe do Módulo, insira com.ibm.ws.wssecurity.wssapi.token.impl.SAMLGenerateLoginModule. Clique OK.
    4. Crie o consumidor de token SAML.
      1. Clique em JAAS - Logins do sistema na trilha de navegação para retornar à página de logins do sistema JAAS.
      2. Clique em Novo e, sob Alias, insira test.consume.saml.
      3. Sob Módulos de Login do JAAS, clique em Novo e, sob Nome da Classe do Módulo, insira com.ibm.ws.wssecurity.wssapi.token.impl.SAMLConsumeLoginModule. Selecione Usar Proxy do Módulo de Login e clique em OK.
      4. Clique em Salvar.
  4. Configure o gerador de token SAML para usar a nova configuração de login do JAAS.
    1. No console administrativo, abra a configuração de ligação que deseja alterar.
    2. Selecione WS-Security > Autenticação e Proteção.
    3. Em Tokens de Autenticação, selecione o token de saída SAML que deseja alterar.
    4. Sob Login do JAAS, selecione test.generate.saml.
  5. Configure o consumidor de token SAML para usar a nova configuração do JAAS.
    1. No console administrativo, abra a configuração de ligação que deseja alterar.
    2. Selecione WS-Security > Autenticação e Proteção.
    3. Em Tokens de Autenticação, selecione o token de entrada SAML que deseja alterar.
    4. Sob Login do JAAS, selecione test.consume.saml.
  6. Clique em Salvar.
  7. Reinicie o servidor de aplicativos para aplicar as mudanças na configuração do JAAS.
  8. Teste o serviço.

Exemplo

O exemplo a seguir ilustra o método createSamlToken() para criar um token holder-of-key assimétrico do SAML 2.0.
private SAMLToken createSamlToken() throws Exception {
  SAMLTokenFactory samlFactory =  SAMLTokenFactory.getInstance (SAMLTokenFactory.WssSamlV20Token11);

  RequesterConfig reqData =  samlFactory.newAsymmetricHolderOfKeyTokenGenerateConfig();
  reqData.setAuthenticationMethod("Password"); //Método de autenticação para Asserção 

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

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

  // (Optional) If you want to use keystore and key properties other than what 
  // is set in the SAMLIssuerConfig.properties file, reset the keystore, 
  // trust store and alias information in the ProviderConfig object.
  KeyInformationConfig kic = samlFactory.newKeyInformationConfig("private_key","keypass","CN=Private");

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

  samlIssuerCfg.setKeyStoreConfig(ksc);    //keystore that holds the private key    
  samlIssuerCfg.setTrustStoreConfig(ksc);  //keystore that holds the public key

  // Set the alias for the public certificate that must exist in the trust store.
  // This alias must not require a password.
  reqData.setKeyAliasForRequester("public_cert");  

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

  // Get the private key from the key store
  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());

  // Add the private key to the token so that the token can be used to sign 
  // elements in a SOAP message. ((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;
}

Ícone que indica o tipo de tópico Tópico de Tarefa



Ícone de registro de data e hora Última atualização: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=twbs_gen_con_token_JAAS_mod
Nome do arquivo: twbs_gen_con_token_JAAS_mod.html