Skip to content

Implementar Autenticação e Autorização com Spring Security e JWT #17

@OtavioXimarelli

Description

@OtavioXimarelli

Atualmente, a API carece de um fluxo de autenticação e autorização funcional para proteger os endpoints. Os endpoints estão todos desprotegidos ou retornando erros 403 devido a uma configuração de segurança incompleta. O objetivo desta tarefa é implementar uma solução de segurança robusta e sem estado (stateless) usando Spring Security e JSON Web Tokens (JWT).

Isso permitirá que os usuários se registrem, façam login para obter um token e usem esse token para acessar endpoints protegidos.

Requisitos e Tarefas a Serem Executadas

1. Configuração da Segurança (SecurityConfig.java)

  • Revisar SecurityFilterChain:
  • Garantir que a política de sessão esteja configurada como STATELESS.
  • Manter o CSRF desabilitado (.csrf(AbstractHttpConfigurer::disable)), o que é apropriado para uma API stateless.
  • Definir corretamente as regras de autorização (.authorizeHttpRequests), permitindo acesso público aos endpoints de autenticação e documentação da API, e exigindo autenticação para todo o resto.
// Exemplo de configuração de autorização
.authorizeHttpRequests(authorize -> authorize
    .requestMatchers(HttpMethod.POST, "/api/auth/login").permitAll()
    .requestMatchers(HttpMethod.POST, "/api/auth/register").permitAll()
    // Adicionar aqui outros endpoints públicos se necessário (ex: Swagger/OpenAPI)
    .anyRequest().authenticated()
)

2. Implementação de JWT (JSON Web Token)

  • Adicionar Dependência de JWT: Incluir uma biblioteca para manipulação de JWT no pom.xml.
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>
  • Criar um TokenService:
  • Implementar um serviço para gerar um token JWT após o login bem-sucedido.
  • O token deve conter informações do usuário (como o login ou ID) e uma data de expiração.
  • Implementar um método para validar um token e extrair o login do usuário a partir dele.
  • Configurar uma chave secreta (secret) para assinar os tokens (armazenada de forma segura, por exemplo, em application.properties).

3. Atualizar o AuthenticationController

  • Modificar o Endpoint de Login:
  • Após autenticar o usuário com sucesso usando AuthenticationManager, o endpoint /api/auth/login deve chamar o TokenService para gerar um JWT.
  • O endpoint deve retornar o token JWT gerado no corpo da resposta. O "auth" que está sendo retornado hoje não é útil em uma API stateless.

4. Criar um Filtro de Validação de Token

  • Implementar um SecurityFilter:
  • Criar um filtro customizado que será executado uma vez por requisição (OncePerRequestFilter).
  • Este filtro irá extrair o token do cabeçalho Authorization da requisição (ex: Bearer <token>).
  • Se um token for encontrado, ele usará o TokenService para validá-lo e extrair o login do usuário.
  • Com o login, ele buscará os detalhes do usuário no UserRepository e definirá o usuário autenticado no contexto de segurança (SecurityContextHolder).
  • Adicionar o Filtro à Cadeia de Segurança:
  • Adicionar o novo SecurityFilter à SecurityFilterChain em SecurityConfig.java, garantindo que ele seja executado antes do filtro padrão UsernamePasswordAuthenticationFilter.
// Em SecurityConfig.java
// ... injetar o seu securityFilter
.addFilterBefore(securityFilter, UsernamePasswordAuthenticationFilter.class)

Critérios de Aceitação

  • As requisições para POST /api/auth/register e POST /api/auth/login devem ser públicas.
  • O endpoint POST /api/auth/register deve salvar o usuário com a senha criptografada usando BCryptPasswordEncoder.
  • O endpoint POST /api/auth/login deve retornar um JWT válido em caso de sucesso.
  • Requisições para endpoints protegidos (ex: GET /api/foods/list) devem retornar 401 Unauthorized ou 403 Forbidden se nenhum token JWT válido for fornecido no cabeçalho Authorization.
  • Requisições para endpoints protegidos devem ser bem-sucedidas quando um JWT válido é fornecido.

Metadata

Metadata

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions