segunda-feira, 9 de novembro de 2015

Single Sign On


Que tal este cenário: Um usuário, digamos o Zezinho, abre uma aplicação sua chamada Solução1 e trabalha normalmente, isso após ter realizado o login corretamente.  Posteriormente, no mesmo navegador o Zezinho abre uma segunda aplicação, Solucao2, e digamos que de forma automática, a Solução 2 já identifica que o Zezinho já se encontra autenticado e o libera de realizar o login novamente.

De forma bem clara, o Single Sign On - SSO, prove um mecanismo para centralizar a autenticação de seus usuários a partir de um ponto único para todas as suas aplicações e o GAM é um recurso de proteção de um projeto Genexus construído com um protocolo que possibilita desenvolver sistemas de autenticação no formato do SSO.  Então que tal estudarmos um pouco a respeito deste assunto e melhorar a qualidade do serviço que prestamos a nossos usuários?


O nome disso? 
Single Sign On ou SSO, e se quiser uma definição mais formal olhe aqui.

Quem utiliza isso? 
Praticamente todos os fornecedores de aplicações que se prezem a realizar um trabalho com foco no conforto do usuário, como por exemplo o Google, Facebook. Lembre-se, por exemplo, do Gmail que uma vez realizado o login para ler seus emails, libera o acesso do Google Drive sem que se tenha de realizar a operação novamente.

Podemos programar isso em Genexus?
Sim, aplicando o GAM na nossa Kb e criando o chamado Identity Provider, um provedor de identidade. E não precisa programar nada, o próprio GAM se encarrega de controlar tudo para você, logo após uma pequena porção de configuração.


Como o GAM implementa o SSO?
O GAM é construído baseado na OAUTH, um protocolo que permite que Aplicações Clientes possam se conectar a aplicações Web, Desktop, Smartdevice e Living Room Device, provendo controle sobre a autenticação e autorização de usuários,


O que é Identity Provider?
É um tipo de aplicação que fornece um serviço de autenticar usuários remotamente.  Como resposta este sistema devolve se houve sucesso ao autenticar um usuário e senha fornecidos.  Um protocolo padrão na Web define os procedimentos necessários para implementar este tipo de ação, o OAUTH, o mesmo usado no GAM e em praticamente todos os demais Identity Provider (Facebook, Google. ...)


Como Fazer?
Primeiramente utilizando o GAM, seguindo os passos que já foram extensamente documentados no Wiki, que estarei incluindo aqui, mas como sou inxerido, resolvi adicionar um pouco mais de clareza neste tema, então neste artigo estaremos:
  1. Configurando um Identity Provider para gerar um SSO com Genexus
  2. Discorrendo sobre esta funcionalidade sob o ponto de vista da aplicabilidade no mundo real

Configurando o Identity Provider

Identity Provider é definido como sendo um provedor de identificação, e se algum dia você realizou uma conexão entre seu sistema e o Facebook, por exemplo, utilizou o provedor de identificação deste sistema. Este provedor, basicamente fornece um serviço que avalia se certo usuário e senha são os que se encontram registrados em seu repositório, devolvendo o resultado para a aplicação cliente.

O modelo Single Sign On proposto aqui basicamente define uma de nossas KBs como sendo um Identity Provider, por meio de um recurso que o GAM passou a implementar a partir da EV3.  E em seguida, outra KB cliente se conectará ao nosso Identity Provider para confrontar se certo usuário já se encontra logado, basicamente, o que o sistema analisa é se existe alguma sessão válida no navegador e se o usuário desta sessão pode utilizar os recursos disponíveis.

O processo de configuração é meio confuso, mas vamos 'tentar' explicar de forma mais simples.

Maiores informações a respeito do Single Sign On com o GAM pode ser alcançado daqui.

1. Crie Duas Kb: Provedor e Cliente

Vamos começar definindo duas kbs que estaremos configurando o GAM. Uma chamaremos de GAM.PROVIDER e outra de GAM.CLIENT, sendo que na GAM.PROVIDER definiremos posteriormente como sendo nosso Identity Provider, ou seja o GAM que será chamado pela aplicação GAM.CLIENT para autenticar remotamente um usuário qualquer.

Após criar as duas KBs acesse a propriedade Enabled Integrated Security (em Preferences - Kb) e a defina como YES. para aplicar o GAM em ambas.  (GAM Getting Started)  Tenha um pouco de paciência neste momento e espere ate que o Genexus volte a funcionar, pois esta operação realizará uma série de importações e pode parecer que a ferramenta ficará indisponível por alguns segundos.

Execute as duas Kbs, configurando os Datastores de ambas, cada qual com um banco de dados separado. O Datastore GAM de ambas as kbs pode ser o mesmo que o definido em Default.


O Genexus levará um tempo para executar as duas kbs, visto que muitos objetos foram criados com a aplicação do GAM.

2. Configurando o GAM

Um resumo do que faremos é registrarmos na GAM.PROVIDER a aplicação da KB GAM.CLIENT, e na GAM.CLIENT definir a autenticação remota.


2.1. Client Id e Secret
Quando ambas as kbs estiverem em funcionamento no navegador de internet, você deverá ingressar no GAMHome (User: admin, Senha: admin123), para ler as configurações que foram geradas.  Para isso acesse o Applications e abra o registro de GAM.PROVIDER e GAM.CLIENT.


Para facilitar as coisas anotei os dois Client Ids e Secrets que utilizaremos para configurar o Identity Provider.  Observe que os valores de Clent Id Secret de ambas as Kbs são distintos e estaremos os valores de GAM.CLIENT para configurar a operação de Single Sign On. Os valores da GAM.PROVIDER não serão utilizados.



2.2. Adicionando a Kb Client no GAM.PROVIDER
A primeira operação a caminho do Single Sign On é adicionar em GAM.PROVIDER um registro de uma aplicação cliente, nossa GAM.CLIENT. Isso é feito em GAM.PROVIDER - Applications, e em seguida uma operação ADD para adicione o registro com as seguintes informações.


Observe que o Client Id e Client Secret são os mesmos da GAM.CLIENT, e novas propriedades devem ser informadas:

Local Login URL deve apontar para o programa gamremotelogin.aspx da kb GAM.PROVIDER, portanto, http://localhost/GAMPROVIDER.NetEnvironment/gamremotelogin.aspx, e Callback URL o endereço da GAM.CLIENT, http://localhost/GAMCLIENT.NetEnvironment.

Após a inclusão da aplicação teremos o registro do GAM.CLIENT como uma segunda aplicação gerenciada pelo GAM de GAM.PROVIDER

Em outras palavras, estamos dizendo que o GAM localizado na kb GAM.PROVIDER será um dos provedores de identidade para os clientes de GAM.CLIENT.  Desta forma, para se executar o GAM.CLIENT será necessário realizar uma operação de login, e esta poderá ser disparada no provedor de identidade (GAM.PROVIDER).


2.3.Configurando o GAM.CLIENT
Para realizarmos o login no GAM.PROVIDER teremos que registrar um método de autenticação do tipo acesso remoto (GAM.REMOTE)  na GAM.CLIENT, Desta forma disparamos uma autenticação em outro GAM, que não o definido na aplicação cliente.

Ao adicionar este novo Authentication Type, teremos novamente que utilizar os valores de ClientId e ClientSecret e Private encryption key , que foram previamente registrados no GAM do provedor de identidade (GAM.PROVIDER), e para os valores de Local site URL = http://localhost/GAMCLIENT.NetEnvironment/ e Remote server URL = http://localhost/GAMPROVIDER.NetEnvironment/


Maiores informações em:


Logando uma Unica Vez

Para testar o modelo basta criar um usuário qualquer na kb GAM.PROVIDER, e em seguida realizar o login remoto a partir da kb GAM.CLIENT.

Apesar de não existir o usuário na kb GAM.CLIENT, o acesso será permitido porque a autenticação do mesmo acontecerá na kb GAM.PROVIDER. Na primeira vez que isso ocorrer, uma tela se abrirá para que o usuário seja criado também na GAM.CLIENT (sem a senha, que ficará na GAM.PROVIDER).

Desta forma, após o login ter sido realizado, o usuário passa a existir em ambos os GAMs. E se selecionar um objeto em ambas as kbs o mesmo será aberto sem que haja a necessidade de realizar novamente a operação de autenticação.

Um detalhe importante é que a operação de autenticação é realizada remotamente, ou seja, um objeto GAMRemoteAccess localizado na GAM.PROVIDER deverá ser aberto para que se ingresse com o usuário e a senha.



Sessão & Logout

Uma vez autenticado remotamente, uma sessão valida será aberta também no GAM.CLIENT, ou seja, a autenticação já havia criado uma sessão valida anteriormente no GAM.PROVIDER. E as duas sessões já liberam o acesso a ambos os sistemas.

Todo o processo de validação da sessão é realizado mediante o definido no protocolo da OAUTH, e tratado pelo GAM sem que seja necessário programar nenhuma linha de código.

Para encerrar a sessão é necessário realizar o logout no GAM.CLIENT, mas isso não encerrará a sessão no GAM.PROVIDER.  Isso causará um efeito, no minimo interessante, pois mesmo se fechar a aba do navegador do cliente, e abrir uma nova no mesmo navegador, o login no GAM.PROVIDER estará ativo e não será necessário autenticar novamente, pois uma nova chamada ao GAMRemoteLogin abrirá novamente a sessão.

Event 'Logout'
GAMRepository.Logout(&gamerrors)
for &gamerror in &gamerrors
msg(&gamerror.Message)
endfor
Endevent

Um logout definitivo somente ocorrerá se a sessão no GAM.PROVIDER for encerrada, como por exemplo, pelo fechamento do navegador.

Maiores informações em:


Tratando o Perfil do Usuário

Para que tudo funcione corretamente no sistema, precisamos ainda tratar da questão do perfil do usuário (Role), isso porque o acesso aos objetos são definidos no próprio Role.

Uma nota importante aqui é que as definições de permissões são sempre no CLIENTE, mediante as definições de Allow e Deny que foram definidas para cada objeto a um certo Role. A autenticação (Authentication) determinará se o cliente pode ingressar no sistema e a autorização (Authorization), determinará quais objetos podem ser acessados, e qual o privilégio de acesso.  Desta forma as definições do PROVIDER não contribuirá no acesso do cliente.

Por outro lado, um detalhe importante é a transferência dos Roles do usuário para a aplicação cliente, que pode ocorrer no processo de login.  Ou seja, quando uma pessoa realiza o login remoto, os Roles definidos na aplicação PROVIDER podem ser replicadas na aplicação CLIENT.

Para que isso ocorra é necessário mapear os perfis utilizando-se a propriedade ExternalId, isso ocorre porque os nomes dos perfis podem até serem iguais, mas como o GAM somente leva em conta o GUID dos perfis, e como estes sempre serão diferentes, precisaremos definir um código próprio para estabelecer a correspondência, sendo aceito números, letras, para definir uma palavra que crie a associação. Por exemplo:


Ao fazer isso, quando realizar a autenticação de um usuário, os perfis (Roles) definidos no PROVIDER serão replicados no CLIENT.

Maiores informações:



Criticas a OAUTH

Finalmente, o GAM é baseado especificamente no protocolo da OAUTH, e como existem similares no mercado que se propõe a realizar a mesma coisa, existem criticas e elogios aos modelos propostos, e fica sempre a duvida a respeito da robustez do GAM para atender as nossas aplicações.

Separei dois artigos interessantes a respeito desta novela para que você tire suas próprias conclusões.


Conclusão 

Antes de finalizar, vamos destacar o excelente trabalho feito pela Genexus para nos disponibilizar este grande recurso, e principalmente pelo farto material disponibilizado na Wiki que foi uma base excepcional para que chegássemos a este artigo, que em muitos detalhes reproduziu a mesma linha de raciocínio dos desenvolvedores. (Atualmente a Wiki possui 405 artigos sobre GAM!)

Este tema é muito interessante para ficar em um único artigo, acredito que logo voltaremos ao tema, para mostrar detalhes mais práticos a respeito do SSO em multiplas kbs Genexus.