Monday, April 8, 2019

Keycloak Server: delegando a segurança de sua aplicação (parte 2)

Na primeira parte deste post, no console de administração, configuramos o Keycloak Server segurar uma aplicação web que vamos criar. A aplicação não vai conter nenhuma linha de código relacionada à login/logout, ela simplesmente vai terceirizar para o Keycloak toda essa tarefa.

Nesta parte 2, criamos a aplicação e testamos seu login e o logout via Keycloak. Nosso container de aplicação será o Wildfly 15.

Criando e publicando MyWebApp

MyWebApp é uma aplicação maven com JSF e uma página inicial index.xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" 
 xmlns:f="http://java.sun.com/jsf/core"
 xmlns:h="http://java.sun.com/jsf/html">

<h:head>
 <title>My App</title>
</h:head>
<h:body>
 <h:form>
  <h:panelGrid>
  <h1>Welcome to My APP!</h1>
  <h:commandButton value="LOGOUT" action="#{indexMB.logout()}" />
  </h:panelGrid>
 </h:form>
</h:body>
</html>

E o managed bean IndexMB:
package acme.view;

import javax.enterprise.inject.Model;
import javax.faces.context.FacesContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;

import org.keycloak.KeycloakSecurityContext;

@Model
public class IndexMB {

 public String logout() throws ServletException {
  
  System.out.println("Logout!.....");
  HttpServletRequest req = (HttpServletRequest)
      FacesContext.getCurrentInstance().getExternalContext().getRequest();
  KeycloakSecurityContext context = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
  System.out.println("-------- realm name: "+context.getRealm());
  req.logout();
  return null;
 }
}

Abaixo o arquivo de configuração pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
 <groupId>com.acme</groupId>
 <artifactId>MyWebApp</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>
 <properties>
  <java.version>1.8</java.version>
 </properties>
 <dependencies>
  <!-- https://mvnrepository.com/artifact/org.keycloak/keycloak-core -->
  <dependency>
 <groupId>org.keycloak</groupId>
 <artifactId>keycloak-core</artifactId>
 <version>5.0.0</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/javax/javaee-api -->
  <dependency>
   <groupId>javax</groupId>
   <artifactId>javaee-api</artifactId>
   <version>7.0</version>
   <scope>compile</scope>
  </dependency>  
 </dependencies>
 <build>
 <finalName>myapp</finalName>
 </build>
</project>

E o arquivo web.xml em WEB-INF. Nele é necessário especificar o método de autenticação como KEYCLOAK:
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
 <display-name>myapp</display-name>
 <welcome-file-list>
  <welcome-file>index.xhtml</welcome-file>
 </welcome-file-list>
 <servlet>
  <servlet-name>Faces Servlet</servlet-name>
  <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>Faces Servlet</servlet-name>
  <url-pattern>*.xhtml</url-pattern>
 </servlet-mapping>
  <!-- Keycloak confs -->
 <security-constraint>
  <web-resource-collection>
   <url-pattern>/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>Developer</role-name>
  </auth-constraint>
 </security-constraint>

 <login-config>
  <auth-method>KEYCLOAK</auth-method>
  <realm-name>TeamSecurity</realm-name>
 </login-config>

 <security-role>
  <role-name>Developer</role-name>
 </security-role>
</web-app>
Na pasta WEB-INF colocamos o arquivo keycloak.json que foi gerado pelo console admin do Keycloak na parte 1 deste post. O código completo do projeto se encontra no github.

Frameworks de Autorização e Autenticação

O Keycloak trabalha com 2 formas de autenticação: OpenID Connect e o SAML 2.0.

OpenID Connect (OIDC) é uma camada de autenticação e identificação de usuário no topo do framework OAuth 2.0. O OAuth 2.0 trabalha com autorizações (o quê pode ser acessado), enquanto o OIDC define um fluxo de autenticação de usuários (quem está acessando).

SAML 2.0 é um padrão de troca de informações entre partes sobre autorização e autenticação por meio de um arquivo XML digitalmente assinado.

Quando for segurar uma aplicação pelo Keycloak a primeira coisa a decidir é qual mecanismo de autenticação e autorização você ira usar. Na maioria dos casos recomenda-se o OIDC, o qual será usado neste post.

Client Adapters

São bibliotecas que tornam mais fácil segurar aplicações e serviços com o Keycloak. Há vários adpaters diferentes dependendo de qual plataforma sua aplicação esteja rodando. Se for uma aplicação Java, existem adpaters para o Wildfly, Tomcat, Spring Boot, Jetty, etc. Há ainda outros adapaters para Java Script, Node.js, Python, iOS, entre outras. Veja a relação completa aqui.

Como nosso container é o WildFly, vamos utilizar seu respectivo adapter para o OIDC. Baixe o arquivo keycloak-wildfly-adapter-dist-5.0.0.zip. Descompacte seu conteúdo (pastas bin, docs e modules) na pasta raiz do Wildfly.

Após descompactar o arquivo, execute o seguinte comando dentro do diretório raiz do Wildfly:
wildfly-15.0.1.Final$ ./bin/jboss-cli.sh --file=bin/adapter-elytron-install-offline.cli
Esse script edita os arquivos de configuração do Wildfly para que ele fique ciente do método de autenticação do Keycloak referenciados no web.xml.

Os próximos passos são:

1 Subir o Keycloak
keycloak-5.0.0$ ./bin/standalone.sh -Djboss.socket.binding.port-offset=100
Após executar o comando, acesse o Keycloak em http://localhost:8180/auth/.

2 Subir o WildFly
wildfly-15.0.1.Final$ ./bin/standalone.sh
Após executar o comando, acesse o Wildfly em http://localhost:9990.

3 Empacotar a aplicação
~/workspace/MyWebApp$ mvn install
Nesse caso utilizamos o Maven. Como alternativa, você pode construir a aplicação utilizando as ferramentas de alguma IDE. O comando acima gera o arquivo myapp.war dentro da pasta target. Copie a URL do arquivo.

4 Publicar myapp.war no Wildfly

Para fazer o deploy da aplicação, vamos utilizar o cliente do Wildfly jboss-cli.sh, que se encontra dentro da pasta bin do Wildfly (ou jboss-cli.bat se for Windows). Execute o seguintes comandos, substituindo o caminho de myapp.war de acordo com o seu ambiente:
~/Servers/wildfly-15.0.1.Final$ ./bin/jboss-cli.sh
You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands.
[disconnected /] connect
[standalone@localhost:9990 /] deploy /home/rafael/workspace/MyWebApp/target/myapp.war
Não esqueça de substituir o caminho até myapp.war de acordo com o seu ambiente.

Pronto! Aplicação foi publicada e possui um mecanismo de autenticação totalmente desacoplado. Para testar acesse a aplicação em http://localhost:8080/myapp. Você vai bater de frente com a seguinte página:


Logue com o usuário que você criou na parte 1 deste post, para o qual foi atribuida a role Developer.

Após logar, você será direcionado para a página da aplicação:


Clique em logout. E o Keycloak vai encerrar sua sessão e você é novamente redirecionado para a página de login.

Servidor de Sessão

O Keycloak também funciona como um servidor de sessão. Acesse myapp de um browser diferente e em seguida logue com o admin na console de administração do Keycloak.

No realm  TemSecurity, no menu client, escolha o client MyWebApp, e depois clique na aba Sessions:



Você verá que o keycloak lista o usuário que você criou com 2 sessões ativas. Clique no usuário, e você poderá derrubá-lo a partir do console do Keycloak.

O Keycloak é uma solução muito interessante que fornece autenticação como microserviço, ou seja, não há dependência entre os componentes internos da aplicação e os processos de autenticação, autorização e manipulação dos dados do usuário. Nenhuma linha de código para login/logout foi escrita e a aplicação já está totalmente segurada.

referências:
https://www.keycloak.org/documentation.html  


"Determinarás tu algum negócio, e ser-te-á firme, e a luz brilhará em teus caminhos."

Jó 22:28

       

2 comments:

  1. Amigo estou buscando freelancer para um job em configurações avançadas em keycloak, terias interesse?

    ReplyDelete
    Replies
    1. blz Fabiel! Então comecei a estudar o Keycloak só mes passado, ainda não domino suas configurações avançadas, quem sabe no futuro...
      abraços

      Delete