Skip to content

Conversation

@OtavioXimarelli
Copy link
Owner

@OtavioXimarelli OtavioXimarelli commented Jun 10, 2025

Resumo por Sourcery

Adiciona autenticação de usuário baseada em JWT com Spring Security e habilita suporte a variáveis de ambiente, atualizando as dependências do projeto e a documentação

Novas Funcionalidades:

  • Implementa endpoints de registro e login de usuário que emitem e validam tokens JWT
  • Protege endpoints de API com um filtro de segurança sem estado usando Spring Security e JWT

Melhorias:

  • Carrega configurações sensíveis de um arquivo .env via um EnvironmentPostProcessor customizado e usa propriedades placeholder
  • Refatora o POM para incluir dependências de security, JWT, dotenv e WebFlux e reorganiza a estrutura do projeto
  • Refatora o modelo de domínio do usuário, o repositório e o serviço para integrar o UserDetails do Spring Security

Build:

  • Reorganiza o POM do Maven e ajusta as configurações do plugin para filtragem de recursos e build do projeto

Documentação:

  • Revisa o README para cobrir a configuração do ambiente, o fluxo de autenticação, a configuração de segurança e os endpoints de API atualizados
Original summary in English

Summary by Sourcery

Add JWT-based user authentication with Spring Security and enable environment variable support, updating project dependencies and documentation

New Features:

  • Implement user registration and login endpoints that issue and validate JWT tokens
  • Secure API endpoints with a stateless security filter using Spring Security and JWT

Enhancements:

  • Load sensitive configuration from a .env file via a custom EnvironmentPostProcessor and use placeholder properties
  • Refactor POM to include security, JWT, dotenv, and WebFlux dependencies and reorganize project structure
  • Refactor user domain model, repository and service to integrate Spring Security's UserDetails

Build:

  • Reorganize Maven POM and adjust plugin configurations for resource filtering and project build

Documentation:

  • Revise README to cover environment setup, authentication flow, security configuration, and updated API endpoints

Summary by CodeRabbit

  • New Features
    • Added user authentication with registration and login endpoints.
    • Integrated JWT-based security for protected API endpoints.
    • Environment variable support introduced for configuration via .env files.
  • Bug Fixes
    • Improved handling of user lookup and authentication errors.
  • Documentation
    • Updated README with security features, environment setup, and revised API documentation.
  • Chores
    • Updated dependencies and configuration for security, JWT, and environment management.
    • Revised application properties to use environment variables and added logging for security.

OtavioXimarelli and others added 30 commits June 1, 2025 23:32
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 10, 2025

Walkthrough

The changes introduce user authentication and security features using Spring Security and JWT. The documentation and configuration are updated to reflect environment variable-driven settings. New classes and DTOs are added for authentication, JWT token management, and security filtering. The project now supports user registration, login, and protected endpoints, with environment variable management via dotenv.

Changes

File(s) Change Summary
README.MD Updated documentation: added security, JWT, environment variable usage, and revised project instructions.
pom.xml Added dependencies: Spring Security, Webflux, JWT, dotenv-java; reorganized sections; removed surefire plugin; Flyway version.
src/main/java/com/otavio/aifoodapp/AiFoodAppApplication.java Minor annotation formatting fix.
src/main/java/com/otavio/aifoodapp/config/CorsConfig.java Removed permissive CORS configuration class and bean.
src/main/java/com/otavio/aifoodapp/config/DotenvEnvironmentPostProcessor.java Added: Loads .env variables into Spring environment early in startup.
src/main/java/com/otavio/aifoodapp/config/SecurityConfig.java Removed old basic security configuration class.
src/main/java/com/otavio/aifoodapp/controller/AuthenticationController.java Added: REST controller for login and registration endpoints, JWT issuance, and password encryption.
src/main/java/com/otavio/aifoodapp/dto/AuthenticationDTO.java
.../LoginResponseDTO.java
.../RegisterDTO.java
Added DTO records for authentication, login response, and registration data.
src/main/java/com/otavio/aifoodapp/model/User.java Added constructor for login, password, role; reformatted getAuthorities method.
src/main/java/com/otavio/aifoodapp/repository/UserRepository.java Changed findByLogin to return UserDetails directly instead of Optional.
src/main/java/com/otavio/aifoodapp/security/SecurityConfig.java New: Defines security filter chain, exposes AuthenticationManager and BCryptPasswordEncoder beans.
src/main/java/com/otavio/aifoodapp/security/SecurityFilter.java New: JWT validation filter, sets authentication in context if token is valid.
src/main/java/com/otavio/aifoodapp/security/TokenService.java New: Service for JWT token generation and validation, uses secret from environment.
src/main/java/com/otavio/aifoodapp/service/AuthorizationService.java Simplified user lookup: direct null check instead of Optional.
src/main/resources/META-INF/spring.factories Registered DotenvEnvironmentPostProcessor as an EnvironmentPostProcessor.
src/main/resources/application.properties Switched to environment variable placeholders for all sensitive/configurable properties; added JWT secret property.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AuthController
    participant AuthManager
    participant UserRepo
    participant TokenService

    Client->>AuthController: POST /api/auth/login (login, password)
    AuthController->>AuthManager: authenticate(login, password)
    AuthManager->>UserRepo: findByLogin(login)
    UserRepo-->>AuthManager: UserDetails
    AuthManager-->>AuthController: Authentication result
    AuthController->>TokenService: generateToken(User)
    TokenService-->>AuthController: JWT token
    AuthController-->>Client: LoginResponseDTO(token, login, role)
Loading
sequenceDiagram
    participant Client
    participant AuthController
    participant UserRepo
    participant PasswordEncoder

    Client->>AuthController: POST /api/auth/register (login, password, role)
    AuthController->>UserRepo: findByLogin(login)
    UserRepo-->>AuthController: UserDetails/null
    alt User exists
        AuthController-->>Client: 400 Bad Request
    else User does not exist
        AuthController->>PasswordEncoder: encode(password)
        PasswordEncoder-->>AuthController: hashedPassword
        AuthController->>UserRepo: save(new User)
        UserRepo-->>AuthController: User
        AuthController-->>Client: 200 OK
    end
Loading
sequenceDiagram
    participant Client
    participant SecurityFilter
    participant TokenService
    participant UserRepo

    Client->>SecurityFilter: Any protected request with Authorization: Bearer <token>
    SecurityFilter->>TokenService: validateToken(token)
    TokenService-->>SecurityFilter: username/exception
    SecurityFilter->>UserRepo: findByLogin(username)
    UserRepo-->>SecurityFilter: UserDetails
    SecurityFilter-->>Client: Proceed if authenticated, else unauthorized
Loading

Poem

🐰
Hop, hop, hooray, security’s here!
JWTs and Spring keep our endpoints clear.
Dotenv whispers secrets, safe and sound,
While passwords get scrambled and tokens abound.
New docs and configs, all tidy and neat—
This bunny’s secure, from ears to feet!
🥕

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai bot changed the title @coderabbitai Add Spring Security with JWT authentication and environment variable support Jun 10, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (10)
src/main/java/com/otavio/aifoodapp/dto/LoginResponseDTO.java (1)

3-3: LGTM! Consider adding field validation.

The record implementation is clean and appropriate for a login response DTO. Consider adding field validation annotations for better data integrity.

+import jakarta.validation.constraints.NotBlank;
+
-public record LoginResponseDTO(String token, String login, String role) {
+public record LoginResponseDTO(
+    @NotBlank String token,
+    @NotBlank String login, 
+    @NotBlank String role
+) {
src/main/resources/application.properties (1)

21-21: Consider reducing logging level for production.

TRACE level logging for Spring Security can be very verbose and may impact performance in production environments.

-logging.level.org.springframework.security=TRACE
+logging.level.org.springframework.security=${LOG_LEVEL_SECURITY:INFO}
src/main/java/com/otavio/aifoodapp/config/DotenvEnvironmentPostProcessor.java (2)

17-17: LGTM! Consider adding error handling and logging.

The dotenv loading implementation is correct with ignoreIfMissing() configuration. Consider adding logging for debugging purposes.

+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 public class DotenvEnvironmentPostProcessor implements EnvironmentPostProcessor {
+    private static final Logger logger = LoggerFactory.getLogger(DotenvEnvironmentPostProcessor.class);
+    
     @Override
     public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
-        Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load();
+        try {
+            Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load();
+            logger.debug("Loading dotenv configuration");
+        } catch (Exception e) {
+            logger.warn("Failed to load .env file: {}", e.getMessage());
+        }

19-20: Consider filtering sensitive variables.

Loading all environment variables with highest priority might override important system properties. Consider filtering or documenting which variables should be loaded.

-        dotenv.entries().forEach(entry -> envMap.put(entry.getKey(), entry.getValue()));
+        dotenv.entries()
+            .stream()
+            .filter(entry -> entry.getKey().startsWith("DB_") || 
+                           entry.getKey().startsWith("JWT_") || 
+                           entry.getKey().startsWith("MARITACA_"))
+            .forEach(entry -> envMap.put(entry.getKey(), entry.getValue()));
src/main/java/com/otavio/aifoodapp/security/SecurityConfig.java (1)

42-50: Consider using more descriptive bean method names.

While the functionality is correct, consider renaming authenticationManagerBean to authenticationManager for consistency with Spring conventions.

@Bean
-public AuthenticationManager authenticationManagerBean(AuthenticationConfiguration authenticationConfiguration) throws Exception {
+public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
    return authenticationConfiguration.getAuthenticationManager();
}
src/main/java/com/otavio/aifoodapp/security/TokenService.java (2)

24-24: Make issuer configurable.

The hardcoded issuer "auth-api" should be configurable to support different environments and deployment scenarios.

Add a configurable issuer property:

@Value("${api.security.token.secret}")
private String secret;
+@Value("${api.security.token.issuer:auth-api}")
+private String issuer;

Then update both generateToken and validateToken methods to use issuer instead of the hardcoded string.


29-31: Improve exception handling specificity.

Wrapping all JWT exceptions in generic RuntimeException reduces error handling capabilities for callers. Consider using more specific custom exceptions or letting the original exceptions propagate.

} catch (JWTCreationException creationException) {
-    throw new RuntimeException("Error while generating token", creationException);
+    throw new IllegalStateException("Failed to generate JWT token", creationException);
}

} catch (JWTVerificationException verificationException) {
-    throw new RuntimeException("Invalid token", verificationException);
+    return null; // or throw a custom InvalidTokenException
}

Also applies to: 42-44

src/main/java/com/otavio/aifoodapp/security/SecurityFilter.java (1)

46-50: Improve token extraction robustness.

The current token extraction could fail if the header doesn't start with "Bearer " exactly. Consider making it more robust.

private String recoverToken(HttpServletRequest request) {
    var authHeader = request.getHeader("Authorization");
-    if (authHeader == null) return null;
-    return authHeader.replace("Bearer ", "");
+    if (authHeader == null || !authHeader.startsWith("Bearer ")) {
+        return null;
+    }
+    return authHeader.substring(7); // "Bearer ".length()
}
README.MD (1)

19-19: Minor grammar correction needed.

Static analysis detected a potential number agreement error in Portuguese.

-- **Spring Boot**: Framework para aplicações Java
+- **Spring Boot**: Framework para aplicações Java

Consider reviewing the Portuguese grammar for consistency throughout the document.

🧰 Tools
🪛 LanguageTool

[grammar] ~19-~19: Possível erro de concordância de número.
Context: ...adas - Spring Boot: Framework para aplicações Java - Spring Data JPA: Persistência de ...

(GENERAL_NUMBER_AGREEMENT_ERRORS)

src/main/java/com/otavio/aifoodapp/controller/AuthenticationController.java (1)

20-35: LGTM - Good use of constructor injection and immutable fields

The class structure follows Spring Boot best practices with proper dependency injection and final field declarations.

Consider removing extra blank lines for cleaner formatting:

 @RestController
 @RequestMapping("/api/auth")
-
 public class AuthenticationController {
-
     private final AuthenticationManager authenticationManager;
-
     private final UserRepository userRepository;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1db51c2 and e513ba5.

📒 Files selected for processing (18)
  • README.MD (1 hunks)
  • pom.xml (1 hunks)
  • src/main/java/com/otavio/aifoodapp/AiFoodAppApplication.java (1 hunks)
  • src/main/java/com/otavio/aifoodapp/config/CorsConfig.java (0 hunks)
  • src/main/java/com/otavio/aifoodapp/config/DotenvEnvironmentPostProcessor.java (1 hunks)
  • src/main/java/com/otavio/aifoodapp/config/SecurityConfig.java (0 hunks)
  • src/main/java/com/otavio/aifoodapp/controller/AuthenticationController.java (1 hunks)
  • src/main/java/com/otavio/aifoodapp/dto/AuthenticationDTO.java (1 hunks)
  • src/main/java/com/otavio/aifoodapp/dto/LoginResponseDTO.java (1 hunks)
  • src/main/java/com/otavio/aifoodapp/dto/RegisterDTO.java (1 hunks)
  • src/main/java/com/otavio/aifoodapp/model/User.java (2 hunks)
  • src/main/java/com/otavio/aifoodapp/repository/UserRepository.java (1 hunks)
  • src/main/java/com/otavio/aifoodapp/security/SecurityConfig.java (1 hunks)
  • src/main/java/com/otavio/aifoodapp/security/SecurityFilter.java (1 hunks)
  • src/main/java/com/otavio/aifoodapp/security/TokenService.java (1 hunks)
  • src/main/java/com/otavio/aifoodapp/service/AuthorizationService.java (1 hunks)
  • src/main/resources/META-INF/spring.factories (1 hunks)
  • src/main/resources/application.properties (1 hunks)
💤 Files with no reviewable changes (2)
  • src/main/java/com/otavio/aifoodapp/config/CorsConfig.java
  • src/main/java/com/otavio/aifoodapp/config/SecurityConfig.java
🧰 Additional context used
🪛 LanguageTool
README.MD

[grammar] ~19-~19: Possível erro de concordância de número.
Context: ...adas - Spring Boot: Framework para aplicações Java - Spring Data JPA: Persistência de ...

(GENERAL_NUMBER_AGREEMENT_ERRORS)

🔇 Additional comments (13)
src/main/java/com/otavio/aifoodapp/AiFoodAppApplication.java (1)

9-9: Minor formatting improvement.

The spacing adjustment in the exclude attribute improves readability.

src/main/resources/META-INF/spring.factories (1)

1-2: Correct Spring Boot environment post-processor registration.

The registration follows Spring Boot's standard conventions for registering custom environment post-processors. This will enable the DotenvEnvironmentPostProcessor to load environment variables early in the application lifecycle.

src/main/java/com/otavio/aifoodapp/model/User.java (2)

37-41: Well-implemented constructor for user creation.

The constructor properly initializes the essential fields for user registration and follows Spring Security UserDetails patterns. This supports the authentication flow nicely.


55-56: Improved readability with explicit conditional formatting.

The multi-line format makes the role-based authority assignment more readable and easier to maintain.

src/main/java/com/otavio/aifoodapp/service/AuthorizationService.java (1)

22-27:

Details

✅ Verification successful

LGTM! Null handling is correct.

The refactoring from Optional to direct null checking is implemented correctly with proper exception handling. This aligns well with the UserRepository interface change.

Verify that all callers of userRepository.findByLogin() are updated to handle the new return type:


🏁 Script executed:

#!/bin/bash
# Description: Search for all usages of findByLogin to ensure consistency with the new signature
rg -A 3 -B 3 "findByLogin"

Length of output: 3013


findByLogin null-handling verified

All usages of userRepository.findByLogin(...) properly handle a null return value:

  • SecurityFilter.java: Checks userExists != null before creating the authentication token.
  • AuthenticationController.java: Uses findByLogin(...) != null to guard against duplicate registrations.
  • AuthorizationService.java: Throws UsernameNotFoundException when user == null.

No further changes are needed.

src/main/java/com/otavio/aifoodapp/repository/UserRepository.java (1)

11-11:

Details

✅ Verification successful

Breaking change: Verify all usages handle null returns.

The method signature change from Optional<UserDetails> to UserDetails removes null-safety guarantees. Ensure all callers properly handle potential null returns.


🏁 Script executed:

#!/bin/bash
# Description: Find all implementations and usages of findByLogin method
ast-grep --pattern 'findByLogin($_)'

Length of output: 38


🏁 Script executed:

#!/bin/bash
# Search for all usages of findByLogin across Java code
rg -n "findByLogin\(" -t java

Length of output: 596


🏁 Script executed:

#!/bin/bash
rg -n -A3 -B3 "findByLogin" src/main/java/com/otavio/aifoodapp/security/SecurityFilter.java
rg -n -A3 -B3 "findByLogin" src/main/java/com/otavio/aifoodapp/service/AuthorizationService.java
rg -n -A3 -B3 "findByLogin" src/main/java/com/otavio/aifoodapp/controller/AuthenticationController.java

Length of output: 1358


All callers already handle null returns – no further action needed

Verification confirms that every usage of findByLogin performs a null check before dereferencing:

  • SecurityFilter.java (line 35): checks userExists != null
  • AuthorizationService.java (line 22): checks user == null and throws if absent
  • AuthenticationController.java (line 51): checks findByLogin(...) != null before proceeding

Since all call sites guard against null, this change does not introduce unchecked NPE risks.

src/main/resources/application.properties (1)

24-24: Ensure JWT secret is properly configured in production.

The default JWT secret value indicates it should be defined externally. Verify that production environments have a strong, unique JWT secret configured.

Consider adding startup validation to ensure the JWT secret is not using the default placeholder value in production.

src/main/java/com/otavio/aifoodapp/security/SecurityConfig.java (2)

17-24: LGTM! Proper dependency injection and configuration setup.

The constructor injection pattern is correctly implemented, ensuring the SecurityFilter dependency is properly managed by Spring.


27-40: Security configuration is well-structured.

The security filter chain correctly:

  • Disables CSRF (appropriate for JWT-based APIs)
  • Sets stateless session management
  • Permits authentication endpoints while protecting others
  • Adds the custom filter in the correct position
pom.xml (2)

31-119: Well-organized dependency structure with good categorization.

The dependencies are properly categorized and the addition of Spring Security and JWT support aligns with the authentication features being implemented.


92-95:

Details

❓ Verification inconclusive

Verify the Flyway version downgrade reason.

The Flyway version was downgraded from 11.8.2 to 11.8.1. Ensure this downgrade is intentional and not due to compatibility issues.


🏁 Script executed:

#!/bin/bash
# Check for known issues with Flyway 11.8.2 and Spring Boot 3.5.0 compatibility
echo "Checking Flyway version compatibility..."
curl -s "https://api.github.com/repos/flyway/flyway/releases" | jq -r '.[] | select(.tag_name | startswith("flyway-")) | .tag_name' | head -5

Length of output: 302


Confirm Flyway version downgrade
It looks like pom.xml now pins Flyway to 11.8.1, even though 11.8.2 (and newer 11.9.x) are available. Unless there’s a documented compatibility issue—e.g. with Spring Boot 3.5.0—please verify this downgrade is intentional. If not, consider upgrading to at least 11.8.2 (or the latest patch) to include important bug fixes.

• File: pom.xml, lines 92–95
• Current snippet:

<artifactId>flyway-database-postgresql</artifactId>
<version>11.8.1</version>
<scope>runtime</scope>

• If no issues are found, update to:

- <version>11.8.1</version>
+ <version>11.8.2</version>
README.MD (1)

15-15: Excellent documentation of new security features.

The README comprehensively documents the new JWT authentication system, including:

  • Clear security architecture explanation
  • Proper warnings about sensitive data
  • Good examples of environment variable configuration
  • Updated API endpoints with authentication details

Also applies to: 43-95

src/main/java/com/otavio/aifoodapp/controller/AuthenticationController.java (1)

1-19: LGTM - Well-organized imports

The package declaration and imports are properly structured and include all necessary dependencies for authentication functionality.

Comment on lines +3 to +4
public record AuthenticationDTO(String login, String password) {
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical security issue: Password exposure in auto-generated toString() method.

Like RegisterDTO, this record will expose the password in its auto-generated toString() method, creating a security vulnerability when this DTO is logged.

Apply the same solution as recommended for RegisterDTO:

-public record AuthenticationDTO(String login, String password) {
-}
+public class AuthenticationDTO {
+    private final String login;
+    private final String password;
+    
+    public AuthenticationDTO(String login, String password) {
+        this.login = login;
+        this.password = password;
+    }
+    
+    public String login() { return login; }
+    public String password() { return password; }
+    
+    @Override
+    public String toString() {
+        return "AuthenticationDTO{login='" + login + "'}";
+    }
+}

Consider adding validation annotations:

public record AuthenticationDTO(
    @NotBlank String login,
    @NotBlank String password
) {}
🤖 Prompt for AI Agents
In src/main/java/com/otavio/aifoodapp/dto/AuthenticationDTO.java at lines 3 to
4, the record's auto-generated toString() method exposes the password, creating
a security risk. To fix this, override the toString() method to exclude the
password field or avoid logging the entire record. Additionally, add validation
annotations like @NotBlank to both login and password fields to ensure they are
not empty or null.

Comment on lines +31 to +44
var token = this.recoverToken(request);
if (token != null) {
var login = tokenService.validateToken(token);
if (login != null && !login.isEmpty()) {
var userExists = userRepository.findByLogin(login);
if (userExists != null) {
UserDetails user = userExists;
var authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
filterChain.doFilter(request, response);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add proper exception handling for token validation.

The current implementation doesn't handle exceptions from tokenService.validateToken(), which could cause the filter to fail unexpectedly. Also, the null check for login could be simplified.

@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    var token = this.recoverToken(request);
    if (token != null) {
-        var login = tokenService.validateToken(token);
-        if (login != null && !login.isEmpty()) {
-            var userExists = userRepository.findByLogin(login);
-            if (userExists != null) {
-                UserDetails user = userExists;
-                var authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
-                SecurityContextHolder.getContext().setAuthentication(authentication);
-            }
-        }
+        try {
+            var login = tokenService.validateToken(token);
+            if (login != null && !login.isEmpty()) {
+                var user = userRepository.findByLogin(login);
+                if (user != null) {
+                    var authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
+                    SecurityContextHolder.getContext().setAuthentication(authentication);
+                }
+            }
+        } catch (RuntimeException e) {
+            // Invalid token, continue without authentication
+        }
    }
    filterChain.doFilter(request, response);
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var token = this.recoverToken(request);
if (token != null) {
var login = tokenService.validateToken(token);
if (login != null && !login.isEmpty()) {
var userExists = userRepository.findByLogin(login);
if (userExists != null) {
UserDetails user = userExists;
var authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
filterChain.doFilter(request, response);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
var token = this.recoverToken(request);
if (token != null) {
try {
var login = tokenService.validateToken(token);
if (login != null && !login.isEmpty()) {
var user = userRepository.findByLogin(login);
if (user != null) {
var authentication = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
} catch (RuntimeException e) {
// Invalid token, continue without authentication
}
}
filterChain.doFilter(request, response);
}
🤖 Prompt for AI Agents
In src/main/java/com/otavio/aifoodapp/security/SecurityFilter.java around lines
31 to 44, add a try-catch block around the call to
tokenService.validateToken(token) to properly handle any exceptions it might
throw. Inside the catch block, log the exception or handle it appropriately to
prevent the filter from failing unexpectedly. Also, simplify the null and empty
check for the login variable by using a utility method or a concise condition.

OtavioXimarelli and others added 2 commits June 10, 2025 14:43
Remove unused import

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/java/com/otavio/aifoodapp/dto/RegisterDTO.java (1)

15-18: Getter names deviate from Java-Bean conventions

Methods named login(), password(), role() will not be recognised automatically by frameworks such as Jackson, MapStruct, Bean Validation, or Spring’s data binding, which expect getLogin(), getPassword(), getRole(). Either rename the methods or annotate them with @JsonProperty("login"), etc., to keep interoperability.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e32551 and 259fcb2.

📒 Files selected for processing (1)
  • src/main/java/com/otavio/aifoodapp/dto/RegisterDTO.java (1 hunks)
🔇 Additional comments (1)
src/main/java/com/otavio/aifoodapp/dto/RegisterDTO.java (1)

21-26: 👍 Good: password excluded from toString()

The custom toString() omits the password, eliminating the leakage flagged in the earlier review.

Comment on lines +5 to +14
public class RegisterDTO {
private final String login;
private final String password;
private final UserRoles role;

public RegisterDTO(String login, String password, UserRoles role) {
this.login = login;
this.password = password;
this.role = role;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Add validation & JSON-safety annotations on incoming data

login, password, and role arrive from the client and should be validated and handled cautiously.
• Add @NotBlank / @Size(min = 8) on password, @NotBlank on login, and @NotNull on role.
• To avoid the password ever being serialized back to a response, mark it @JsonProperty(access = JsonProperty.Access.WRITE_ONLY) or @JsonIgnore.

+import com.fasterxml.jackson.annotation.JsonProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import jakarta.validation.constraints.NotNull;
 ...
-    private final String login;
-    private final String password;
-    private final UserRoles role;
+    @NotBlank
+    private final String login;
+
+    @NotBlank
+    @Size(min = 8)
+    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
+    private final String password;
+
+    @NotNull
+    private final UserRoles role;

🏁 Script executed:

#!/bin/bash
# Display the first 50 lines of RegisterDTO to inspect current imports and annotations
sed -n '1,50p' src/main/java/com/otavio/aifoodapp/dto/RegisterDTO.java

# Search the project for Jackson annotations to confirm JSON mapping library
grep -R "JsonProperty" -n src
grep -R "JsonIgnore" -n src

# Search for existing Jakarta Validation annotations to verify if the dependency is in use
grep -R "NotBlank" -n src
grep -R "Size" -n src
grep -R "jakarta.validation" -n .

Length of output: 907


🏁 Script executed:

#!/bin/bash
# List root files to find build configuration
echo "Root files:"
ls -1 .

# Inspect Maven POM for validation and Jackson dependencies
if [ -f pom.xml ]; then
  echo "---- pom.xml ----"
  grep -n "<artifactId>jakarta.validation-api</artifactId>" -n pom.xml || echo "No Jakarta Validation API dependency found"
  grep -n "jackson" -n pom.xml || echo "No Jackson dependencies found"
fi

# Inspect Gradle build for validation and Jackson dependencies
if [ -f build.gradle ]; then
  echo "---- build.gradle ----"
  grep -n "jakarta.validation" -n build.gradle || echo "No Jakarta Validation in build.gradle"
  grep -n "jackson" -n build.gradle || echo "No Jackson dependencies found in build.gradle"
fi

Length of output: 455


🏁 Script executed:

#!/bin/bash
# Show the dependencies block in pom.xml
echo "---- Dependencies in pom.xml ----"
sed -n '/<dependencies>/,/<\/dependencies>/p' pom.xml

# Search for Spring Boot starter and Jackson dependencies explicitly
echo "---- Searching for Spring Boot starters ----"
grep -n "spring-boot-starter" -n pom.xml || echo "No Spring Boot starters found"

echo "---- Searching for Jackson groupId ----"
grep -n "<groupId>com.fasterxml.jackson</groupId>" -n pom.xml || echo "No Jackson groupId found"

Length of output: 5147


Add Jakarta Validation dependency and field constraints to RegisterDTO

To enforce input validation and prevent password serialization:

• pom.xml
– Add the Spring Boot validation starter to enable @NotBlank, @Size, @NotNull support.

 <dependencies>
     <!-- existing starters -->
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-validation</artifactId>
+    </dependency>
     <!-- other dependencies -->
 </dependencies>

• src/main/java/com/otavio/aifoodapp/dto/RegisterDTO.java
– Import the required Jakarta Validation and Jackson annotations.
– Annotate fields:
@NotBlank on login
@NotBlank + @Size(min=8) + @JsonProperty(access = WRITE_ONLY) on password
@NotNull on role

+import com.fasterxml.jackson.annotation.JsonProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+import jakarta.validation.constraints.NotNull;
 
 public class RegisterDTO {
-    private final String login;
-    private final String password;
-    private final UserRoles role;
+    @NotBlank
+    private final String login;
+
+    @NotBlank
+    @Size(min = 8)
+    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
+    private final String password;
+
+    @NotNull
+    private final UserRoles role;
 
     public RegisterDTO(String login, String password, UserRoles role) {
         this.login = login;
         this.password = password;
         this.role = role;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public class RegisterDTO {
private final String login;
private final String password;
private final UserRoles role;
public RegisterDTO(String login, String password, UserRoles role) {
this.login = login;
this.password = password;
this.role = role;
}
// src/main/java/com/otavio/aifoodapp/dto/RegisterDTO.java
package com.otavio.aifoodapp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.NotNull;
public class RegisterDTO {
@NotBlank
private final String login;
@NotBlank
@Size(min = 8)
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private final String password;
@NotNull
private final UserRoles role;
public RegisterDTO(String login, String password, UserRoles role) {
this.login = login;
this.password = password;
this.role = role;
}
}
🤖 Prompt for AI Agents
In src/main/java/com/otavio/aifoodapp/dto/RegisterDTO.java lines 5 to 14, add
Jakarta Validation and Jackson annotations to enforce input validation and
prevent password serialization. Import @NotBlank, @Size, @NotNull from Jakarta
Validation and @JsonProperty from Jackson. Annotate the login field with
@NotBlank, the password field with @NotBlank, @Size(min=8), and
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY), and the role field with
@NotNull. Also, ensure the pom.xml includes the Spring Boot validation starter
dependency to support these annotations.

@OtavioXimarelli OtavioXimarelli marked this pull request as draft June 10, 2025 18:11
@OtavioXimarelli OtavioXimarelli marked this pull request as ready for review June 10, 2025 18:11
@sourcery-ai
Copy link

sourcery-ai bot commented Jun 11, 2025

🧙 Sourcery está revisando seu pull request!


Dicas e comandos

Interagindo com o Sourcery

  • Acionar uma nova revisão: Comente @sourcery-ai review no pull request.
  • Continuar discussões: Responda diretamente aos comentários de revisão do Sourcery.
  • Gerar um issue do GitHub a partir de um comentário de revisão: Peça ao Sourcery para criar um
    issue a partir de um comentário de revisão respondendo a ele. Você também pode responder a um
    comentário de revisão com @sourcery-ai issue para criar um issue a partir dele.
  • Gerar um título para o pull request: Escreva @sourcery-ai em qualquer lugar no título do
    pull request para gerar um título a qualquer momento. Você também pode comentar
    @sourcery-ai title no pull request para (re)gerar o título a qualquer momento.
  • Gerar um resumo do pull request: Escreva @sourcery-ai summary em qualquer lugar no
    corpo do pull request para gerar um resumo do PR a qualquer momento exatamente onde você
    quiser. Você também pode comentar @sourcery-ai summary no pull request para
    (re)gerar o resumo a qualquer momento.
  • Gerar guia do revisor: Comente @sourcery-ai guide no pull
    request para (re)gerar o guia do revisor a qualquer momento.
  • Resolver todos os comentários do Sourcery: Comente @sourcery-ai resolve no
    pull request para resolver todos os comentários do Sourcery. Útil se você já
    abordou todos os comentários e não quer mais vê-los.
  • Dispensar todas as revisões do Sourcery: Comente @sourcery-ai dismiss no pull
    request para dispensar todas as revisões existentes do Sourcery. Especialmente útil se você
    quiser começar do zero com uma nova revisão - não se esqueça de comentar
    @sourcery-ai review para acionar uma nova revisão!

Personalizando Sua Experiência

Acesse seu painel para:

  • Ativar ou desativar recursos de revisão, como o resumo do pull request gerado pelo Sourcery,
    o guia do revisor e outros.
  • Alterar o idioma da revisão.
  • Adicionar, remover ou editar instruções de revisão personalizadas.
  • Ajustar outras configurações de revisão.

Obtendo Ajuda

Original review guide in English

🧙 Sourcery is reviewing your pull request!


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@OtavioXimarelli OtavioXimarelli deleted the SpringSecurity-implementation branch June 11, 2025 11:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants