Welcome Guest, Not a member yet? Register   Sign In
Configure CORS for test API
#1

(This post was last modified: 03-27-2025, 12:06 PM by wolverine4277.)

Hi, a few days ago I finished an API and after testing it a little bit I published it for a coworker to test it from his terminal.
The issue is that having the API on a server and the html/javascript that consumes the API appeared the problem with CORS.
If I don't use authorization (Bearer {token}) everything works fine, when I add a filter for JWT it stops working.
From this I started to do the configurations indicated in https://codeigniter.com/user_guide/libraries/cors.html whitout success!

<Cors.php>
PHP Code:
public array $api = [
    'allowedOrigins'         => ['http://localhost'],
    'allowedOriginsPatterns' => [],
    'supportsCredentials'    => false,
    'allowedHeaders'         => ['Authorization''Content-Type'],
    'exposedHeaders'         => [],
    'allowedMethods'         => ['GET''POST''PATCH''PUT''DELETE'],
    'maxAge'                 => 7200,
]; 

<Routes.php>
PHP Code:
$routes->group('', ['filter' => ['cors:api']], static function (RouteCollection $routes): void {
    $routes->resource('client', ['controller' => 'ClientController']);
    $routes->options('client', static function () {}); 
    $routes->options('client/(:any)', static function () {});
}); 
PHP Code:
CodeIgniter v4.6.0 Command Line Tool Server Time2025-03-27 18:20:17 UTC+00:00

+---------+------------------+------+----------------------------------------------+------------------+---------------+
Method  Route            Name Handler                                      Before Filters   After Filters |
+---------+------------------+------+----------------------------------------------+------------------+---------------+
GET     client           »    | \App\Controllers\ClientController::index     authjwt cors:api cors:api      |
GET     client/new       »    | \App\Controllers\ClientController::new       authjwt cors:api cors:api      |
GET     client/(.*)/edit »    | \App\Controllers\ClientController::edit/$1   authjwt cors:api cors:api      |
GET     client/(.*)      »    | \App\Controllers\ClientController::show/$1   authjwt cors:api cors:api      |
POST    client           »    | \App\Controllers\ClientController::create    authjwt cors:api cors:api      |
PATCH   client/(.*)      »    | \App\Controllers\ClientController::update/$authjwt cors:api cors:api      |
PUT     client/(.*)      »    | \App\Controllers\ClientController::update/$authjwt cors:api cors:api      |
DELETE  client/(.*)      »    | \App\Controllers\ClientController::delete/$authjwt cors:api cors:api      |
OPTIONS client           »    | (Closure)                                    authjwt cors:api cors:api      |
OPTIONS client/(.*)      »    | (Closure)                                    authjwt cors:api cors:api      |
+---------+------------------+------+----------------------------------------------+------------------+---------------+ 
Required Before Filters: forcehttps,pagecache
Required After Filters: pagecache, performance, toolbar

Also try something like this:

PHP Code:
$routes->group('', ['filter' => 'cors'], static function (RouteCollection $routes): void {
    $routes->resource('client');

    $routes->options('client', static function () {
        // Implement processing for normal non-preflight OPTIONS requests,
        // if necessary.
        $response response();
        $response->setStatusCode(204);
        $response->setHeader('Allow:''OPTIONS, GET, POST, PUT, PATCH, DELETE');

        return $response;
    });
    $routes->options('client/(:any)', static function () {});
}); 
without luck!
If I comment the line 'authjwt' => ['except' => ['/']], in Filters.php all works fine:


<Filters.php>
PHP Code:
public array $globals = [
    ...
    'authjwt' => ['except' => ['/']], 
    ... 
The code of JWT filter is like this:

<AuthJwtFilter.php>
PHP Code:
namespace App\Filters;

use 
CodeIgniter\HTTP\RequestInterface;
use 
CodeIgniter\HTTP\ResponseInterface;
use 
CodeIgniter\Filters\FilterInterface;

class 
AuthJWTFilter implements FilterInterface
{
    public function before(RequestInterface $request$arguments null)
    {
        // Get the Authorization header
        $authHeader $request->getHeader('Authorization');
        if (!$authHeader) {
            return $this->unauthorizedResponse();
        }

        // Extract the token from the header
        $token str_replace('Bearer '''$authHeader->getValue());

        // Validate the token (you can implement your own validation logic here)
        if (!$this->isValidToken($token)) {
            return $this->unauthorizedResponse();
        }
    }

    public function after(RequestInterface $requestResponseInterface $response$arguments null)
    {
        // Do something after the request is processed
    }

    private function isValidToken($token)
    {
        // Implement your token validation logic here
        // For example, check against a database or decode a JWT

        return $token === env('auth.JWT'); // Testing code, not the real one
    }

    private function unauthorizedResponse()
    {
        return service('response')
            ->setStatusCode(ResponseInterface::HTTP_UNAUTHORIZED)
            ->setJSON(['error' => 'Authentication is required.']);
    }




The code on client es like this:

PHP Code:
    const token 'token'
    fetch('http://mydomain.com/myproject/client', {
        method'GET',
        headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type''application/json'
       }
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('Network response was not ok ' response.statusText);
        }
        return response.json();
    })
    .then(data => {
        const dataDiv document.getElementById('data');
        dataDiv.innerHTML = `<p>${JSON.stringify(data)}</p>`;
    })
    .catch(error => {
        console.error('There was a problem with the fetch operation:'error);
    }); 
Image with error



I'm probably getting something wrong but I don't realize it.
Can someone help me?
Regards.
Reply
#2

(This post was last modified: 03-28-2025, 07:49 AM by luckmoshy.)

Your issue is here you can use '/' to mean that from the / routes,
PHP Code:
'authjwt' => ['except' => ['/']], 
=
Code:
'authjwt' => ['except' => ['api/*']],
Codeigniter First, Codeigniter Then You!!
yekrinaDigitals

Reply
#3

(This post was last modified: 03-28-2025, 11:59 AM by wolverine4277.)

(03-28-2025, 07:48 AM)luckmoshy Wrote: Your issue is here you can use '/' to mean that from the / routes,
PHP Code:
'authjwt' => ['except' => ['/']], 
    =
Code:
'authjwt' => ['except' => ['api/*']],

Hi luckmoshy.
I tried what you suggested but it didn't work.
I recently started using CodeIgniter, so I may be wrong, but I understand that by doing the modification you indicated what I configure is that I do not apply the authjwt filter to everything that starts with api.
The urls that I use are like:

None url have api in the path.
Regards.
Reply
#4

After reviewing the code I think I found the problem, the authjwt filter was applied before the cors filter.
When I modified that the API started to work when the correct jwt was sent (returning code 200) but did not work when an incorrect jwt was sent (returning code 401, which is correct, but I do not have access to the json response as CORS Missing Allow Origin is indicated.
What I did was to modify the function that returns the response adding the headers in the AuthJwtFilter:

PHP Code:
    private function unauthorizedResponse()
    {
        return service('response')
            ->setHeader('Access-Control-Allow-Origin''http://localhost'// Change this to your frontend URL
            ->setHeader('Access-Control-Allow-Headers''Authorization, Content-Type')
            ->setStatusCode(ResponseInterface::HTTP_UNAUTHORIZED)
            ->setJSON(['error' => 'Authentication is required.']);
    


and after that it was working.
Is it right to do it this way?
Or you should access the cors configuration and do something like this?
PHP Code:
        $response service('response');

        // Set CORS headers
        $corsConfig config('CORS');
        $allowedOrigins $corsConfig->api['allowedOrigins'];
        $allowedHeaders $corsConfig->api['allowedHeaders'];
        $origin $request->getHeaderLine('Origin');
        if (in_array($origin$allowedOrigins)) {
            $response->setHeader('Access-Control-Allow-Origin'$origin);
            $response->setHeader('Access-Control-Allow-Headers'$allowedHeaders);
        }

        // Set the response status and message
        return $response
            
->setStatusCode(ResponseInterface::HTTP_UNAUTHORIZED)
            ->setJSON(['error' => 'Authenticatin is required.']); 

Or is a better option? I feel like I'm repeating code...
Regards.

Translated with DeepL.com (free version)
Reply




Theme © iAndrew 2016 - Forum software by © MyBB