Merge branch 'jwt'

This commit is contained in:
ErickSkrauch 2016-02-24 01:15:49 +03:00
commit 36a5f7b359
13 changed files with 60 additions and 23 deletions

View File

@ -14,7 +14,7 @@ return [
'components' => [ 'components' => [
'user' => [ 'user' => [
'identityClass' => \common\models\Account::class, 'identityClass' => \common\models\Account::class,
'enableAutoLogin' => true, 'enableSession' => false,
'loginUrl' => null, 'loginUrl' => null,
], ],
'log' => [ 'log' => [

View File

@ -4,11 +4,15 @@ namespace api\controllers;
use api\models\LoginForm; use api\models\LoginForm;
use Yii; use Yii;
use yii\filters\AccessControl; use yii\filters\AccessControl;
use yii\helpers\ArrayHelper;
class AuthenticationController extends Controller { class AuthenticationController extends Controller {
public function behaviors() { public function behaviors() {
return array_merge(parent::behaviors(), [ return ArrayHelper::merge(parent::behaviors(), [
'authenticator' => [
'except' => ['login'],
],
'access' => [ 'access' => [
'class' => AccessControl::class, 'class' => AccessControl::class,
'rules' => [ 'rules' => [
@ -31,7 +35,7 @@ class AuthenticationController extends Controller {
public function actionLogin() { public function actionLogin() {
$model = new LoginForm(); $model = new LoginForm();
$model->load(Yii::$app->request->post()); $model->load(Yii::$app->request->post());
if (!$model->login()) { if (($jwt = $model->login()) === false) {
return [ return [
'success' => false, 'success' => false,
'errors' => $this->normalizeModelErrors($model->getErrors()), 'errors' => $this->normalizeModelErrors($model->getErrors()),
@ -40,6 +44,7 @@ class AuthenticationController extends Controller {
return [ return [
'success' => true, 'success' => true,
'jwt' => $jwt,
]; ];
} }

View File

@ -3,6 +3,7 @@ namespace api\controllers;
use api\traits\ApiNormalize; use api\traits\ApiNormalize;
use Yii; use Yii;
use yii\filters\auth\HttpBearerAuth;
/** /**
* @property \common\models\Account|null $account * @property \common\models\Account|null $account
@ -12,8 +13,15 @@ class Controller extends \yii\rest\Controller {
public function behaviors() { public function behaviors() {
$parentBehaviors = parent::behaviors(); $parentBehaviors = parent::behaviors();
// Добавляем авторизатор для входа по jwt токенам
$parentBehaviors['authenticator'] = [
'class' => HttpBearerAuth::className(),
];
// xml нам не понадобится // xml нам не понадобится
unset($parentBehaviors['contentNegotiator']['formats']['application/xml']); unset($parentBehaviors['contentNegotiator']['formats']['application/xml']);
// rate limiter здесь не применяется
unset($parentBehaviors['rateLimiter']);
return $parentBehaviors; return $parentBehaviors;
} }

View File

@ -14,13 +14,17 @@ use yii\helpers\ArrayHelper;
class OauthController extends Controller { class OauthController extends Controller {
public function behaviors() { public function behaviors() {
return array_merge(parent::behaviors(), [ return ArrayHelper::merge(parent::behaviors(), [
'authenticator' => [
'except' => ['validate', 'issue-token'],
],
'access' => [ 'access' => [
'class' => AccessControl::class, 'class' => AccessControl::class,
'rules' => [ 'rules' => [
[ [
'actions' => ['validate', 'issue-token'], 'actions' => ['validate', 'issue-token'],
'allow' => true, 'allow' => true,
'roles' => ['?'],
], ],
[ [
'actions' => ['complete'], 'actions' => ['complete'],

View File

@ -5,11 +5,15 @@ use api\models\ConfirmEmailForm;
use api\models\RegistrationForm; use api\models\RegistrationForm;
use Yii; use Yii;
use yii\filters\AccessControl; use yii\filters\AccessControl;
use yii\helpers\ArrayHelper;
class SignupController extends Controller { class SignupController extends Controller {
public function behaviors() { public function behaviors() {
return array_merge(parent::behaviors(), [ return ArrayHelper::merge(parent::behaviors(), [
'authenticator' => [
'except' => ['register', 'confirm'],
],
'access' => [ 'access' => [
'class' => AccessControl::class, 'class' => AccessControl::class,
'rules' => [ 'rules' => [

View File

@ -44,16 +44,14 @@ class LoginForm extends BaseApiForm {
} }
/** /**
* Logs in a user using the provided username and password. * @return bool|string JWT с информацией об аккаунте
*
* @return boolean whether the user is logged in successfully
*/ */
public function login() { public function login() {
if (!$this->validate()) { if (!$this->validate()) {
return false; return false;
} }
return Yii::$app->user->login($this->getAccount(), $this->rememberMe ? 3600 * 24 * 30 : 0); return $this->getAccount()->getJWT();
} }
/** /**

View File

@ -2,6 +2,7 @@
namespace common\models; namespace common\models;
use common\components\UserPass; use common\components\UserPass;
use damirka\JWT\UserTrait;
use Yii; use Yii;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use yii\base\NotSupportedException; use yii\base\NotSupportedException;
@ -34,6 +35,7 @@ use yii\web\IdentityInterface;
* @mixin TimestampBehavior * @mixin TimestampBehavior
*/ */
class Account extends ActiveRecord implements IdentityInterface { class Account extends ActiveRecord implements IdentityInterface {
use UserTrait;
const STATUS_DELETED = -10; const STATUS_DELETED = -10;
const STATUS_REGISTERED = 0; const STATUS_REGISTERED = 0;
@ -64,13 +66,6 @@ class Account extends ActiveRecord implements IdentityInterface {
return static::findOne(['id' => $id]); return static::findOne(['id' => $id]);
} }
/**
* @inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null) {
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
/** /**
* @param string $email * @param string $email
* @return static|null * @return static|null
@ -247,4 +242,22 @@ class Account extends ActiveRecord implements IdentityInterface {
return false; return false;
} }
/**
* @inheritdoc
*/
protected static function getSecretKey() {
return Yii::$app->params['jwtSecret'];
}
/**
* Getter for "header" array that's used for generation of JWT
* @return array JWT Header Token param, see http://jwt.io/ for details
*/
protected static function getHeaderToken() {
return [
'iss' => Yii::$app->request->hostInfo,
'aud' => Yii::$app->request->hostInfo,
];
}
} }

View File

@ -14,13 +14,14 @@
}, },
"minimum-stability": "stable", "minimum-stability": "stable",
"require": { "require": {
"php": ">=5.4.0", "php": ">=5.6.0",
"yiisoft/yii2": ">=2.0.6", "yiisoft/yii2": ">=2.0.6",
"yiisoft/yii2-bootstrap": "*", "yiisoft/yii2-bootstrap": "*",
"yiisoft/yii2-swiftmailer": "*", "yiisoft/yii2-swiftmailer": "*",
"ramsey/uuid": "^3.1", "ramsey/uuid": "^3.1",
"league/oauth2-server": "~4.1.5", "league/oauth2-server": "~4.1.5",
"yiisoft/yii2-redis": "~2.0.0" "yiisoft/yii2-redis": "~2.0.0",
"damirka/yii2-jwt": "dev-master#be29a5b5d7e7d146c13d4374788e02c54cc04138"
}, },
"require-dev": { "require-dev": {
"yiisoft/yii2-codeception": "*", "yiisoft/yii2-codeception": "*",

View File

@ -1,3 +1,4 @@
<?php <?php
return [ return [
'jwtSecret' => 'some-long-secret-key',
]; ];

View File

@ -1,3 +1,4 @@
<?php <?php
return [ return [
'jwtSecret' => 'some-long-secret-key',
]; ];

View File

@ -101,6 +101,7 @@ class LoginCest {
$I->canSeeResponseContainsJson([ $I->canSeeResponseContainsJson([
'success' => true, 'success' => true,
]); ]);
$I->canSeeResponseJsonMatchesJsonPath('$.jwt');
$I->cantSeeResponseJsonMatchesJsonPath('$.errors'); $I->cantSeeResponseJsonMatchesJsonPath('$.errors');
} }
@ -123,6 +124,7 @@ class LoginCest {
$I->canSeeResponseContainsJson([ $I->canSeeResponseContainsJson([
'success' => true, 'success' => true,
]); ]);
$I->canSeeResponseJsonMatchesJsonPath('$.jwt');
$I->cantSeeResponseJsonMatchesJsonPath('$.errors'); $I->cantSeeResponseJsonMatchesJsonPath('$.errors');
} }

View File

@ -11,6 +11,9 @@ class AccountSteps extends FunctionalTester {
$route = new LoginRoute($I); $route = new LoginRoute($I);
$route->login('Admin', 'password_0'); $route->login('Admin', 'password_0');
$I->canSeeResponseIsJson(); $I->canSeeResponseIsJson();
$I->canSeeResponseJsonMatchesJsonPath('$.jwt');
$jwt = $I->grabDataFromResponseByJsonPath('$.jwt')[0];
$I->amBearerAuthenticated($jwt);
} }
} }

View File

@ -39,25 +39,22 @@ class LoginFormTest extends DbTestCase {
$this->specify('get errors and don\'t log in into account with wrong credentials', function () use ($model) { $this->specify('get errors and don\'t log in into account with wrong credentials', function () use ($model) {
expect('model should not login user', $model->login())->false(); expect('model should not login user', $model->login())->false();
expect('error messages should be set', $model->errors)->notEmpty(); expect('error messages should be set', $model->errors)->notEmpty();
expect('user should not be logged in', Yii::$app->user->isGuest)->true();
}); });
} }
public function testLoginByUsernameCorrect() { public function testLoginByUsernameCorrect() {
$model = $this->createModel('Admin', 'password_0'); $model = $this->createModel('Admin', 'password_0');
$this->specify('user should be able to login with correct username and password', function () use ($model) { $this->specify('user should be able to login with correct username and password', function () use ($model) {
expect('model should login user', $model->login())->true(); expect('model should login user', $model->login())->notEquals(false);
expect('error message should not be set', $model->errors)->isEmpty(); expect('error message should not be set', $model->errors)->isEmpty();
expect('user should be logged in', Yii::$app->user->isGuest)->false();
}); });
} }
public function testLoginByEmailCorrect() { public function testLoginByEmailCorrect() {
$model = $this->createModel('admin@ely.by', 'password_0'); $model = $this->createModel('admin@ely.by', 'password_0');
$this->specify('user should be able to login with correct email and password', function () use ($model) { $this->specify('user should be able to login with correct email and password', function () use ($model) {
expect('model should login user', $model->login())->true(); expect('model should login user', $model->login())->notEquals(false);
expect('error message should not be set', $model->errors)->isEmpty(); expect('error message should not be set', $model->errors)->isEmpty();
expect('user should be logged in', Yii::$app->user->isGuest)->false();
}); });
} }