Добавлено запоминание client_redirect_uri при oauth авторизации

This commit is contained in:
ErickSkrauch 2016-11-05 18:02:46 +03:00
parent fe4e62af39
commit bc2f1d4ce9
5 changed files with 47 additions and 43 deletions

View File

@ -4,6 +4,7 @@ namespace api\controllers;
use api\filters\ActiveUserRule; use api\filters\ActiveUserRule;
use common\components\oauth\Exception\AcceptRequiredException; use common\components\oauth\Exception\AcceptRequiredException;
use common\components\oauth\Exception\AccessDeniedException; use common\components\oauth\Exception\AccessDeniedException;
use common\models\Account;
use common\models\OauthClient; use common\models\OauthClient;
use common\models\OauthScope; use common\models\OauthScope;
use League\OAuth2\Server\Exception\OAuthException; use League\OAuth2\Server\Exception\OAuthException;
@ -108,7 +109,7 @@ class OauthController extends Controller {
/** @var \common\models\OauthClient $clientModel */ /** @var \common\models\OauthClient $clientModel */
$clientModel = OauthClient::findOne($client->getId()); $clientModel = OauthClient::findOne($client->getId());
if (!$account->canAutoApprove($clientModel, $authParams['scopes'])) { if (!$this->canAutoApprove($account, $clientModel, $authParams)) {
$isAccept = Yii::$app->request->post('accept'); $isAccept = Yii::$app->request->post('accept');
if ($isAccept === null) { if ($isAccept === null) {
throw new AcceptRequiredException(); throw new AcceptRequiredException();
@ -197,6 +198,36 @@ class OauthController extends Controller {
$this->getServer()->addGrantType(new RefreshTokenGrant()); $this->getServer()->addGrantType(new RefreshTokenGrant());
} }
/**
* Метод проверяет, может ли текущий пользователь быть автоматически авторизован
* для указанного клиента без запроса доступа к необходимому списку прав
*
* @param Account $account
* @param OauthClient $client
* @param array $oauthParams
*
* @return bool
*/
private function canAutoApprove(Account $account, OauthClient $client, array $oauthParams) : bool {
if ($client->is_trusted) {
return true;
}
/** @var \League\OAuth2\Server\Entity\ScopeEntity[] $scopes */
$scopes = $oauthParams['scopes'];
/** @var \common\models\OauthSession|null $session */
$session = $account->getOauthSessions()->andWhere(['client_id' => $client->id])->one();
if ($session !== null) {
$existScopes = $session->getScopes()->members();
if (empty(array_diff(array_keys($scopes), $existScopes))) {
return true;
}
}
return false;
}
/** /**
* @param array $queryParams * @param array $queryParams
* @param OauthClient $clientModel * @param OauthClient $clientModel

View File

@ -57,11 +57,10 @@ class AccessTokenStorage extends AbstractStorage implements AccessTokenInterface
* @inheritdoc * @inheritdoc
*/ */
public function create($token, $expireTime, $sessionId) { public function create($token, $expireTime, $sessionId) {
$model = new OauthAccessToken([ $model = new OauthAccessToken();
'access_token' => $token, $model->access_token = $token;
'expire_time' => $expireTime, $model->expire_time = $expireTime;
'session_id' => $sessionId, $model->session_id = $sessionId;
]);
if (!$model->save()) { if (!$model->save()) {
throw new Exception('Cannot save ' . OauthAccessToken::class . ' model.'); throw new Exception('Cannot save ' . OauthAccessToken::class . ' model.');

View File

@ -4,6 +4,7 @@ namespace common\components\oauth\Storage\Yii2;
use common\components\oauth\Entity\AuthCodeEntity; use common\components\oauth\Entity\AuthCodeEntity;
use common\components\oauth\Entity\SessionEntity; use common\components\oauth\Entity\SessionEntity;
use common\models\OauthSession; use common\models\OauthSession;
use ErrorException;
use League\OAuth2\Server\Entity\AccessTokenEntity as OriginalAccessTokenEntity; use League\OAuth2\Server\Entity\AccessTokenEntity as OriginalAccessTokenEntity;
use League\OAuth2\Server\Entity\AuthCodeEntity as OriginalAuthCodeEntity; use League\OAuth2\Server\Entity\AuthCodeEntity as OriginalAuthCodeEntity;
use League\OAuth2\Server\Entity\ScopeEntity; use League\OAuth2\Server\Entity\ScopeEntity;
@ -67,7 +68,7 @@ class SessionStorage extends AbstractStorage implements SessionInterface {
*/ */
public function getByAuthCode(OriginalAuthCodeEntity $authCode) { public function getByAuthCode(OriginalAuthCodeEntity $authCode) {
if (!$authCode instanceof AuthCodeEntity) { if (!$authCode instanceof AuthCodeEntity) {
throw new \ErrorException('This module assumes that $authCode typeof ' . AuthCodeEntity::class); throw new ErrorException('This module assumes that $authCode typeof ' . AuthCodeEntity::class);
} }
return $this->getSession($authCode->getSessionId()); return $this->getSession($authCode->getSessionId());
@ -99,11 +100,11 @@ class SessionStorage extends AbstractStorage implements SessionInterface {
])->scalar(); ])->scalar();
if ($sessionId === false) { if ($sessionId === false) {
$model = new OauthSession([ $model = new OauthSession();
'client_id' => $clientId, $model->client_id = $clientId;
'owner_type' => $ownerType, $model->owner_type = $ownerType;
'owner_id' => $ownerId, $model->owner_id = $ownerId;
]); $model->client_redirect_uri = $clientRedirectUri;
if (!$model->save()) { if (!$model->save()) {
throw new Exception('Cannot save ' . OauthSession::class . ' model.'); throw new Exception('Cannot save ' . OauthSession::class . ' model.');

View File

@ -110,34 +110,6 @@ class Account extends ActiveRecord {
return $this->hasMany(AccountSession::class, ['account_id' => 'id']); return $this->hasMany(AccountSession::class, ['account_id' => 'id']);
} }
/**
* Метод проверяет, может ли текущий пользователь быть автоматически авторизован
* для указанного клиента без запроса доступа к необходимому списку прав
*
* @param OauthClient $client
* @param \League\OAuth2\Server\Entity\ScopeEntity[] $scopes
*
* TODO: этому методу здесь не место.
*
* @return bool
*/
public function canAutoApprove(OauthClient $client, array $scopes = []) : bool {
if ($client->is_trusted) {
return true;
}
/** @var OauthSession|null $session */
$session = $this->getOauthSessions()->andWhere(['client_id' => $client->id])->one();
if ($session !== null) {
$existScopes = $session->getScopes()->members();
if (empty(array_diff(array_keys($scopes), $existScopes))) {
return true;
}
}
return false;
}
/** /**
* Выполняет проверку, принадлежит ли этому нику аккаунт у Mojang * Выполняет проверку, принадлежит ли этому нику аккаунт у Mojang
* *

View File

@ -5,14 +5,15 @@ use common\components\redis\Set;
use yii\db\ActiveRecord; use yii\db\ActiveRecord;
/** /**
* This is the model class for table "oauth_access_tokens". * Поля:
*
* @property string $access_token * @property string $access_token
* @property string $session_id * @property string $session_id
* @property integer $expire_time * @property integer $expire_time
* *
* Геттеры:
* @property Set $scopes * @property Set $scopes
* *
* Отношения:
* @property OauthSession $session * @property OauthSession $session
*/ */
class OauthAccessToken extends ActiveRecord { class OauthAccessToken extends ActiveRecord {
@ -26,7 +27,7 @@ class OauthAccessToken extends ActiveRecord {
} }
public function getScopes() { public function getScopes() {
return new Set($this->getDb()->getSchema()->getRawTableName($this->tableName()), $this->access_token, 'scopes'); return new Set(static::getDb()->getSchema()->getRawTableName(static::tableName()), $this->access_token, 'scopes');
} }
public function beforeDelete() { public function beforeDelete() {