codeigniter4 / CodeIgniter4

Open Source PHP Framework (originally from EllisLab)
https://codeigniter.com/
MIT License
5.4k stars 1.9k forks source link

Bug: CORS Filter issue #6185

Closed shishamo closed 2 years ago

shishamo commented 2 years ago

PHP Version

7.4

CodeIgniter4 Version

4.2.1

CodeIgniter4 Installation Method

Manual (zip or tar.gz)

Which operating systems have you tested for this bug?

macOS

Which server did you use?

apache

Database

Mariadb

What happened?

Set a Cors filter in $globals before filter It was working before but filter doesn't runs work the new version of CI

Doesn't work even setting $multipleFilters and/or $autoRoutesImproved on true.

Only works when set "not recommended" $routes->setAutoRoute(true); in Routes.php

Steps to Reproduce

Set filter as below

public function before(RequestInterface $request, $arguments = null) {
        $response = service('response');

        // allow origin
        $response->setHeader('Access-Control-Allow-Origin', '*');

        // allow headers
        $response->setHeader('Access-Control-Allow-Headers', [
            'Authorization',
            'Content-Type',
            'X-Api-Key',
            'X-Requested-With',
        ]);

        // allow methods
        $response->setHeader('Access-Control-Allow-Methods', [
            'OPTIONS',
            'GET',
            'POST',
            'PUT',
            'DELETE',
        ]);

        $response->setHeader('Access-Control-Allow-Credentials', 'true');
        $response->setHeader('Access-Control-Max-Age', '3600');

        if ($request->getMethod() === 'options') {
            $response->send();

            exit();
        }
}

Expected Output

Doesn't show Cors error when call Api

Anything else?

No response

kenjis commented 2 years ago

Set a Cors filter in $globals before filter

How did you set? Can you show us exact code?

It was working before but filter doesn't runs work the new version of CI

What did you get? Error message? And the page can be accessible from the same origin?

kenjis commented 2 years ago

It seems your CORS filter is broken.

$response->setHeader('Access-Control-Allow-Origin', '*');
$response->setHeader('Access-Control-Allow-Credentials', 'true');
shishamo commented 2 years ago

@kenjis thanks for your answer

How did you set? Can you show us exact code?

I set the filter as below

/**
 * Configures aliases for Filter classes to
 * make reading things nicer and simpler.
 *
 * @var array
 */
public $aliases = [
    'csrf'          => CSRF::class,
    'toolbar'       => DebugToolbar::class,
    'honeypot'      => Honeypot::class,
    'invalidchars'  => InvalidChars::class,
    'secureheaders' => SecureHeaders::class,
    'cors'          => Cors::class,
];

/**
 * List of filter aliases that are always
 * applied before and after every request.
 *
 * @var array
 */
public $globals = [
    'before' => [
        // 'honeypot',
        // 'csrf',
        // 'invalidchars',
        'cors',
    ],
    'after' => [
        // 'toolbar',
        // 'honeypot',
        // 'secureheaders',
    ],
];

What did you get? Error message?

I have a Cors policy error message as following attaching file

Capture d’écran 2022-06-26 à 08 55 21

And the page can be accessible from the same origin?

Yes i can, the problem looks to be than CI doesn't run the filter

It seems your CORS filter is broken.

I am sorry i don't get where the CORS filter is broken?

iRedds commented 2 years ago
  1. Don't use exit()
    
    if ($request->getMethod() === 'options') {
    -   $response->send();
kenjis commented 2 years ago

I am sorry i don't get where the CORS filter is broken?

Basically you should not use *:

$response->setHeader('Access-Control-Allow-Origin', '*');

You should set your site. Because * means you allow access from anywhere. CORS is a security mechanism. It is like just disabling CORS protection.

And credential is not supported if the CORS header Access-Control-Allow-Origin is *. https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials Because it is too dangerous.

I recommend you learn what CORS is. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

kenjis commented 2 years ago

As iRedds says, it seems you did not define a route for the HTTP OPTIONS method.

shishamo commented 2 years ago

@kenjis

Basically you should not use $response->setHeader('Access-Control-Allow-Origin', '*');

Oh i get it, i put that for my tests but you are right, i shouldn't allow all origins.

@iRedds

You must have a route for the HTTP OPTIONS method.

After adding a route for the OPTIONS method it works properly, thank you very much.

Don't use exit()

I've removed that part, thanks for your help

devslimbr commented 2 years ago

I have the same problem. What would it be "You must have a route for the HTTP OPTIONS method."?

kenjis commented 2 years ago

It means HTTP verb OPTIONS. See https://codeigniter4.github.io/CodeIgniter4/incoming/routing.html#setting-routing-rules

devslimbr commented 2 years ago

Thank You!

Would it add this? $routes->options('(:any)', '', ['filter' => 'cors']);

kenjis commented 2 years ago

If the filter returns correct responses, yes. See https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS