1
votes

I am trying to use ajax request in reactJs to fetch a resource that require authentication from Bearer Auth in Yii2.

Request Headers

Accept: /
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
Access-Control-Request-Headers: authorization
Access-Control-Request-Method: GET
Connection: keep-alive
Host: localhost
Origin: http://localhost:8110
Referer: http://localhost:8110/
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36

Response Headers

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS
Access-Control-Allow-Origin: http://localhost:8110
Connection: Keep-Alive
Content-Length: 150
Content-Type: application/json; charset=UTF-8
Date: Fri, 21 Apr 2017 10:36:27 GMT
Keep-Alive: timeout=5, max=99
Server: Apache/2.4.25 (Ubuntu)
Www-Authenticate: Bearer realm="api"

This is my behavior method in yii2 framework

public function behaviors()
  {
        $behaviors = parent::behaviors();
        unset($behaviors['authenticator']);
        return [
                [
                    'class' => 'yii\filters\ContentNegotiator',
                    'only' => ['view', 'index', 'filters', 'slug', 'shortlist'],  // in a controller
                    // if in a module, use the following IDs for user actions
                    'formats' => [
                        'application/json' => Response::FORMAT_JSON,
                    ],
                ],
                'corsFilter' => [
                    'class' => \yii\filters\Cors::className(),
                    'cors' => [
                        'Origin' => ['*'],
                        'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'OPTIONS'],
                        'Access-Control-Request-Headers' => ['*'],
                        'Access-Control-Allow-Credentials' => true,
                        ],
                ],
                'authenticator' => [
                        'class' => \yii\filters\auth\HttpBearerAuth::className(),
                        'except' => ['options'],
                ],
        ];
  }

I know this some issue related to CORS because the same request is working fine with Postman and cURL(from terminal) with the same token, reactjs and ajax showing the same error.

1

1 Answers

1
votes

Your mistake is at:

'except' => ['options'],

Class "HttpBearerAuth" inherits yii\base\ActionFilter which public property "$except" according to the documentation defines a "list of action IDs that this filter should not apply to". Not the http methods. So the above will not except a preflight request from "authenticator", but to the actionOptions() which is not what you want.

What you should do is avoid returning a 401 http error for an OPTIONS http request(which causes your error), and just return a 200 empty response. You could do this by adding:

public function beforeAction($action)
{
    //your code

    if (Yii::$app->getRequest()->getMethod() === 'OPTIONS') {
        parent::beforeAction($action);
        Yii::$app->getResponse()->getHeaders()->set('Content-Type', 'text/plain');
        Yii::$app->end();
    }

    return parent::beforeAction($action);
}