Yii Framework Forum

Ajax call from browser - 401 and CORS issue


(David Hagen) #1

I’m getting 401 and CORS if I use the following code and try the api from browser - ajax call. My controller is extended from Controller. As I understood Browser send options header which API doesn’t allow unless it has authorization header.

    public function behaviors()
    {
        
        $behaviors = parent::behaviors();
            $behaviors['authenticator'] = [
                'class' => HttpBearerAuth::className(),
            ];
    
        // remove authentication filter
        $auth = $behaviors['authenticator'];
        unset($behaviors['authenticator']);
        
        // add CORS filter
        $behaviors['corsFilter'] = [
            'class' => \yii\filters\Cors::className(),
        ];
        
        // re-add authentication filter
        $behaviors['authenticator'] = $auth;
        // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
        $behaviors['authenticator']['except'] = ['options'];
        
    
        return $behaviors;
    } 

As soon I add this
if(\Yii::$app->getRequest()->getMethod()!=‘OPTIONS’){
$behaviors[‘authenticator’] = [
‘class’ => HttpBearerAuth::className(),
];
}
I don’t get any error. The above code allowing preflight but is there any security risk??


(Schanz15) #2

Which one? \yii\web\Controller or \yii\rest\Controller?

Anyhow – You do not need to explicitly handle OPTIONS request, the Cors filter already takes care of that. However, whats important is the order of your behaviors. The Cors filter must precede the authentication and verb filter in order to let pass preflight requests.

The way you declared your behaviors array actually looks okay. If you extend from yii\rest\ActiveController you run into problems because there is a verbFilter that precedes the corsFilter and thus leads to a failing preflight request. If you extend from yii\web\Controller I can’t see why the preflight requests are returned with a 401.

Try this:

    public function behaviors()
    {
        $behaviors = parent::behaviors();
        $behaviors['authenticator'] = HttpBearerAuth::class;

        return array_merge([
            'corsFilter' => Cors::class,
        ], $behaviors);
    }