1084

How to add CORS for API

Comments for “How to add CORS for API”
 

Posted by udiaz60 on Monday 1st July 2024 at 20:39 GMT

Helo,
I'm trying to consume the api from a React app to learn but I can't consume it through CORS. How can I add cors headers in each request.
Console Log Browser:
Cross-origin request blocked: The same-origin policy does not allow reading the remote resource at http://localhost/genesis/api/get/paises. (Reason: missing CORS ‘Access-Control-Allow-Origin’ header.) Status code: 400
Thanks in advance.

udiaz60

User Level: Guest

Date Joined: 24/05/2022

Posted by sasin91 on Saturday 6th July 2024 at 15:43 GMT

Seems like there is no direct support for CORS on the API endpoints from what i can tell.

I made a PR to add this, https://github.com/trongate/trongate-framework/pull/187

sasin91

User Level: Guest

Date Joined: 13/09/2022

Posted by DaFa on Sunday 7th July 2024 at 01:04 GMT

Hi guys,

Thank you sasin91 for your solution. However, I'm a little concerned about the security can of worms you may have opened here.

1. Allowing All Origins ('*'): This can be risky, especially if the API handles sensitive data or operations. It enables any external domain to access the API, which can lead to Cross-Site Request Forgery (CSRF) and other attacks.

2. Wildcard Handling: The code attempts to handle wildcard origins, but this can be complex and error-prone. Incorrect handling can unintentionally expose the API to unintended origins.

3. Credentials (`CORS_ALLOWED_CREDENTIALS`): Allowing credentials with '*' for origins is problematic. If `Access-Control-Allow-Origin` is set to '*', `Access-Control-Allow-Credentials` cannot be `true` as per the CORS specification. This setting can lead to security vulnerabilities by exposing user credentials to all origins.

What do you think about:
config.php
define('CORS_ENABLED', true);
define('CORS_ALLOWED_ORIGINS', 'https://trusteddomain.com, https://subdomain.trusteddomain.com');
define('CORS_ALLOWED_METHODS', 'GET, POST, PUT, DELETE, OPTIONS');
define('CORS_ALLOWED_HEADERS', 'X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding');
define('CORS_ALLOWED_CREDENTIALS', true);

Use of Environment Variable:
// Example of using environment variables for CORS configuration
define('CORS_ENABLED', getenv('CORS_ENABLED') === 'true' ? true : false);
define('CORS_ALLOWED_ORIGINS', getenv('CORS_ALLOWED_ORIGINS'));
define('CORS_ALLOWED_METHODS', getenv('CORS_ALLOWED_METHODS'));
define('CORS_ALLOWED_HEADERS', getenv('CORS_ALLOWED_HEADERS'));
define('CORS_ALLOWED_CREDENTIALS', getenv('CORS_ALLOWED_CREDENTIALS') === 'true' ? true : false);
In this example, you would set environment variables (CORS_ENABLED, CORS_ALLOWED_ORIGINS, CORS_ALLOWED_METHODS, CORS_ALLOWED_HEADERS, CORS_ALLOWED_CREDENTIALS) in your server's configuration or .env file for each environment.

There would also be a need to work on wildcard handling to make it more robust and thoroughly tested or even remove wildcards altogether. This is an untested sample block of code from GPT4-o
// Example of improved wildcard handling logic
if (!empty($_SERVER['HTTP_ORIGIN'])) {
    $origin = $_SERVER['HTTP_ORIGIN'];
    $allowedOrigins = explode(',', CORS_ALLOWED_ORIGINS);

    $isOriginAllowed = false;
    foreach ($allowedOrigins as $allowedOrigin) {
        if (strpos($allowedOrigin, '*') === false) {
            // Exact match
            if ($origin === $allowedOrigin) {
                $isOriginAllowed = true;
                break;
            }
        } else {
            // Wildcard match
            $allowedOriginPattern = str_replace('*', '.*', preg_quote($allowedOrigin));
            if (preg_match('/^' . $allowedOriginPattern . '$/', $origin)) {
                $isOriginAllowed = true;
                break;
            }
        }
    }

    if ($isOriginAllowed) {
        header('Access-Control-Allow-Origin: ' . $origin);
    } else {
        header('Access-Control-Allow-Origin: ' . $allowedOrigins[0]);
    }
}

And a suggestion to separate configuration for credentials to ensure that `Access-Control-Allow-Credentials` is only enabled for trusted origins.
// Example of handling CORS credentials separately
if (defined('CORS_ALLOWED_CREDENTIALS') && CORS_ALLOWED_CREDENTIALS === true) {
    if (defined('CORS_ALLOWED_ORIGINS') && CORS_ALLOWED_ORIGINS !== '*') {
        // Only set credentials header for specific trusted origins
        if (in_array($origin, explode(',', CORS_ALLOWED_ORIGINS))) {
            header('Access-Control-Allow-Credentials: true');
        } else {
            header('Access-Control-Allow-Credentials: false');
        }
    } else {
        header('Access-Control-Allow-Credentials: true');
    }
}
In this example, `Access-Control-Allow-Credentials` is only set to `true` when `CORS_ALLOWED_CREDENTIALS` is enabled and the origin is explicitly listed in `CORS_ALLOWED_ORIGINS` (if not set to '*'). This ensures credentials are only sent to trusted origins, enhancing security.
Founding Member

DaFa

User Level: Founding Member

Date Joined: 30/11/2018

×