Web Security
Beginner
1 min read
Same-Origin Policy and Why CORS Exists
Example
# Illustrating CORS preflight with curl
# 1. Preflight request (browser sends this automatically before complex requests)
curl -i -X OPTIONS https://api.example.com/users \
-H "Origin: https://app.example.com" \
-H "Access-Control-Request-Method: DELETE" \
-H "Access-Control-Request-Headers: Authorization, Content-Type"
# Expected preflight response (server must include these headers):
# HTTP/2 204
# Access-Control-Allow-Origin: https://app.example.com
# Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
# Access-Control-Allow-Headers: Authorization, Content-Type
# Access-Control-Max-Age: 86400
# Vary: Origin
# 2. Actual DELETE request (browser sends after successful preflight)
curl -i -X DELETE https://api.example.com/users/42 \
-H "Origin: https://app.example.com" \
-H "Authorization: Bearer eyJ..." \
-H "Content-Type: application/json"
# 3. Credentialed request (cookies + CORS)
# Browser only sends cookies cross-origin if:
# a) fetch() uses credentials: 'include'
# b) Server responds with Access-Control-Allow-Credentials: true
# c) Access-Control-Allow-Origin is a specific origin (not '*')
curl -i -X GET https://api.example.com/profile \
-H "Origin: https://app.example.com" \
--cookie "session=abc123"
# Response must have:
# Access-Control-Allow-Origin: https://app.example.com (NOT *)
# Access-Control-Allow-Credentials: true
Related Resources
Web Security Reference
Complete tag & property list
Web Security How-To Guides
Step-by-step practical guides
Web Security Exercises
Practice what you've learned
More in Web Security