Spring boot + Keycloak - protegendo suas APIs (parte 1)
Tags: java, springboot, keycloak
Published: 2021-07-16 20:55:33

### Segurança em APIs?
Tem APIs nos teus serviços? Como esta a segurança destas APIs?
Temos algumas maneiras de aplicar seguranças nas nossas APIs. Uma delas é a autenticação e autorização utilizando [OpenID](https://pt.wikipedia.org/wiki/OpenID)/[OAuth2](https://oauth.net/2/).

### Keycloak
Pra que desenvolver se já temos ferramentas prontas?
O [Keycloak](https://www.keycloak.org/) é uma ferramenta open source que prove autenticação e autorização para serviços utilizando alguns protocolos como OpenID, OAuth2 e SAML. Ele tem integração com LDAP, AD e redes sociais.
Para testarmos, vamos subir uma instância do docker:
`docker run --name keycloak -p 8080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin quay.io/keycloak/keycloak:14.0.0`
Ele sobe uma instância do H2 e mesmo que o serviço for reiniciado não vai perder as configurações que fizermos.

#### Configurando o Keycloak
O serviço vai subir na porta 8080 e pode ser acessado pela url `http://localhost:8080`
![Tela inicial](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xf27sj4wcy6uspyrr86p.png)
Quando subimos o docker, setamos um usuário e senha iniciais (KEYCLOAK_USER=**admin** e KEYCLOAK_PASSWORD=**admin**). Clique em "Administration Console", informe o usuário/senha para entrar no console.
![Login](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0l4asfaga00qwzf1n3xz.png)
A primeira coisa que precisamos fazer dentro do console é a criação de um realm. Podemos entender aqui que o realm é a representação da sua aplicação, podemos ter varias aplicações rodando na mesma instância do Keycloak.
Por default já é criado um realm *master*, é onde existe a conta de admin criado inicialmente e só iremos utiliza-lo para a criação de outros realms.
Então no canto superior esquerdo, vamos clicar em "Add realm".
![Criando realm](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i23cuy6s392g1x5nth8f.png)
O próximo passo é criar e configurar o client. Na aba lateral esquerda, clique em "Clients" e depois no botão "Create".
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vs5zqbfrj6psl9zgfkea.png)
Depois de salvo, iremos editar as seguintes propriedades do client.
![Editando o client](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3jdqqbjlatpm5myo0a87.png)
Aqui a url foi adicionada apenas por ser requerida, não iremos utiliza-la.
Estas alterações são necessárias para que, utilizando este client-id, conseguirmos adquirir um token para acesso as APIs.


### Aplicação
Vamos criar um projeto simples utilizando o [Spring Initializr](https://start.spring.io/).

![Criando o projeto](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ipr08qeq85y6daoyej7c.png)

Abra o projeto na sua IDE, edite o *application.properties* e adicione a porta que sua aplicação vai subir:

```yaml
server.port=8090
```

Vamos adicionar o controller abaixo:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jdozuezz5f22jw2io86s.png)
Subindo o projeto e fazendo um teste básico no postman podemos ver que o endpoint esta completamente aberto, sem nenhuma segurança.
![Teste endpoint não seguro](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5a92wdfgca6n4yv5na3.png)

Agora vamos adicionar a segurança. Edite o *pom.xml* e adicione as dependências necessárias:
```xml
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
		</dependency>
```

Só de adicionar as dependências, nossos endpoints já não estarão mais expostos.
![Teste endpoint bloqueado](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lr44xdz4pdmnby0qdged.png)
Agora vamos informar ao spring security qual é a url de validação do token. Vamos editar o *application.properties* e vamos adicionar a propriedades necessária:
```yaml
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/auth/realms/security-api
```
**Atenção** ao ultimo elemento da url, ele é o nome do seu realm.

E isso é o básico que precisamos para ter nossa API segura.

### Pegando um token

Vamos pegar um access token no Keycloak pra testar nosso endpoint. A url para buscar o access token é:
`http://localhost:8080/auth/realms/security-api/protocol/openid-connect/token`
Lembrando que *security-api* é o nome do realm.
No postman, crie um request POST utilizando esta url acima. No body do request vamos enviar o seguinte:
* client_id: é o nome do client que foi criado no keycloak, no nosso caso é *web-app*.
* client_secret: aqui precisamos pegar o valor gerado lá no cadastro do client no keycloak. Edite o client, vá na aba "Credentials" e copie o valor de "Secret"
![client secret](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lk810jy4w57tbsvqvohq.png)
* grant_type: vamos setar "client_credentials", pois iremos gerar um token de um client cadastrado no keycloak.
![access token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wxce3fycegpuqgsz03xs.png)

### Testando o endpoint seguro

Vamos copiar o valor do campo "access_token" do response e vamos editar o request ao nosso serviço. Este token deve ser incluído no header do request com a key *Authorization* e no value incluiremos um prefixo que mostra o tipo do token que será *Bearer*. Vai ficar assim:
![Teste endpoint seguro](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rgq2spj3skgkgsg7q1if.png)
Por ora é isto... vamos melhorar este código na parte 2.

O código deste tutorial esta no [github](https://github.com/msmacorin/spring-boot-keycloak/tree/1.0)

Já saiu a segunda parte de tutorial, você pode ver [aqui](https://dev.to/mmacorin/spring-boot-keycloak-protegendo-suas-apis-parte-2-5bb4)