Skip to main content

Overview

The Furniture API implements security measures including CORS configuration, SSL requirements for database connections, and service registry authentication through Netflix Eureka. This document covers the current security implementation and best practices.

CORS Configuration

Cross-Origin Resource Sharing

The API implements CORS to control which frontend applications can access the API endpoints. Configuration: CorsConfig.java
@Configuration
public class CorsConfig implements WebMvcConfigurer {
  @Override
  public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/api/**")
        .allowedOrigins("https://tu-frontend.com")
        .allowedMethods("GET","POST","PUT","DELETE","PATCH","OPTIONS")
        .allowedHeaders("*");
  }
}

CORS Policy Details

Allowed Paths: /api/** (all API endpoints) Allowed Origins: https://tu-frontend.com Allowed Methods:
  • GET - Read operations
  • POST - Create operations
  • PUT - Full update operations
  • DELETE - Delete operations
  • PATCH - Partial update operations
  • OPTIONS - Preflight requests
Allowed Headers: All headers (*) Credentials: Not enabled by default
The wildcard * for allowed headers is permissive. In production, consider restricting to specific headers like Content-Type, Authorization, and X-Requested-With.

Preflight Requests

Browsers automatically send OPTIONS requests before actual requests when:
  • Using methods other than GET, HEAD, or POST
  • Including custom headers
  • Using Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain
The CORS configuration handles these preflight requests automatically.

Production Considerations

The configuration includes a comment in Spanish: “evitar '' en producción” (avoid '' in production), indicating the current setup should be hardened before deployment.
Recommendations for production:
  1. Multiple Origins: Support multiple frontend domains
.allowedOrigins(
    "https://tu-frontend.com",
    "https://www.tu-frontend.com",
    "https://admin.tu-frontend.com"
)
  1. Specific Headers: Limit allowed headers
.allowedHeaders("Content-Type", "Authorization", "X-Request-ID")
  1. Enable Credentials: If using cookies or authentication
.allowCredentials(true)
When allowCredentials(true) is enabled, you cannot use wildcard * for origins. You must specify exact domain names.

Database Security

SSL/TLS Encryption

The PostgreSQL database connection requires SSL encryption:
spring.datasource.url=jdbc:postgresql://...?sslmode=require&channelBinding=require
Security Features:
  • sslmode=require - Forces encrypted connections
  • channelBinding=require - Prevents man-in-the-middle attacks
  • Connection pooling through Neon pooler
All data in transit between the application and database is encrypted using TLS. Neon uses certificate-based authentication for added security.

Database Credentials

The current application.properties file contains hardcoded database credentials. This is a security risk and should be addressed before production deployment.
Recommended approach:
  1. Environment Variables: Store credentials externally
spring.datasource.url=${DATABASE_URL}
  1. Secret Management: Use services like:
    • AWS Secrets Manager
    • HashiCorp Vault
    • Kubernetes Secrets
    • Spring Cloud Config Server
  2. Profile-Specific Configuration: Separate configs for dev/prod
# application-prod.properties
spring.datasource.url=${DATABASE_URL}

Service Discovery Security

Eureka Client Configuration

The microservice registers with Netflix Eureka for service discovery:
eureka.client.service-url.defaultZone=https://furniture-eureka-server.onrender.com/eureka
eureka.instance.prefer-ip-address=true
eureka.client.fetch-registry=true
eureka.client.register-with-eureka=true
Security considerations:
  • Eureka server uses HTTPS protocol
  • Service registration is automatic on startup
  • IP address is preferred for service-to-service communication
The @EnableDiscoveryClient annotation in FurnitureApplication.java enables automatic service registration with Eureka, allowing other microservices to discover this API.

API Security (Not Yet Implemented)

The current implementation does not include authentication or authorization mechanisms. All endpoints are publicly accessible.
For production deployment, consider implementing:

1. Spring Security

Add Spring Security dependency:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2. JWT Authentication

Implement token-based authentication:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/**").authenticated()
            )
            .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
        return http.build();
    }
}

3. OAuth 2.0 / OpenID Connect

Integrate with identity providers:
  • Auth0
  • Okta
  • Keycloak
  • AWS Cognito

4. API Key Authentication

For service-to-service communication:
@Component
public class ApiKeyFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                    HttpServletResponse response, 
                                    FilterChain filterChain) {
        String apiKey = request.getHeader("X-API-Key");
        // Validate API key
    }
}

Actuator Security

Spring Boot Actuator endpoints are currently enabled without security:
spring-boot-starter-actuator
Actuator endpoints can expose sensitive information about your application. They should be secured before production deployment.
Secure actuator endpoints:
# Expose only health endpoint
management.endpoints.web.exposure.include=health,info
management.endpoint.health.show-details=when-authorized
@Configuration
public class ActuatorSecurityConfig {
    @Bean
    public SecurityFilterChain actuatorSecurity(HttpSecurity http) {
        http.requestMatcher(EndpointRequest.toAnyEndpoint())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers(EndpointRequest.to("health")).permitAll()
                .anyRequest().hasRole("ADMIN")
            );
        return http.build();
    }
}

Input Validation

The application includes Hibernate Validator for bean validation:
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>
Use validation annotations on DTOs and entities:
public class ProductRequest {
    @NotBlank(message = "Product name is required")
    @Size(min = 3, max = 100)
    private String name;
    
    @NotNull
    @DecimalMin(value = "0.01")
    private Double price;
    
    @Pattern(regexp = "^[A-Z0-9-]+$")
    private String sku;
}
Validation prevents SQL injection and data integrity issues by rejecting invalid input before it reaches the database layer.

Security Headers

Implement security headers to protect against common web vulnerabilities:
@Configuration
public class SecurityHeadersConfig {
    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers("/swagger-ui/**");
    }
    
    @Bean
    public SecurityFilterChain headers(HttpSecurity http) throws Exception {
        http.headers(headers -> headers
            .contentSecurityPolicy("default-src 'self'")
            .xssProtection(xss -> xss.headerValue(XXssProtectionHeaderWriter.HeaderValue.ENABLED_MODE_BLOCK))
            .frameOptions(frame -> frame.deny())
            .httpStrictTransportSecurity(hsts -> hsts
                .includeSubDomains(true)
                .maxAgeInSeconds(31536000)
            )
        );
        return http.build();
    }
}

Best Practices

Development Environment

  • Use separate database credentials for development
  • Enable detailed error messages for debugging
  • Use HTTP for local development
  • Keep Swagger UI enabled for API testing

Production Environment

  • Never commit credentials to source control
  • Use environment variables or secret managers
  • Enable HTTPS only (disable HTTP)
  • Implement rate limiting
  • Add request logging and monitoring
  • Disable detailed error messages
  • Restrict CORS to specific domains
  • Secure all actuator endpoints
  • Implement authentication and authorization
  • Use API versioning
  • Add request/response encryption for sensitive data
Consider using Spring Profiles (@Profile("prod")) to automatically apply production security configurations when the production profile is active.

Future Security Enhancements

Recommended roadmap for security improvements:
  1. Phase 1: Implement JWT authentication
  2. Phase 2: Add role-based access control (RBAC)
  3. Phase 3: Implement rate limiting and DDoS protection
  4. Phase 4: Add API audit logging
  5. Phase 5: Implement field-level encryption for sensitive data
  6. Phase 6: Add IP whitelisting for admin endpoints
  7. Phase 7: Implement API versioning with security policies per version

Build docs developers (and LLMs) love