CORS (Cross-Origin Resource Sharing)
What is CORS?
CORS is a security mechanism that allows or restricts web applications running at one origin to access resources from a different origin.
Same-Origin Policy
Same Origin:
https://example.com/page1 → https://example.com/api ✅
Different Origin:
https://example.com → https://api.example.com ❌
https://example.com → http://example.com ❌ (different protocol)
https://example.com → https://example.com:8080 ❌ (different port)CORS Headers
Request Headers
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, AuthorizationResponse Headers
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400Node.js/Express Implementation
// Using cors middleware
const cors = require('cors');
// Allow all origins (development only)
app.use(cors());
// Specific origin
app.use(cors({
origin: 'https://example.com'
}));
// Multiple origins
app.use(cors({
origin: ['https://example.com', 'https://app.example.com']
}));
// Dynamic origin
app.use(cors({
origin: (origin, callback) => {
const allowedOrigins = ['https://example.com', 'https://app.example.com'];
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
}
}));
// Full configuration
app.use(cors({
origin: 'https://example.com',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
allowedHeaders: ['Content-Type', 'Authorization'],
exposedHeaders: ['X-Total-Count', 'X-Page'],
credentials: true,
maxAge: 86400 // 24 hours
}));Manual CORS Implementation
// Without cors middleware
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://example.com');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.header('Access-Control-Allow-Credentials', 'true');
// Handle preflight
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
next();
});.NET Implementation
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("AllowSpecificOrigin",
builder =>
{
builder.WithOrigins("https://example.com")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
// Multiple policies
options.AddPolicy("AllowMultipleOrigins",
builder =>
{
builder.WithOrigins(
"https://example.com",
"https://app.example.com")
.WithMethods("GET", "POST", "PUT", "DELETE")
.WithHeaders("Content-Type", "Authorization")
.WithExposedHeaders("X-Total-Count")
.SetPreflightMaxAge(TimeSpan.FromDays(1));
});
});
}
public void Configure(IApplicationBuilder app)
{
app.UseCors("AllowSpecificOrigin");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
// Per-controller CORS
[EnableCors("AllowSpecificOrigin")]
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
// ...
}Preflight Requests
// Browser sends OPTIONS request before actual request
OPTIONS /api/users
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization
// Server responds
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
// Then browser sends actual request
POST /api/users
Origin: https://example.com
Content-Type: application/json
Authorization: Bearer token123Credentials
// Server allows credentials
app.use(cors({
origin: 'https://example.com',
credentials: true
}));
// Angular - Include credentials
@Injectable()
export class UserService {
getUsers(): Observable<User[]> {
return this.http.get<User[]>(`${this.apiUrl}/users`, {
withCredentials: true
});
}
}
// Fetch API
fetch('https://api.example.com/users', {
credentials: 'include'
});Environment-Specific CORS
// Development - Allow all
if (process.env.NODE_ENV === 'development') {
app.use(cors());
}
// Production - Specific origins
if (process.env.NODE_ENV === 'production') {
app.use(cors({
origin: process.env.ALLOWED_ORIGINS.split(','),
credentials: true
}));
}Route-Specific CORS
// Different CORS for different routes
const publicCors = cors({
origin: '*'
});
const privateCors = cors({
origin: 'https://example.com',
credentials: true
});
app.get('/api/public/data', publicCors, (req, res) => {
res.json({ data: 'public' });
});
app.get('/api/private/data', privateCors, authenticate, (req, res) => {
res.json({ data: 'private' });
});Common CORS Errors
// Error: No 'Access-Control-Allow-Origin' header
// Solution: Add CORS middleware
// Error: Credential is not supported if the CORS header 'Access-Control-Allow-Origin' is '*'
// Solution: Specify exact origin when using credentials
app.use(cors({
origin: 'https://example.com', // Not '*'
credentials: true
}));
// Error: Request header field authorization is not allowed
// Solution: Add header to allowedHeaders
app.use(cors({
allowedHeaders: ['Content-Type', 'Authorization']
}));Angular Proxy (Development)
// proxy.conf.json
{
"/api": {
"target": "http://localhost:3000",
"secure": false,
"changeOrigin": true
}
}// angular.json
{
"serve": {
"options": {
"proxyConfig": "proxy.conf.json"
}
}
}Interview Tips
- Explain CORS: Cross-origin security mechanism
- Show headers: Request and response headers
- Demonstrate implementation: Node.js, .NET
- Discuss preflight: OPTIONS requests
- Mention credentials: withCredentials flag
- Show errors: Common issues and solutions
Summary
CORS allows controlled access to resources from different origins. Configure allowed origins, methods, and headers on server. Browser sends preflight OPTIONS request for complex requests. Use credentials flag for cookies/auth. Set specific origins in production, not wildcard. Handle CORS in middleware or per-route. Essential for web APIs accessed from browsers.
Test Your Knowledge
Take a quick quiz to test your understanding of this topic.