Yii2 REST api bearer authentication
Solution 1
I had the same case you did. I am using ReactJS
for client dan Yii2 for api.
In your case, check this rule:
[
'class' => 'yii\rest\UrlRule',
'controller' => 'v1/checkins',
'extraPatterns' => [
'GET checkinview/<id:\d+>' => 'checkinview/'
],
]
This code should be:
[
'class' => 'yii\rest\UrlRule',
'controller' => 'v1/checkins',
'tokens' => ['{id}' => '<id:\\w+>'], --> because you stil use ActiveController
'pluralize' => false, --> for disable pluralize
'extraPatterns' => [
'GET checkinview/<id:\d+>' => 'checkinview' --> remove '/' sign
'OPTIONS checkinview/<id:\d+>' => 'options', --> for corsFilter
],
]
Solution 2
- Give me "user.php" for checking more...
- The "CheckinsController" should like below LOCs (don't add more information when you don't control it).
namespace api\modules\v1\controllers;
use yii\rest\ActiveController;
use yii\data\ActiveDataProvider;
use yii\filters\ContentNegotiator;
use api\modules\v1\models\CheckinApi;
use yii\filters\auth\HttpBearerAuth;
use yii\web\Response;
class CheckinsController extends ActiveController
{
public $modelClass = 'common\models\Events';
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBearerAuth::className()
];
return $behaviors;
}
}
- You can refer a manual here: http://budiirawan.com/setup-restful-api-yii2/
- Also can refer this project https://github.com/NguyenDuyPhong/yii2_advanced_api_phong (including database) - It's working very well on my localhost. Hopefully I helped you something!
Admin
Updated on July 15, 2022Comments
-
Admin almost 2 years
I am using Yii2 framework as the backend and react js for the client side. I am trying to create REST api with HTTPBearer authentication but always get a 401 Unauthorized error. I have followed the Yii2 Rest api authentication with no success. I have also implemented findIdentityByAccessToken on user.php and access_token on my sql. My files:-
Folder structure:-
-api
--config
--main.php
--main-local.php
...
--modules
--v1
--controllers
--CheckinsController.php-backend
-common
-frontend ..main.php
<?php $params = array_merge( require(__DIR__ . '/../../common/config/params.php'), require(__DIR__ . '/../../common/config/params-local.php'), require(__DIR__ . '/params.php'), require(__DIR__ . '/params-local.php') ); return [ 'id' => 'app-api', 'basePath' => dirname(__DIR__), 'bootstrap' => ['log'], 'modules' => [ 'v1' => [ 'basePath' => '@app/modules/v1', 'class' => 'api\modules\v1\Module' // here is our v1 modules ] ], 'components' => [ 'user' => [ 'identityClass' => 'common\models\User', 'enableAutoLogin' => false, 'enableSession' => false, 'loginUrl' =>'', ], 'log' => [ 'traceLevel' => YII_DEBUG ? 3 : 0, 'targets' => [ [ 'class' => 'yii\log\FileTarget', 'levels' => ['error', 'warning'], ], ], ], 'request' => [ 'class' => '\yii\web\Request', 'enableCookieValidation' => false, 'parsers' => [ 'application/json' => 'yii\web\JsonParser', ] ], 'urlManager' => [ 'enablePrettyUrl' => true, 'enableStrictParsing' => true, 'showScriptName' => false, 'rules' => [ [ 'class' => 'yii\rest\UrlRule', 'controller' => 'v1/user', 'tokens' => [ '{id}' => '<id:\\w+>' ] ], [ 'class' => 'yii\rest\UrlRule', 'controller' => 'v1/event', 'extraPatterns' => [ 'GET test' => 'test' ], ], [ 'class' => 'yii\rest\UrlRule', 'controller' => 'v1/checkins', 'extraPatterns' => [ 'GET checkinview/<id:\d+>' => 'checkinview/' ], ] ], ] ], 'params' => $params, ];
CheckinsController.php
namespace api\modules\v1\controllers; use yii\rest\ActiveController; use yii\data\ActiveDataProvider; use yii\filters\ContentNegotiator; use api\modules\v1\models\CheckinApi; use yii\filters\auth\HttpBearerAuth; use yii\web\Response; class CheckinsController extends ActiveController { public $modelClass = 'common\models\Events'; public function behaviors() { $behaviors = parent::behaviors(); $behaviors['authenticator'] = [ 'class' => HttpBearerAuth::className() ]; $behaviors['contentNegotiator'] = [ 'class' => ContentNegotiator::className(), 'formats' => [ 'application/json' => Response::FORMAT_JSON, ], ]; return $behaviors; } public function actionCheckinview($id) { // \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; $query = new CheckinApi(); $test = [ 'count' => $query->Checkincount($id), 'checkinid' => $id, 'useridused' => Yii::$app->user->identity->id, ]; return $test;//Testing purpose } } User.php class User extends ActiveRecord implements IdentityInterface { const STATUS_DELETED = 0; const STATUS_ACTIVE = 10; /** * @inheritdoc */ public static function tableName() { return '{{%user}}'; } /** * @inheritdoc */ public function behaviors() { return [ TimestampBehavior::className(), ]; } /** * @inheritdoc */ public function rules() { return [ ['status', 'default', 'value' => self::STATUS_ACTIVE], ['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]], ]; } public function fields() { $fields = parent::fields(); // remove fields that contain sensitive information unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token'],$fields['access_token']); return $fields; } /** * @inheritdoc */ public static function findIdentity($id) { return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]); } /** * @inheritdoc */ public static function findIdentityByAccessToken($token, $type = null) { return static::findOne(['access_token' => $token]); } /** * Finds user by username * * @param string $username * @return static|null */ public static function findByUsername($username) { return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]); } /** * Finds user by password reset token * * @param string $token password reset token * @return static|null */ public static function findByPasswordResetToken($token) { if (!static::isPasswordResetTokenValid($token)) { return null; } return static::findOne([ 'password_reset_token' => $token, 'status' => self::STATUS_ACTIVE, ]); } /** * Finds out if password reset token is valid * * @param string $token password reset token * @return boolean */ public static function isPasswordResetTokenValid($token) { if (empty($token)) { return false; } $expire = Yii::$app->params['user.passwordResetTokenExpire']; $parts = explode('_', $token); $timestamp = (int) end($parts); return $timestamp + $expire >= time(); } /** * @inheritdoc */ public function getId() { return $this->getPrimaryKey(); } /** * @inheritdoc */ public function getAuthKey() { return $this->auth_key; } /** * @inheritdoc */ public function validateAuthKey($authKey) { return $this->getAuthKey() === $authKey; } /** * Validates password * * @param string $password password to validate * @return boolean if password provided is valid for current user */ public function validatePassword($password) { return Yii::$app->security->validatePassword($password, $this->password_hash); } /** * Generates password hash from password and sets it to the model * * @param string $password */ public function setPassword($password) { $this->password_hash = Yii::$app->security->generatePasswordHash($password); } /** * Generates "remember me" authentication key */ public function generateAuthKey() { $this->auth_key = Yii::$app->security->generateRandomString(); } /** * Generates "api" access token */ public function generateAccessToken() { $this->access_token = Yii::$app->security->generateRandomString($length = 16); } /** * Generates new password reset token */ public function generatePasswordResetToken() { $this->password_reset_token = Yii::$app->security- >generateRandomString() . '_' . time(); } /** * Removes password reset token */ public function removePasswordResetToken() { $this->password_reset_token = null; } }
Any help would be much appreciated!! trying to get around this problem for days, but no success. Dont know if it is a simple error done by me!!