DEV Community

Paulo Neto
Paulo Neto

Posted on

Protegendo suas API's com Keycloak

Dando continuidade ao post que fiz há um tempo sobre representação de arquitetura de aplicações com diagramas C4, neste post trago uma questão muito importante quando falamos sobre desenvolvimento de API's Rest, que é a segurança. Para exemplificar a segurança em API's Rest, trago um exemplo de implementação de um dos componentes da arquitetura representada no diagrama do post anterior. Neste post apresento a implementação do microservice ecommerce-ms-product implementado com Java 17, JPA e Spring Boot. Para a segurança da API utilizei o Keycloak como Identity and Access Management(IAM).

O que é um Identity and Access Management(IAM)?

A gestão de identidade e acesso oferece supervisão sobre a autenticação de usuários e a disponibilidade de recursos. Frequentemente referida como IAM, essa tecnologia assegura que as pessoas adequadas tenham acesso aos recursos digitais apropriados no momento oportuno e pelas razões corretas.

Conceitos básicos sobre IAM

Um recurso digital refere-se a qualquer combinação de aplicativos e dados dentro de um sistema computacional. Entre os exemplos, estão aplicativos web, APIs, plataformas, dispositivos e bancos de dados.

No centro do IAM está a identidade. Alguém deseja acessar seu recurso, seja um cliente, funcionário, membro ou participante. No contexto do IAM, uma conta de usuário corresponde a uma identidade digital. Além de representar pessoas, essas contas também podem estar associadas a elementos não humanos, como softwares, dispositivos da Internet das Coisas (IoT) ou robôs.

A autenticação consiste na verificação de uma identidade digital, garantindo que alguém (ou algo) comprove ser quem afirma.
Já a autorização determina quais recursos um usuário tem permissão para acessar.

Os padrões de autenticação e autorização são essenciais para garantir a segurança e a eficiência dos sistemas de gerenciamento de identidade (IAM). Os mais reconhecidos e amplamente adotados na indústria incluem:

OAuth 2.0: Protocolo de autorização que permite acesso seguro a recursos sem expor credenciais.
OpenID Connect (OIDC): Extensão do OAuth 2.0 para autenticação, permitindo que usuários se identifiquem de maneira segura.
SAML (Security Assertion Markup Language): Protocolo baseado em XML usado para autenticação e troca de informações de identidade entre diferentes sistemas.
FIDO2/WebAuthn: Padrão para autenticação sem senha, baseado em chaves criptográficas.
LDAP (Lightweight Directory Access Protocol): Protocolo usado para acessar e manter diretórios de informações sobre usuários e dispositivos.

Esses padrões são amplamente considerados os mais seguros e confiáveis para gerenciar identidades, proteger dados pessoais e controlar o acesso a recursos.

Client Credentials Flow

Na implementação utilizei o Client Credentials Flow(definido no OAuth 2.0 RFC 6749, seção 4.4) envolve um aplicativo trocando suas credenciais de aplicativo, como client ID e client secret, por um token de acesso.

Image description

Este fluxo é mais adequado para aplicativos Máquina-a-Máquina (M2M), como CLIs, daemons ou serviços de backend, porque o sistema deve autenticar e autorizar o aplicativo em vez de um usuário.

Na prática

Na implementação do microservice ecommerce-ms-product criei duas coleções de recurso:

/produtos
/categorias

Nelas implementei endpoints para criar, consultar deletar e atualizar esses recursos. Para proteger esses endpoints, para que sejam acessados apenas por quem tem as credenciais necessárias, adicionei no aquivo application.properties do projeto a seguinte entrada:

spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:7080/realms/security-ecommerce-api

Essa entrada configura a aplicação para utilizar o realm security-ecommerce-api que foi criado no Keycloak

Também adicionei as seguintes dependências do Spring no projeto:

        <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>
Enter fullscreen mode Exit fullscreen mode

Com essas dependências no projeto, os endpoints do projeto já ficam indisponíveis, sendo acessadas apenas por quem tem as credenciais adequadas.

Configuração do Realm security-ecommerce-api

Na área interna do Keycloak, crie um novo Realm:

Image description

No Realm criado, vá ao menu Clients e crie um novo Client:

Image description

No nosso exemplo, criei o client ID ecommerce-client, o client secret é gerado pelo Keycloak e apresentado na aba Credentials:

Image description

Testando a API segura

Para testar essa implementação, utilizei uma extensão do VSCode, Rest Client para executar requisições:

Image description

Configuração para Keycloak local

Para rodar o Keycloak local utilizei o Docker e Compose para subir os serviços do Mysql, para a base de dados do Keycloak, e do Keycloak.

services:

  mysqlsrv:
    image: mysql:5.7
    environment:
        MYSQL_ROOT_PASSWORD: "MySql2019!"
        MYSQL_DATABASE: "ecommerce-produtos"
    ports:
      - "3306:3306"
    volumes:
      - /home/paulo/Desenvolvimento/docker/mysql:/var/lib/mysql
    networks:
      - ecommerce-network

  keycloak:
    image: quay.io/keycloak/keycloak:24.0
    container_name: keycloak-ecommerce
    environment:
      KC_HOSTNAME: localhost
      KC_HOSTNAME_PORT: 7080
      KC_HOSTNAME_STRICT_BACKCHANNEL: "true"
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: admin
      KC_HEALTH_ENABLED: "true"
      KC_LOG_LEVEL: info
      KC_DB: mysql
      KC_DB_USERNAME: root
      KC_DB_PASSWORD: MySql2019!
      KC_DB_URL_HOST: mysqlsrv
      KC_DB_URL_PORT: 3306
      KC_DB_SCHEMA: keycloak
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:7080/health/ready"]
      interval: 15s
      timeout: 2s
      retries: 15
    command: ["start-dev", "--http-port", "7080", "--https-port", "7443"]
    ports:
      - "7080:7080"
      - "7443:7443"
    networks:
      - ecommerce-network
    depends_on: 
      - mysqlsrv

networks: 
  ecommerce-network:
    driver: bridge  
Enter fullscreen mode Exit fullscreen mode

Top comments (0)