CORS Configuration
Overview
Cross-Origin Resource Sharing (CORS) allows the API to accept requests from frontend applications hosted on different domains. This is essential when deploying client applications separately from the API backend, such as on GitHub Pages, Netlify, or other hosting platforms.
Problem Solved
By default, web browsers block cross-origin HTTP requests initiated from scripts for security reasons. Without proper CORS configuration:
- Frontend applications on different domains cannot access the API
- Authentication requests fail
- AJAX calls return CORS errors in browser console
- API endpoints return “No ‘Access-Control-Allow-Origin’ header” errors
Configuration
Environment Variable
Set the CORS_ALLOWED_ORIGINS environment variable in your .env file:
# Single origin
CORS_ALLOWED_ORIGINS=https://metanull.github.io
# Multiple origins (comma-separated)
CORS_ALLOWED_ORIGINS=https://metanull.github.io,https://app.example.com
# Development and production origins
CORS_ALLOWED_ORIGINS=http://localhost:5174,https://metanull.github.io/inventory-management-ui
# Empty value = no origins allowed (default - only same-origin allowed)
CORS_ALLOWED_ORIGINS=
How It Works
The CORS configuration in config/cors.php:
- Reads
CORS_ALLOWED_ORIGINSenvironment variable - Parses comma-separated origin URLs
- Applies CORS headers to API routes (
api/*) and authentication endpoints (sanctum/csrf-cookie) - Enables credential support for cookie-based authentication
CORS headers applied:
Access-Control-Allow-Origin- Allowed origin domainsAccess-Control-Allow-Methods- All HTTP methodsAccess-Control-Allow-Headers- All request headersAccess-Control-Allow-Credentials- Enables cookie/token authentication
Production Deployment
For GitHub Pages Client App
If deploying a client application at https://metanull.github.io/inventory-management-ui/:
CORS_ALLOWED_ORIGINS=https://metanull.github.io
Note: Use the root domain (metanull.github.io), not the full path with subdirectory.
CI/CD Configuration
Add the CORS_ALLOWED_ORIGINS variable to your GitHub environment MWNF-SVR:
- Go to your repository Settings
- Navigate to Environments → MWNF-SVR
- Add environment variable:
- Name:
CORS_ALLOWED_ORIGINS - Value:
https://metanull.github.io
- Name:
The deployment workflow automatically includes this configuration in the .env file.
Multiple Client Applications
For multiple frontend deployments:
# Production, staging, and development clients
CORS_ALLOWED_ORIGINS=https://metanull.github.io,https://staging.example.com,http://localhost:5174
Testing the Configuration
After deployment, verify CORS is working:
- Open browser DevTools Console
- Navigate to your client application
- Make an API request
-
Check Network tab for response headers:
Access-Control-Allow-Origin: https://metanull.github.io Access-Control-Allow-Credentials: true - Verify no CORS errors in Console
Common CORS Origins
# GitHub Pages (user site)
CORS_ALLOWED_ORIGINS=https://username.github.io
# GitHub Pages (project site)
CORS_ALLOWED_ORIGINS=https://username.github.io
# Netlify
CORS_ALLOWED_ORIGINS=https://app-name.netlify.app
# Vercel
CORS_ALLOWED_ORIGINS=https://app-name.vercel.app
# Custom domain
CORS_ALLOWED_ORIGINS=https://app.yourdomain.com
# Multiple environments
CORS_ALLOWED_ORIGINS=https://username.github.io,https://staging.example.com,https://app.example.com
Security Considerations
⚠️ Important: Only allow origins you control. Allowing untrusted origins can lead to:
- Unauthorized API access from malicious sites
- Data exposure to third parties
- CSRF attacks if combined with weak authentication
Best Practices:
- Use specific domain names, not wildcards
- Include protocol (
https://) in origin URLs - Regularly audit allowed origins
- Remove unused origins from configuration
- Use environment-specific configurations (dev vs. prod)
- Never use
*(all origins) in production
Troubleshooting
CORS Error in Browser
Error: “Access to fetch at ‘https://api.example.com’ from origin ‘https://app.example.com’ has been blocked by CORS policy”
Solutions:
- Verify origin is in
CORS_ALLOWED_ORIGINS - Check protocol matches (
httpvshttps) - Ensure no trailing slashes in origin URLs
- Clear Laravel config cache:
php artisan config:clear - Restart web server after configuration changes
Credentials Not Included
Error: “Credentials flag is ‘true’, but the ‘Access-Control-Allow-Credentials’ header is ‘’”
Solutions:
- Verify
supports_credentials => trueinconfig/cors.php - Ensure frontend sends credentials:
axios.get("/api/endpoint", { withCredentials: true }); - Check Sanctum configuration for stateful domains
Preflight Request Fails
Error: “Response to preflight request doesn’t pass access control check”
Solutions:
- Verify
OPTIONSmethod is allowed in CORS config - Check web server allows OPTIONS requests
- Ensure API routes don’t require authentication for preflight
- Test with
curl -X OPTIONSto debug
Mixed Content Errors
Error: “Mixed Content: The page at ‘https://…’ was loaded over HTTPS, but requested an insecure resource”
Solutions:
- Ensure API uses HTTPS in production
- Update
APP_URLto usehttps:// - Configure trusted proxies if behind reverse proxy
- Check that all asset URLs use HTTPS
Advanced Configuration
Custom Headers
Modify config/cors.php to expose custom headers:
'exposed_headers' => ['X-Custom-Header', 'X-Rate-Limit'],
Preflight Caching
Enable preflight caching to reduce OPTIONS requests:
'max_age' => 86400, // Cache for 24 hours
Origin Patterns
For dynamic subdomains, use patterns:
'allowed_origins_patterns' => ['/^https:\/\/.*\.example\.com$/'],
Development vs. Production
Development
# Allow localhost for development
CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:5174,http://127.0.0.1:5173
Production
# Only allow production domains
CORS_ALLOWED_ORIGINS=https://metanull.github.io,https://app.example.com
Environment-Specific .env Files
Use separate .env files for each environment:
.env.local- Development.env.staging- Staging.env.production- Production
API Client Configuration
When using the API from a frontend application:
// Configure API client
import { Configuration, DefaultApi } from "@metanull/inventory-app-api-client";
const config = new Configuration({
basePath: "https://api.example.com",
credentials: "include", // Include cookies/auth tokens
});
const api = new DefaultApi(config);
Ensure your HTTP client sends credentials:
// Axios
axios.defaults.withCredentials = true;
// Fetch
fetch(url, { credentials: "include" });
Related Documentation
- Mozilla CORS Documentation
- Laravel CORS Package
- API Integration Guidelines
- Trusted Proxy Configuration
GitHub Pages Deployment Example
Complete workflow for deploying client app to GitHub Pages:
-
Configure API CORS (this guide):
CORS_ALLOWED_ORIGINS=https://metanull.github.io -
Deploy API backend with updated
.env -
Configure client app with API URL:
VITE_API_BASE_URL=https://api.example.com -
Build and deploy client to GitHub Pages
-
Test API access from deployed app
See GitHub Pages Deployment Guide for client deployment details.