Histórico da Página
Índice
Índice | ||||||
---|---|---|---|---|---|---|
|
Objetivo
Esta experiência de uso tem como objetivo principal o uso do Fluig Identity como IDP (Identity Provider) para a linha de produtos TFS - Totvs Financial Services. Consiste em transferir para o Fluig Identity a responsabilidade por autenticar e validar usuários do TFS provendo assim um ponto de acesso único através do Single-Sign-On.
Single-Sign-On
Single-Sign-On (SSO) é uma propriedade do controle de acesso de sistemas de softwares independentes, porém multi-relacionados. Com esta propriedade um usuário efetua login uma vez e ganha acesso a todos os sistemas sem ser solicitado a efetuar login novamente em cada um deles. Por outro lado, Single-Sign-Off é a propriedade pela qual uma única ação de logout termina o acesso a vários sistemas de software.
Como diferentes aplicações e recursos suportam diferentes mecanismos de autenticação, Single-Sign-On deve internamente traduzir e armazenar as credenciais para os diversos mecanismos a partir da credencial utilizada para autenticação inicial.
Módulo de Segurança do TFS
A linha de produtos TFS - Core Banking constitui-se de dezenas de módulos que, interligados, fornecem soluções de Core Banking a diversos tipos de Instituições Financeiras. Basicamente, a linha de produtos está dividida em módulos que foram concebidas em duas plataformas: Plataforma Web e plataforma Power Builder.
Os módulos da plataforma Web são todos desenvolvidos em Java e utiliza o Josso, uma solução para Single-Sign-On de aplicações Web.
O Fluig Identity disponibiliza a possibilidade de autenticação tanto para aplicações Web quanto para aplicações Desktop. Durante a configuração da Aplicação no Fluig Identity é possível selecionar o tipo de autenticação (login). A opção SAML é a aplicada as aplicações web-based, enquanto que a opção Executável SAML é o login de aplicações Desktop.
Para as experiências de uso do Fluig, o segmento TFS irá configurar duas aplicações:
- TFS Web, portal de entrada para os módulos Web da suite de produtos TFS Core-Banking. Será configurada com login SAML.
- TFS Power Builder, que é o portal de entrada para os módulos Power Builder da suite de produtos TFS Core-Banking. Será configurada com login Executável SAML.
SAML
Fluxo da autenticação
A autenticação consiste basicamente em identificar o usuário que está acessando a aplicação e atestar que sua identidade é válida. Com o Fluig Identity atuando como o Provedor de Identidade (ID Provider) e a aplicação cadastrada e configurada atuando como o Provedor de Serviço (Service Provider), existe a possibilidade de a aplicação ser iniciada em qualquer um dos lados.
A aplicação pode ser inicializada tanto de através do Fluig Identity (através do lançamento da aplicação cadastrada) quanto através da própria aplicação, ou seja, da mesma forma que era chamada antes do contexto do Single-Sign-On (pela URL no browser no caso de aplicações web, ou pela execução da linha de comando em aplicações desktop).
No Fluig Identity, é possível configurar o tipo de inicialização da aplicação.
Nota | ||
---|---|---|
| ||
Para aplicações Web configurada com IDP_INITIATED, a inicialização funciona tanto pelo IDP (Identity Provider) quanto pelo SP (Service Provider). Em outras palavras, é possível inicializar uma aplicação Web tanto pelo Fluig Identity quanto pelo browser se a aplicação estiver configurada como IDP_INITIATED. |
IDP_INITIATED
Este tipo de inicialização ocorre quando a chamada da aplicação é feita a partir do IDP (Identity Provider), ou seja, a partir do Fluig Identity.
O usuário acessa o Fluig Identity. Para ter acesso ao Fluig Identity, precisa se logar. Uma vez logado e autenticado, o IDP vai lançar a aplicação invocando o Servlet de Consumidor de Asserções (AssertionConsumerService). Esta Servlet recebe a requisição e repassa para o saml-java-toolkit que irá fazer todas as ações relacionadas a handshake e autoriazação do usuário. Uma vez realizadas as ações, o toolkit devolve um objeto que representa o usuário validado e autenticado.
O aplicativo, então, estabelece uma relação de confiança com o IDP e assume que o usuário devolvido é de fato válido e autêntico.
SP_INITIATED
Este tipo de inicialização ocorre quando a chamada da aplicação é feita a partir do próprio SP (Service Provider).
O usuário acessa o diretamente o aplicativo (URL no browser ou executável). O aplicativo identifica que está sendo acessado diretamente, então, durante as primeiras instruções de inicialização, direciona a requisição para a Servlet RequestGenerator. Esta Servlet redireciona a requisição para o Fluig Identity para que o usuário possa se logar. Uma vez logado, o Fluig Identity invoca o Servlet de Consumidor de Asserções (AssertionConsumerService). A partir daí, o resto do fluxo segue da mesma forma que o fluxo no IDP_INITIATED e resulta na entrega de um objeto que representa o usuário validado e autenticado.
Então, igualmente o aplicativo estabelece uma relação de confiança com o IDP e assume que o usuário devolvido é de fato válido e autêntico.
Preparando o TFS para o Single-Sign-On
A aplicação Web do portal de módulos do TFS utiliza um toolkit em java que implementa o SAML, o saml-java-toolkit. O toolkit fica, então, responsável por toda ação relacionada a negociação e hand-shake durante o processo de autenticação e entregará o usuário devidamente identificado e autenticado no Fluig Identity para a aplicação Web. Para utilizar o saml-java-toolkit, foi adicionado a dependência no pom.xml do projeto web:
Bloco de código | ||||
---|---|---|---|---|
| ||||
<!-- DEPENDENCIAS DO SAML TOTVS -->
<dependency>
<groupId>com.totvslabs</groupId>
<artifactId>saml-java-toolkit</artifactId>
<version>1.2.3</version>
</dependency> |
O toolkit SAML utiliza um conjunto de propriedades que identifica e configura o toolkit para o Fluig identity. O framework da aplicação Web do portal de módulos do TFS possui o arquivo app.xml e o utiliza para guardar estas propriedades. Deve ser inseridas as propriedades que o toolkit SAML irá utilizar durante sua execução.
Bloco de código | ||||
---|---|---|---|---|
| ||||
<appconfig>
<aplicacaoNome>Sistema TOTVS</aplicacaoNome>
<!--
Outras propriedades neste nível...
...
...
-->
<parametros>
<autenticacaoFluig>true</autenticacaoFluig>
<autenticacaoLogout>https://tfs.thecloudpass.com/cloudpass/login/logout</autenticacaoLogout>
<autenticacaoClockSkew>60</autenticacaoClockSkew>
<autenticacaoSpIssuerName>TotvsLabs</autenticacaoSpIssuerName>
<autenticacaoSpProtocolBinding>HttpPost</autenticacaoSpProtocolBinding>
<autenticacaoAcsURL>http://10.51.6.62:8085/jsp_login/ACS</autenticacaoAcsURL>
<autenticacaoIdpProtocolBinding>HttpPost</autenticacaoIdpProtocolBinding>
<autenticacaoProviderName>TotvsLabs</autenticacaoProviderName>
<autenticacaoNameIdFormat>email</autenticacaoNameIdFormat>
<autenticacaoRelayState>http://10.51.6.62:8085/jsp_login/ACS</autenticacaoRelayState>
<autenticacaoIdpIssuerName>TotvsLabs</autenticacaoIdpIssuerName>
<autenticacaoIdpDestination>https://tfs.thecloudpass.com/cloudpass/SPInitPost/receiveSSORequest/lteodrn5ckp9kl181410443016241/get619yn058rezjv1410518461489</autenticacaoIdpDestination>
<autenticacaoCertificateFile>C:\\Dev\\tfs.thecloudpass.com.crt</autenticacaoCertificateFile>
<autenticacaoIdpCertIssuerName>Totvslabs</autenticacaoIdpCertIssuerName>
<autenticacaoExecutavelSAMLTimeout>60</autenticacaoExecutavelSAMLTimeout>
<!--
Outras propriedades neste nível...
...
...
-->
</parametros>
</appconfig> |
Segundo o fluxo acima, ao lançar a aplicação TFS Web, o Fluig Identity dispara um resquest para a URL de Consumidor de Asserções configurada para a aplicação (http://{host:port}/jsp_login/ACS). Este contexto está mapeado no web.xml.
Bloco de código | ||||
---|---|---|---|---|
| ||||
<!-- CONFIGURACAO DO SAML DO FLUIG DA TOTVS -->
<servlet>
<servlet-name>ACS</servlet-name>
<servlet-class>com.totalbanco.framework.josso.web.AssertionConsumerService</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ACS</servlet-name>
<url-pattern>/ACS</url-pattern>
</servlet-mapping> |
De acordo com o mapeamento, o request é direcionado para a Servlet abaixo. Tanto o doPost()
quanto o doGet()
delegam a chamada para o método privado receiveResponse()
. Note que ele faz uso das propriedades gravadas no app.xml descritas acima.
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
package com.totalbanco.framework.josso.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.totalbanco.framework.orion.TBAppConfig;
import com.totvslabs.idm.protocol.saml2toolkit.common.OpenSAMLInitializer;
import com.totvslabs.idm.protocol.saml2toolkit.common.PropertyObject;
import com.totvslabs.idm.protocol.saml2toolkit.common.User;
import com.totvslabs.idm.protocol.saml2toolkit.responseVerify.ResponseProcessor;
/**
* This class will receive SAML response from the IDP
*
*/
public class AssertionConsumerService extends HttpServlet {
private final static Logger logger = LoggerFactory.getLogger(AssertionConsumerService.class);
private static final long serialVersionUID = 1L;
@Override
public void init() {
try {
//initialize the library
OpenSAMLInitializer initOpenSaml = new OpenSAMLInitializer();
initOpenSaml.initializeLibrary();
}catch (Exception e){
logger.error("Exception occurred while initializing the OpenSaml library: " + e.getMessage());
}
}
@Override
public void doGet(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) throws ServletException, IOException {
logger.debug("received a GET");
receiveResponse(httpRequest, httpResponse);
}
@Override
public void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException {
logger.debug("received a POST");
receiveResponse(request, response);
}
private void receiveResponse(HttpServletRequest httpRequest, HttpServletResponse httpResponse) {
logger.debug("receieved a SAML Response");
try {
final TBAppConfig tbAppConfig = (TBAppConfig) httpRequest.getSession().getServletContext().getAttribute(TBAppConfig.COMPONENT_NAME);
final PropertyObject propObj = new PropertyObject();
propObj.setClockSkew(tbAppConfig.getParametros().get("autenticacaoClockSkew"));
propObj.setSpIssuerName(tbAppConfig.getParametros().get("autenticacaoSpIssuerName"));
propObj.setSpProtocolBinding(tbAppConfig.getParametros().get("autenticacaoSpProtocolBinding"));
propObj.setAcsUrl(tbAppConfig.getParametros().get("autenticacaoAcsURL"));
propObj.setIdpProtocolBinding(tbAppConfig.getParametros().get("autenticacaoIdpProtocolBinding"));
propObj.setProviderName(tbAppConfig.getParametros().get("autenticacaoProviderName"));
propObj.setNameIdFormat(tbAppConfig.getParametros().get("autenticacaoNameIdFormat"));
propObj.setRelayState(tbAppConfig.getParametros().get("autenticacaoRelayState"));
propObj.setIdpIssuerName(tbAppConfig.getParametros().get("autenticacaoIdpIssuerName"));
propObj.setIdpDestination(tbAppConfig.getParametros().get("autenticacaoIdpDestination"));
propObj.setCertificateFile(tbAppConfig.getParametros().get("autenticacaoCertificateFile"));
propObj.setIdpCertIssuerName(tbAppConfig.getParametros().get("autenticacaoIdpCertIssuerName"));
logger.debug("ResponseProcessor.processResponse() will be executed with properties bellow:");
logger.debug("ClockSkew: " + propObj.getClockSkew());
logger.debug("SpIssuerName: " + propObj.getSpIssuerName());
logger.debug("SpProtocolBinding: " + propObj.getSpProtocolBinding());
logger.debug("AcsUrl: " + propObj.getAcsUrl());
logger.debug("IdpProtocolBinding: " + propObj.getIdpProtocolBinding());
logger.debug("ProviderName: " + propObj.getProviderName());
logger.debug("NameIdFormat: " + propObj.getNameIdFormat());
logger.debug("RelayState: " + propObj.getRelayState());
logger.debug("IdpIssuerName: " + propObj.getIdpIssuerName());
logger.debug("IdpDestination: " + propObj.getIdpDestination());
logger.debug("CertificateFile: " + propObj.getCertificateFile());
final ResponseProcessor responseProcessor = new ResponseProcessor();
final User user = responseProcessor.processResponse(httpRequest, httpResponse, propObj);
logger.debug("Usuário autenticado: " + user.getUsername());
httpRequest.getSession(true).setAttribute("userFluig", user);
httpResponse.sendRedirect(httpRequest.getContextPath() + "/signon/login.htm");
} catch(Exception e) {
logger.error("Exception while processing the response: " + e.getMessage());
}
}
} |
Executável SAML
Aviso | ||
---|---|---|
| ||
Estas instruções devem ser seguidas para que o Executável SAML funcione! |
As aplicações Power Builder são instaladas através de um instalador do tipo Wizard que, além de copiar todos os arquivos corretamente na pasta de instalação, ainda efetua o registro da aplicação no Registro do Windows (Regedit). Além da informação do executável, é criado um par chave/valor com chave 'Path' e com valor que contém os caminhos dos diretórios onde se encontram as DLL's necessárias para execução da aplicação Power Builder.
Na solução Executável SAML, ao efetuar o handshake SAML após o launcher da aplicação, o Fluig Identity invoca o executável Power Builder através do Desktop Launcher, que é uma aplicação utilitária executável (appinvoker.exe), que por sua vez realiza a chamada do executável do Power Builder propriamente dito.
O problema é que o executável Power Builder, ao ser invocado pelo appinvoker.exe, herda dele todas as configurações do Registro do Windows. Como o appinvoker não tem a chave 'Path' configurada, também não a repassa para o executável Power Builder que fica sem "saber" onde estão as DLL's e portanto, incapaz de funcionar corretamente.
Para que o executável Power Builder possa ser executado corretamente, deve ser criado o par chave/valor do tipo 'Valor da Cadeia de Caracteres' na configuração Regedit do appinvoker exatamente igual ao configurado para o executável Power Builder.
Deck of Cards | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||||||||||||
|
Provisionamento
https://totvslab.atlassian.net/wiki/display/PI/SCIM+Integration+Steps#SCIMIntegrationSteps-Users