Skip to main content

Overview

The Product Distribution Dashboard API currently operates without authentication or authorization mechanisms. The API is designed for internal use within a controlled network environment and relies on CORS (Cross-Origin Resource Sharing) configuration to restrict access to approved frontend applications.
This API does not implement authentication. All endpoints are publicly accessible to clients that satisfy CORS requirements. Do not expose this API to the public internet without implementing proper authentication and authorization.

Current Security Model

The API’s security model consists of:
  1. CORS-based origin restriction: Only requests from the configured frontend URL are allowed
  2. Network-level security: API should be deployed in a private network or behind a firewall
  3. Input validation: Request parameters are validated using Jakarta Bean Validation

No Authentication Headers Required

API requests do not require any authentication headers such as:
  • API keys
  • Bearer tokens
  • Basic authentication credentials
  • Session cookies
All endpoints are accessible without credentials as long as CORS requirements are met.

CORS Configuration

The API implements CORS to control which web applications can make requests to the backend.

Configuration Details

CORS is configured in the CorsConfig class (backend/src/main/java/com/productdistribution/backend/config/CorsConfig.java:1):
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    
    @Value("${app.frontend.url}")
    private String frontendUrl;
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins(frontendUrl)
                .allowedMethods("GET", "POST", "OPTIONS")
                .allowedHeaders("*");
    }
}

CORS Settings

SettingConfigurationDescription
Allowed Origins${app.frontend.url}Only requests from this origin are permitted
Allowed MethodsGET, POST, OPTIONSHTTP methods that can be used
Allowed Headers*All request headers are permitted
Mapped Paths/**CORS applies to all API endpoints
Allow CredentialsNot set (defaults to false)Cookies and authentication headers not supported
Max AgeNot setBrowser caches preflight requests per default policy

Frontend URL Configuration

The allowed frontend URL is configured via the app.frontend.url property in application configuration files:

Development Environment

File: backend/src/main/resources/application-dev.properties:7
app.frontend.url=${APP_FRONTEND_URL}
Typically set to http://localhost:3000 or http://localhost:5173 for local development.

Production Environment

File: backend/src/main/resources/application-prod.properties:22
app.frontend.url=${APP_FRONTEND_URL}
Set via the APP_FRONTEND_URL environment variable to the production frontend domain (e.g., https://app.example.com).

Environment Variable Setup

To configure the frontend URL, set the APP_FRONTEND_URL environment variable:
# Development
export APP_FRONTEND_URL=http://localhost:3000

# Production
export APP_FRONTEND_URL=https://your-frontend-domain.com
The frontend URL must be an exact match. Subdomains, protocols, and ports must match exactly. For example, http://localhost:3000 will not match http://localhost:3001.

Making API Requests

From the Configured Frontend

Requests from the configured frontend application work automatically:
// Fetch example from allowed origin
fetch('http://localhost:8080/api/products')
  .then(response => response.json())
  .then(data => console.log(data));
// Axios example from allowed origin
import axios from 'axios';

const products = await axios.get('http://localhost:8080/api/products');

CORS Preflight Requests

For non-simple requests (e.g., POST with JSON body), browsers automatically send a preflight OPTIONS request:
OPTIONS /api/stock-assignments/distribute HTTP/1.1
Origin: http://localhost:3000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
The server responds with allowed methods and headers:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: *

From Other Origins (Blocked)

Requests from origins other than the configured frontend URL will be blocked:
// Request from http://example.com (not allowed)
fetch('http://localhost:8080/api/products')
  .then(response => response.json())
  .catch(error => {
    // CORS error: No 'Access-Control-Allow-Origin' header present
    console.error('CORS blocked:', error);
  });
Browser console error:
Access to fetch at 'http://localhost:8080/api/products' from origin 'http://example.com' 
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on 
the requested resource.

Security Considerations

Current Limitations

The following security measures are NOT implemented:
  • No user authentication: Cannot identify or verify users
  • No authorization: All clients have full access to all endpoints
  • No rate limiting: Susceptible to abuse and DoS attacks
  • No audit logging: Cannot track who performed actions
  • No API key validation: Cannot revoke access for specific clients
Given the lack of authentication, follow these deployment practices:
  1. Private Network: Deploy the API in a private network not accessible from the public internet
  2. VPN/Firewall: Use VPN or firewall rules to restrict network access
  3. API Gateway: Place an API gateway with authentication in front of the API
  4. HTTPS Only: Always use HTTPS in production to encrypt data in transit
  5. Environment Isolation: Keep development and production environments separate

Data Validation

While authentication is absent, the API implements input validation:
  • Jakarta Bean Validation: Request parameters are validated (see @Valid annotations)
  • Type Safety: Strong typing prevents many injection attacks
  • SQL Injection Protection: JPA/Hibernate provides parameterized queries
Validation errors return 400 Bad Request with detailed error messages (see Error Handling).

Future Authentication Considerations

If authentication is implemented in the future, consider these approaches:

Option 1: JWT Bearer Tokens

Implement JWT (JSON Web Token) authentication:
GET /api/products HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Advantages:
  • Stateless authentication
  • Can include user roles and permissions
  • Widely supported by frontend frameworks
Implementation:
  • Add Spring Security with JWT support
  • Update CORS config to handle Authorization header
  • Implement token validation filter

Option 2: API Key Authentication

Use API keys for service-to-service authentication:
GET /api/products HTTP/1.1
X-API-Key: your-api-key-here
Advantages:
  • Simple to implement
  • Easy to revoke individual keys
  • Suitable for internal services
Implementation:
  • Store API keys in database
  • Add request filter to validate keys
  • Provide key management endpoints

Option 3: OAuth 2.0 / OpenID Connect

Integrate with identity providers (Google, Azure AD, etc.): Advantages:
  • Enterprise-grade security
  • Single sign-on (SSO) support
  • Leverages existing identity infrastructure
Implementation:
  • Add Spring Security OAuth2 client
  • Configure identity provider
  • Update frontend for OAuth flow

CORS Changes for Authentication

When implementing authentication, update CORS configuration:
registry.addMapping("/**")
    .allowedOrigins(frontendUrl)
    .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
    .allowedHeaders("*")
    .allowCredentials(true)  // Enable for cookies/auth headers
    .maxAge(3600);  // Cache preflight for 1 hour

Testing Without Authentication

Using cURL

Test endpoints directly with cURL:
# Get all products
curl http://localhost:8080/api/products

# Get specific warehouse
curl http://localhost:8080/api/warehouses/W001

# Trigger distribution (POST)
curl -X POST http://localhost:8080/api/stock-assignments/distribute
cURL requests bypass CORS restrictions since CORS is a browser-enforced policy.

Using API Testing Tools

Tools like Postman, Insomnia, or Thunder Client can test the API without CORS restrictions:
  1. Set the request URL (e.g., http://localhost:8080/api/products)
  2. Choose the HTTP method (GET, POST)
  3. Send the request - no authentication headers needed

Browser Developer Tools

From the configured frontend application, use browser console:
// Quick test in browser console
await fetch('/api/products').then(r => r.json())

Troubleshooting CORS Issues

Issue: “CORS policy: No ‘Access-Control-Allow-Origin’ header”

Causes:
  • Frontend URL doesn’t match app.frontend.url configuration
  • Protocol mismatch (http vs https)
  • Port mismatch
  • Missing APP_FRONTEND_URL environment variable
Solutions:
  1. Verify APP_FRONTEND_URL environment variable is set correctly
  2. Check application logs for configured frontend URL
  3. Ensure exact match including protocol and port
  4. Restart backend after configuration changes

Issue: “Method not allowed”

Cause: Using HTTP method not in allowed list (PUT, DELETE, PATCH) Solution: Only GET, POST, and OPTIONS are allowed. Use supported methods or update CorsConfig.

Issue: “Credentials mode is ‘include’”

Cause: Frontend sending credentials but allowCredentials not enabled Solution: Either:
  • Remove credentials from frontend request
  • Add .allowCredentials(true) to CORS config

API Overview

Return to API overview and available endpoints

Configuration

Learn about backend configuration options

Error Handling

Understand error response formats

Deployment

Backend deployment guide and security setup

Build docs developers (and LLMs) love