Lesson 85 of 158 – CORS
85%

CORS – Cross-Origin Resource Sharing

CORS stands for Cross-Origin Resource Sharing. It is a browser security mechanism that controls whether a web application can make requests to a server from a different origin.

Note: CORS is mainly enforced by browsers. A React Native application is not subject to browser CORS in the same way as a web application, but understanding CORS is important when your REST API is also used by websites or browser-based applications.

1. What is CORS?

CORS allows a server to specify which origins are permitted to access its resources from a browser.

Browser Application
        ↓
Cross-Origin Request
        ↓
REST API
        ↓
CORS Rules
        ↓
Allow or Reject

The server sends special HTTP response headers that tell the browser whether the request is allowed.

2. What is an Origin?

An origin is made up of three main parts:

  • Protocol
  • Domain
  • Port
https://example.com:443

Protocol → https
Domain  → example.com
Port    → 443

If any of these parts changes, the browser may consider the request to be cross-origin.

3. Same-Origin Request

Suppose your website and API are hosted on the same origin:

Website:
https://example.com

API:
https://example.com/api/students.php

These URLs use the same protocol, domain, and port, so the request is same-origin.

4. Cross-Origin Request

A request becomes cross-origin when the origin is different.

Website:
https://myapp.com

API:
https://api.example.com/students.php

The browser treats these as different origins because the hostnames are different.

5. Why Do Browsers Use CORS?

Browsers implement same-origin protections to prevent a website from freely reading sensitive information from another origin.

CORS provides a controlled way for a server to say:

"This origin is allowed to access my API."

Therefore, CORS is part of browser security rather than an authentication system.

6. The Access-Control-Allow-Origin Header

The most important CORS response header is:

Access-Control-Allow-Origin

For example:

Access-Control-Allow-Origin: https://example.com

This tells the browser that requests from the specified origin may be allowed to access the response.

7. Allowing Any Origin

A server can use the wildcard:

Access-Control-Allow-Origin: *

This means the response is available to requests from any origin, subject to other browser and request restrictions.

For private APIs, avoid using a wildcard automatically. Configure the policy according to your application's requirements.

8. Adding CORS in PHP

A simple PHP API can send a CORS response header:

<?php

header(
    "Access-Control-Allow-Origin: https://example.com"
);

header(
    "Content-Type: application/json"
);

echo json_encode([
    "success" => true
]);

?>

The browser uses the CORS header when deciding whether JavaScript can read the response.

9. Allowing Multiple Origins

You generally do not send multiple origins in a single Access-Control-Allow-Origin header.

Instead, the server can inspect the request's Origin header and return the matching origin when it belongs to an allowlist.

$allowedOrigins = [
    "https://example.com",
    "https://admin.example.com"
];

This provides more control than blindly allowing every origin.

10. Reading the Origin in PHP

PHP can read the request's Origin header:

$origin =
    $_SERVER['HTTP_ORIGIN']
    ?? '';

The API can then compare this value against a predefined allowlist.

11. CORS Allowlist

$allowedOrigins = [
    "https://example.com",
    "https://admin.example.com"
];

$origin =
    $_SERVER['HTTP_ORIGIN']
    ?? '';

if (in_array(
    $origin,
    $allowedOrigins,
    true
)) {

    header(
        "Access-Control-Allow-Origin: "
        . $origin
    );
}

An allowlist is useful when only specific browser applications should access the API.

12. Access-Control-Allow-Methods

CORS can also specify which HTTP methods are allowed.

header(
    "Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS"
);

This tells the browser which methods the server is prepared to accept for cross-origin requests.

13. Access-Control-Allow-Headers

The server can specify which request headers may be used.

header(
    "Access-Control-Allow-Headers: Content-Type, Authorization"
);

This is especially useful for APIs that receive JSON and use Bearer tokens.

14. Content-Type and CORS

A React or browser application may send JSON data using:

Content-Type: application/json

The API can explicitly allow the Content-Type request header:

Access-Control-Allow-Headers:
Content-Type, Authorization

15. Authorization Header

JWT-protected APIs commonly receive:

Authorization: Bearer YOUR_TOKEN

A browser-based application may require the server to allow this request header through CORS.

header(
    "Access-Control-Allow-Headers: "
    . "Content-Type, Authorization"
);

16. What is a Preflight Request?

For some cross-origin requests, the browser first sends an OPTIONS request to ask the server whether the actual request is permitted.

Browser
   ↓
OPTIONS Request
   ↓
API
   ↓
CORS Permission
   ↓
Actual Request

This is called a CORS preflight request.

17. Handling OPTIONS in PHP

A PHP API can handle the OPTIONS request before processing the actual API operation.

if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {

    http_response_code(204);

    exit;
}

The required CORS headers should be sent before this check.

18. Complete Basic CORS Setup

<?php

$origin =
    $_SERVER['HTTP_ORIGIN']
    ?? '';

$allowedOrigins = [
    "http://localhost:3000",
    "https://example.com"
];

if (in_array(
    $origin,
    $allowedOrigins,
    true
)) {

    header(
        "Access-Control-Allow-Origin: "
        . $origin
    );
}

header(
    "Access-Control-Allow-Methods: "
    . "GET, POST, PUT, DELETE, OPTIONS"
);

header(
    "Access-Control-Allow-Headers: "
    . "Content-Type, Authorization"
);

header(
    "Content-Type: application/json"
);

if (
    $_SERVER['REQUEST_METHOD']
    === 'OPTIONS'
) {

    http_response_code(204);
    exit;
}

?>

19. CORS with JSON APIs

A PHP REST API commonly returns JSON:

header(
    "Content-Type: application/json"
);

echo json_encode([
    "success" => true,
    "message" => "API working"
]);

CORS headers and JSON response headers can be sent together.

20. CORS with React Web Application

A browser-based React application may call a different API origin:

React App
http://localhost:3000

        ↓

PHP API
http://localhost/api/

The PHP server must provide an appropriate CORS policy if the browser is expected to allow the frontend to read the API response.

21. CORS and React Native

React Native is not running JavaScript inside a normal browser page in the same way as a web application.

Therefore, browser CORS restrictions generally do not apply to React Native networking in the same way they apply to browser-based JavaScript.

React Native
     ↓
HTTP Request
     ↓
PHP REST API
     ↓
JSON Response

Even so, it is useful to configure CORS correctly if the same API will also be consumed by web applications.

22. Fetch Request from a Browser

fetch(
    "https://api.example.com/students.php"
)
.then(response => response.json())
.then(data => {
    console.log(data);
})
.catch(error => {
    console.log(error);
});

If the API's CORS policy does not allow the browser's origin, the browser may block the JavaScript application from reading the cross-origin response.

23. CORS Error in the Browser

A browser may show a message similar to:

Access to fetch at
'https://api.example.com/...'
from origin
'https://myapp.com'
has been blocked by CORS policy.

This usually means the API's CORS response does not satisfy the browser's requirements for that request.

24. CORS is Not Authentication

CORS should not be used as a replacement for authentication.

CORS
 ↓
Controls Browser Access

Authentication
 ↓
Identifies User

Authorization
 ↓
Checks Permissions

A protected API should still verify JWTs or another authentication mechanism.

25. CORS is Not SQL Injection Protection

CORS does not protect your database from SQL injection.

Your API should still use:

  • Prepared statements
  • Input validation
  • Authentication
  • Authorization
  • Safe error handling

CORS is only one part of the overall API security configuration.

26. Common CORS Mistakes

  • Allowing every origin without considering the application requirements.
  • Forgetting to allow required HTTP methods.
  • Forgetting required request headers.
  • Not handling OPTIONS preflight requests.
  • Trying to solve authentication using CORS.
  • Assuming CORS protects the API from non-browser clients.
  • Using CORS as a replacement for API security.

27. Testing CORS with Postman

Postman can be useful for testing API endpoints and headers. However, Postman is not a browser and therefore does not enforce browser CORS restrictions in the same way.

You can inspect the API response headers:

Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers

For actual browser behavior, test the API from a browser-based application as well.

28. Production CORS Configuration

In production, define the origins that actually need access.

$allowedOrigins = [
    "https://app.example.com",
    "https://admin.example.com"
];

Avoid copying development settings such as localhost origins into production without reviewing them.

29. Complete CORS Request Flow

Browser / Web App
        ↓
Cross-Origin Request
        ↓
PHP REST API
        ↓
Check Origin
        ↓
CORS Response Headers
        ↓
Authentication
        ↓
Validation
        ↓
Database
        ↓
JSON Response
        ↓
Browser

A correctly configured CORS policy allows the browser to communicate with the API while other API security controls continue to protect the application.

30. CORS Summary

CORS controls cross-origin browser access to REST APIs. PHP can send CORS response headers such as Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers.

For React Native applications, browser CORS restrictions generally do not work the same way, but the same API may also need CORS support for web clients.

CORS
 ↓
Browser Cross-Origin Control
 ↓
Allowed Origin
 ↓
Allowed Methods
 ↓
Allowed Headers
 ↓
REST API

📌 Key Points

  • CORS stands for Cross-Origin Resource Sharing.
  • CORS controls cross-origin browser requests.
  • An origin consists of protocol, domain, and port.
  • Access-Control-Allow-Origin controls allowed origins.
  • Access-Control-Allow-Methods specifies allowed methods.
  • Access-Control-Allow-Headers specifies allowed request headers.
  • Some cross-origin requests require an OPTIONS preflight request.
  • PHP can handle OPTIONS requests before processing the actual API request.
  • CORS is not an authentication mechanism.
  • CORS does not prevent SQL injection.
  • React Native is not subject to browser CORS restrictions in the same way as browser JavaScript.
  • Postman does not enforce browser CORS behavior.
  • Production APIs should use an appropriate origin allowlist.
  • CORS should be combined with authentication, authorization, validation, and other security controls.
  • The next lesson will cover file upload APIs.

🧠 Quick Quiz

Question: Which HTTP response header is primarily used to specify which origin can access a resource through a browser?