Yii2 RESTFULL api browser blocked by CORS policy

Hi,
i have a problem, i use: https://github.com/sirinibin/Yii2-RESTful-API-with-OAuth2?fbclid=IwAR1i5XhcRIov2iT9HPJErVd_FjnYfVoYL5AREOid8QmdDOjmI7K1d-GKMIk

and it works fine, but from browser (fetch from reactNative) i have error:

and

how can i add OPTIONS to all my requests?

Likely it can be done by using application level beforeAction event.

Hi,
in SIteController for you?

class SiteController extends RestController

{

public $enableCsrfValidation=false;

/**

 * @inheritdoc

 */

public function behaviors()

{

    $behaviors = parent::behaviors();       

    return $behaviors + [

        'apiauth' => [

            'class' => Apiauth::className(),

            'exclude' => ['authorize', 'register', 'accesstoken','index'],

        ], 

        'access' => [

            'class' => AccessControl::className(),

            'only' => ['logout', 'signup'],           

            'rules' => [

                [

                    'actions' => ['signup'],

                    'allow' => true,

                    'roles' => ['?'],

                ],

                [

                    'actions' => ['logout', 'me'],

                    'allow' => true,

                    'roles' => ['@'],

                ],

                [

                    'actions' => ['authorize', 'register', 'accesstoken','options'],

                    'allow' => true,

                    'roles' => ['*'],

                    //'actions' => ['options'], // important for cors ie. pre-flight requests                              

                ],

            ],

        ],

        'verbs' => [

            'class' => Verbcheck::className(),

            'actions' => [

                'logout' => ['GET'],

                'authorize' => ['POST'],

                //'options' => ['OPTIONS'],

                'register' => ['POST'],

                'accesstoken' => ['POST'],

                'me' => ['GET'],

            ],

        ],           

        

    ];

}

/**

 * @inheritdoc

 */

public function actions()

{

    return [

        'error' => [

            'class' => 'yii\web\ErrorAction',

        ],

    ];

}

// public function actions() 

// {

//     $actions = parent::actions();

//     $actions['options'] = [

//         'class' => 'yii\rest\OptionsAction',

//         // optional:

//         'collectionOptions' => ['GET', 'POST', 'HEAD', 'OPTIONS'],

//         'resourceOptions' => ['GET', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],

//     ];

//     return $actions;

// }

/**

 * Displays homepage.

 *

 * @return string

 */

public function actionIndex()

{

    Yii::$app->api->sendSuccessResponse(['Yii2 RESTful API with OAuth2']);

    //  return $this->render('index');

}

public function actionRegister()

{

    $model = new SignupForm();

    $model->attributes = $this->request;

    if ($user = $model->signup()) {

        $data=$user->attributes;

        unset($data['auth_key']);

        unset($data['password_hash']);

        unset($data['password_reset_token']);

        Yii::$app->api->sendSuccessResponse($data);

    }

}

public function actionMe()

{

    $data = Yii::$app->user->identity;

    $data = $data->attributes;

    unset($data['auth_key']);

    unset($data['password_hash']);

    unset($data['password_reset_token']);

    Yii::$app->api->sendSuccessResponse($data);

}

public function actionAccesstoken()

{

    if (!isset($this->request["authorization_code"])) {

        Yii::$app->api->sendFailedResponse("Authorization code missing");

    }

    $authorization_code = $this->request["authorization_code"];

    $auth_code = AuthorizationCodes::isValid($authorization_code);

    if (!$auth_code) {

        Yii::$app->api->sendFailedResponse("Invalid Authorization Code");

    }

    $accesstoken = Yii::$app->api->createAccesstoken($authorization_code);

    $data = [];

    $data['access_token'] = $accesstoken->token;

    $data['expires_at'] = $accesstoken->expires_at;

    Yii::$app->api->sendSuccessResponse($data);

}

public function actionAuthorize()

{

    $model = new LoginForm();

    $model->attributes = $this->request;

    if ($model->validate() && $model->login()) {

        $auth_code = Yii::$app->api->createAuthorizationCode(Yii::$app->user->identity['id']);

        $data = [];

        $data['authorization_code'] = $auth_code->code;

        $data['expires_at'] = $auth_code->expires_at;

        Yii::$app->api->sendSuccessResponse($data);

    } else {

        Yii::$app->api->sendFailedResponse($model->errors);

    }

}

public function actionTest()

{

    return $this->render('test');

}

public function actionLogout()

{

    $headers = Yii::$app->getRequest()->getHeaders();

    $access_token = $headers->get('x-access-token');

    if(!$access_token){

        $access_token = Yii::$app->getRequest()->getQueryParam('access-token');

    }

    $model = AccessTokens::findOne(['token' => $access_token]);

    if ($model->delete()) {

        Yii::$app->api->sendSuccessResponse(["Logged Out Successfully"]);

    } else {

        Yii::$app->api->sendFailedResponse("Invalid Request");

    }

}

}

or in RestController?

class RestController extends Controller

{

public $request;

public $enableCsrfValidation = false;

public $headers;



public function behaviors()

{

    $behaviors = parent::behaviors();

    // $behaviors['authenticator'] = [

    //     'class' => \yii\filters\auth\HttpBearerAuth::className(),

    // ];

    // // remove authentication filter

    // $auth = $behaviors['authenticator'];

    // unset($behaviors['authenticator']);

    $behaviors['corsFilter'] = [

        'class' => \yii\filters\Cors::className(),

        'cors' => [

            'Origin' => ['*'],

             'Access-Control-Allow-Origin' => ['*', 'http://10.10.10.79:8080','http://localhost:19006'],

            'Access-Control-Request-Method' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'],

            'Access-Control-Request-Headers' => ['*'],

            'Access-Control-Allow-Credentials' => null,

            'Access-Control-Max-Age' => 86400,

            'Access-Control-Expose-Headers' => []

        ]

    ];

    // // re-add authentication filter

    // $behaviors['authenticator'] = $auth;

    // // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)

    // $behaviors['authenticator']['except'] = ['options'];

    return $behaviors;

}

public function init()

{

    $this->request = json_decode(file_get_contents('php://input'), true);

    if($this->request&&!is_array($this->request)){

        Yii::$app->api->sendFailedResponse(['Invalid Json']);

    }

}

}

thanks

No, I mean application:

'on beforeAction' => function ($event) {
    // send CORS headers here
    echo "Hello";
},
1 Like

Hi,
i comment
Yii::$app->api->sendFailedResponse
on the backend\behaviours\Verbcheck and it works:

even if it’s not the best in my opinion.
In your opinion, is that enough?

Thanks and congratulations for your job

I don’t know. That’s your custom code, not part of the framework.

1 Like

Hi, solved:

Personalize Cors.php

    {
        $this->request = $this->request ?: Yii::$app->getRequest();
        $this->response = $this->response ?: Yii::$app->getResponse();

        $this->overrideDefaultSettings($action);

        $requestCorsHeaders = $this->extractHeaders();
        $responseCorsHeaders = $this->prepareHeaders($requestCorsHeaders);
        $this->addCorsHeaders($this->response, $responseCorsHeaders);

        if ($this->request->isOptions && $this->request->headers->has('Access-Control-Request-Method')) {
            // it is CORS preflight request, respond with 200 OK without further processing
            $this->response->setStatusCode(200);
            return false;
        }

        return true;
    }

thanks