mirror of
https://github.com/elyby/accounts.git
synced 2024-11-30 02:32:26 +05:30
Хранилище access_token вынесено в redis
Переписана логика связи моделей для oAuth процесса
This commit is contained in:
parent
4f259a9dc7
commit
422d5c4fd4
@ -10,9 +10,9 @@ use yii\web\IdentityInterface;
|
||||
use yii\web\UnauthorizedHttpException;
|
||||
|
||||
/**
|
||||
* @property Account $account
|
||||
* @property OauthClient $client
|
||||
* @property OauthSession $session
|
||||
* @property Account $account
|
||||
* @property OauthClient $client
|
||||
* @property OauthSession $session
|
||||
* @property OauthAccessToken $accessToken
|
||||
*/
|
||||
class Identity implements IdentityInterface {
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace api\components\OAuth2\Entities;
|
||||
|
||||
use api\components\OAuth2\Storage\SessionStorage;
|
||||
use ErrorException;
|
||||
use League\OAuth2\Server\Entity\SessionEntity as OriginalSessionEntity;
|
||||
|
||||
class AccessTokenEntity extends \League\OAuth2\Server\Entity\AccessTokenEntity {
|
||||
@ -11,6 +13,10 @@ class AccessTokenEntity extends \League\OAuth2\Server\Entity\AccessTokenEntity {
|
||||
return $this->sessionId;
|
||||
}
|
||||
|
||||
public function setSessionId($sessionId) {
|
||||
$this->sessionId = $sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
* @return static
|
||||
@ -22,4 +28,17 @@ class AccessTokenEntity extends \League\OAuth2\Server\Entity\AccessTokenEntity {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSession() {
|
||||
if ($this->session instanceof OriginalSessionEntity) {
|
||||
return $this->session;
|
||||
}
|
||||
|
||||
$sessionStorage = $this->server->getSessionStorage();
|
||||
if (!$sessionStorage instanceof SessionStorage) {
|
||||
throw new ErrorException('SessionStorage must be instance of ' . SessionStorage::class);
|
||||
}
|
||||
|
||||
return $sessionStorage->getById($this->sessionId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -22,4 +22,8 @@ class AuthCodeEntity extends \League\OAuth2\Server\Entity\AuthCodeEntity {
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSessionId(string $sessionId) {
|
||||
$this->sessionId = $sessionId;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,44 @@
|
||||
<?php
|
||||
namespace api\components\OAuth2\Entities;
|
||||
|
||||
use api\components\OAuth2\Storage\SessionStorage;
|
||||
use ErrorException;
|
||||
use League\OAuth2\Server\Entity\SessionEntity as OriginalSessionEntity;
|
||||
|
||||
class RefreshTokenEntity extends \League\OAuth2\Server\Entity\RefreshTokenEntity {
|
||||
|
||||
private $sessionId;
|
||||
|
||||
public function isExpired() : bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getSession() : SessionEntity {
|
||||
if ($this->session instanceof SessionEntity) {
|
||||
return $this->session;
|
||||
}
|
||||
|
||||
$sessionStorage = $this->server->getSessionStorage();
|
||||
if (!$sessionStorage instanceof SessionStorage) {
|
||||
throw new ErrorException('SessionStorage must be instance of ' . SessionStorage::class);
|
||||
}
|
||||
|
||||
return $sessionStorage->getById($this->sessionId);
|
||||
}
|
||||
|
||||
public function getSessionId() : int {
|
||||
return $this->sessionId;
|
||||
}
|
||||
|
||||
public function setSession(OriginalSessionEntity $session) {
|
||||
parent::setSession($session);
|
||||
$this->setSessionId($session->getId());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setSessionId(int $sessionId) {
|
||||
$this->sessionId = $sessionId;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,12 @@
|
||||
namespace api\components\OAuth2\Grants;
|
||||
|
||||
use api\components\OAuth2\Entities;
|
||||
use ErrorException;
|
||||
use League\OAuth2\Server\Entity\ClientEntity as OriginalClientEntity;
|
||||
use League\OAuth2\Server\Entity\RefreshTokenEntity as OriginalRefreshTokenEntity;
|
||||
use League\OAuth2\Server\Event;
|
||||
use League\OAuth2\Server\Exception;
|
||||
use League\OAuth2\Server\Util\SecureKey;
|
||||
|
||||
class RefreshTokenGrant extends \League\OAuth2\Server\Grant\RefreshTokenGrant {
|
||||
|
||||
@ -19,4 +25,126 @@ class RefreshTokenGrant extends \League\OAuth2\Server\Grant\RefreshTokenGrant {
|
||||
return new Entities\SessionEntity($this->server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Метод таки пришлось переписать по той причине, что нынче мы храним access_token в redis с expire значением,
|
||||
* так что он может банально несуществовать на тот момент, когда к нему через refresh_token попытаются обратиться.
|
||||
* Поэтому мы расширили логику RefreshTokenEntity и она теперь знает о сессии, в рамках которой была создана
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function completeFlow() {
|
||||
$clientId = $this->server->getRequest()->request->get('client_id', $this->server->getRequest()->getUser());
|
||||
if (is_null($clientId)) {
|
||||
throw new Exception\InvalidRequestException('client_id');
|
||||
}
|
||||
|
||||
$clientSecret = $this->server->getRequest()->request->get(
|
||||
'client_secret',
|
||||
$this->server->getRequest()->getPassword()
|
||||
);
|
||||
if ($this->shouldRequireClientSecret() && is_null($clientSecret)) {
|
||||
throw new Exception\InvalidRequestException('client_secret');
|
||||
}
|
||||
|
||||
// Validate client ID and client secret
|
||||
$client = $this->server->getClientStorage()->get(
|
||||
$clientId,
|
||||
$clientSecret,
|
||||
null,
|
||||
$this->getIdentifier()
|
||||
);
|
||||
|
||||
if (($client instanceof OriginalClientEntity) === false) {
|
||||
$this->server->getEventEmitter()->emit(new Event\ClientAuthenticationFailedEvent($this->server->getRequest()));
|
||||
throw new Exception\InvalidClientException();
|
||||
}
|
||||
|
||||
$oldRefreshTokenParam = $this->server->getRequest()->request->get('refresh_token', null);
|
||||
if ($oldRefreshTokenParam === null) {
|
||||
throw new Exception\InvalidRequestException('refresh_token');
|
||||
}
|
||||
|
||||
// Validate refresh token
|
||||
$oldRefreshToken = $this->server->getRefreshTokenStorage()->get($oldRefreshTokenParam);
|
||||
if (($oldRefreshToken instanceof OriginalRefreshTokenEntity) === false) {
|
||||
throw new Exception\InvalidRefreshException();
|
||||
}
|
||||
|
||||
// Ensure the old refresh token hasn't expired
|
||||
if ($oldRefreshToken->isExpired()) {
|
||||
throw new Exception\InvalidRefreshException();
|
||||
}
|
||||
|
||||
/** @var Entities\AccessTokenEntity|null $oldAccessToken */
|
||||
$oldAccessToken = $oldRefreshToken->getAccessToken();
|
||||
if ($oldAccessToken instanceof Entities\AccessTokenEntity) {
|
||||
// Get the scopes for the original session
|
||||
$session = $oldAccessToken->getSession();
|
||||
} else {
|
||||
if (!$oldRefreshToken instanceof Entities\RefreshTokenEntity) {
|
||||
throw new ErrorException('oldRefreshToken must be instance of ' . Entities\RefreshTokenEntity::class);
|
||||
}
|
||||
|
||||
$session = $oldRefreshToken->getSession();
|
||||
}
|
||||
|
||||
$scopes = $this->formatScopes($session->getScopes());
|
||||
|
||||
// Get and validate any requested scopes
|
||||
$requestedScopesString = $this->server->getRequest()->request->get('scope', '');
|
||||
$requestedScopes = $this->validateScopes($requestedScopesString, $client);
|
||||
|
||||
// If no new scopes are requested then give the access token the original session scopes
|
||||
if (count($requestedScopes) === 0) {
|
||||
$newScopes = $scopes;
|
||||
} else {
|
||||
// The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure
|
||||
// the request doesn't include any new scopes
|
||||
foreach ($requestedScopes as $requestedScope) {
|
||||
if (!isset($scopes[$requestedScope->getId()])) {
|
||||
throw new Exception\InvalidScopeException($requestedScope->getId());
|
||||
}
|
||||
}
|
||||
|
||||
$newScopes = $requestedScopes;
|
||||
}
|
||||
|
||||
// Generate a new access token and assign it the correct sessions
|
||||
$newAccessToken = $this->createAccessTokenEntity();
|
||||
$newAccessToken->setId(SecureKey::generate());
|
||||
$newAccessToken->setExpireTime($this->getAccessTokenTTL() + time());
|
||||
$newAccessToken->setSession($session);
|
||||
|
||||
foreach ($newScopes as $newScope) {
|
||||
$newAccessToken->associateScope($newScope);
|
||||
}
|
||||
|
||||
// Expire the old token and save the new one
|
||||
($oldAccessToken instanceof Entities\AccessTokenEntity) && $oldAccessToken->expire();
|
||||
$newAccessToken->save();
|
||||
|
||||
$this->server->getTokenType()->setSession($session);
|
||||
$this->server->getTokenType()->setParam('access_token', $newAccessToken->getId());
|
||||
$this->server->getTokenType()->setParam('expires_in', $this->getAccessTokenTTL());
|
||||
|
||||
if ($this->shouldRotateRefreshTokens()) {
|
||||
// Expire the old refresh token
|
||||
$oldRefreshToken->expire();
|
||||
|
||||
// Generate a new refresh token
|
||||
$newRefreshToken = $this->createRefreshTokenEntity();
|
||||
$newRefreshToken->setId(SecureKey::generate());
|
||||
$newRefreshToken->setExpireTime($this->getRefreshTokenTTL() + time());
|
||||
$newRefreshToken->setAccessToken($newAccessToken);
|
||||
$newRefreshToken->save();
|
||||
|
||||
$this->server->getTokenType()->setParam('refresh_token', $newRefreshToken->getId());
|
||||
} else {
|
||||
$oldRefreshToken->setAccessToken($newAccessToken);
|
||||
$oldRefreshToken->save();
|
||||
}
|
||||
|
||||
return $this->server->getTokenType()->generateResponse();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,87 +2,66 @@
|
||||
namespace api\components\OAuth2\Storage;
|
||||
|
||||
use api\components\OAuth2\Entities\AccessTokenEntity;
|
||||
use common\models\OauthAccessToken;
|
||||
use common\components\Redis\Key;
|
||||
use common\components\Redis\Set;
|
||||
use League\OAuth2\Server\Entity\AccessTokenEntity as OriginalAccessTokenEntity;
|
||||
use League\OAuth2\Server\Entity\ScopeEntity;
|
||||
use League\OAuth2\Server\Storage\AbstractStorage;
|
||||
use League\OAuth2\Server\Storage\AccessTokenInterface;
|
||||
use yii\db\Exception;
|
||||
use yii\helpers\Json;
|
||||
|
||||
class AccessTokenStorage extends AbstractStorage implements AccessTokenInterface {
|
||||
|
||||
private $cache = [];
|
||||
public $dataTable = 'oauth_access_tokens';
|
||||
|
||||
/**
|
||||
* @param string $token
|
||||
* @return OauthAccessToken|null
|
||||
*/
|
||||
private function getTokenModel($token) {
|
||||
if (!isset($this->cache[$token])) {
|
||||
$this->cache[$token] = OauthAccessToken::findOne($token);
|
||||
}
|
||||
|
||||
return $this->cache[$token];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($token) {
|
||||
$model = $this->getTokenModel($token);
|
||||
if ($model === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var SessionStorage $sessionStorage */
|
||||
$sessionStorage = $this->server->getSessionStorage();
|
||||
$result = Json::decode((new Key($this->dataTable, $token))->getValue());
|
||||
|
||||
$token = new AccessTokenEntity($this->server);
|
||||
$token->setId($model->access_token);
|
||||
$token->setExpireTime($model->expire_time);
|
||||
$token->setSession($sessionStorage->getById($model->session_id));
|
||||
$token->setId($result['id']);
|
||||
$token->setExpireTime($result['expire_time']);
|
||||
$token->setSessionId($result['session_id']);
|
||||
|
||||
return $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getScopes(OriginalAccessTokenEntity $token) {
|
||||
$scopes = $this->scopes($token->getId());
|
||||
$entities = [];
|
||||
foreach($this->getTokenModel($token->getId())->getScopes() as $scope) {
|
||||
$entities[] = (new ScopeEntity($this->server))->hydrate(['id' => $scope]);
|
||||
foreach($scopes as $scope) {
|
||||
if ($this->server->getScopeStorage()->get($scope) !== null) {
|
||||
$entities[] = (new ScopeEntity($this->server))->hydrate(['id' => $scope]);
|
||||
}
|
||||
}
|
||||
|
||||
return $entities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function create($token, $expireTime, $sessionId) {
|
||||
$model = new OauthAccessToken();
|
||||
$model->access_token = $token;
|
||||
$model->expire_time = $expireTime;
|
||||
$model->session_id = $sessionId;
|
||||
$payload = Json::encode([
|
||||
'id' => $token,
|
||||
'expire_time' => $expireTime,
|
||||
'session_id' => $sessionId,
|
||||
]);
|
||||
|
||||
if (!$model->save()) {
|
||||
throw new Exception('Cannot save ' . OauthAccessToken::class . ' model.');
|
||||
}
|
||||
$this->key($token)->setValue($payload)->expireAt($expireTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function associateScope(OriginalAccessTokenEntity $token, ScopeEntity $scope) {
|
||||
$this->getTokenModel($token->getId())->getScopes()->add($scope->getId());
|
||||
$this->scopes($token->getId())->add($scope->getId())->expireAt($token->getExpireTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function delete(OriginalAccessTokenEntity $token) {
|
||||
$this->getTokenModel($token->getId())->delete();
|
||||
$this->key($token->getId())->delete();
|
||||
$this->scopes($token->getId())->delete();
|
||||
}
|
||||
|
||||
private function key(string $token) : Key {
|
||||
return new Key($this->dataTable, $token);
|
||||
}
|
||||
|
||||
private function scopes(string $token) : Set {
|
||||
return new Set($this->dataTable, $token, 'scopes');
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,81 +8,65 @@ use League\OAuth2\Server\Entity\AuthCodeEntity as OriginalAuthCodeEntity;
|
||||
use League\OAuth2\Server\Entity\ScopeEntity;
|
||||
use League\OAuth2\Server\Storage\AbstractStorage;
|
||||
use League\OAuth2\Server\Storage\AuthCodeInterface;
|
||||
use yii\helpers\Json;
|
||||
|
||||
class AuthCodeStorage extends AbstractStorage implements AuthCodeInterface {
|
||||
|
||||
public $dataTable = 'oauth_auth_codes';
|
||||
|
||||
public $ttl = 3600; // 1h
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($code) {
|
||||
$result = json_decode((new Key($this->dataTable, $code))->getValue(), true);
|
||||
if (!$result) {
|
||||
$result = Json::decode((new Key($this->dataTable, $code))->getValue());
|
||||
if ($result === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($result['expire_time'] < time()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var SessionStorage $sessionStorage */
|
||||
$sessionStorage = $this->server->getSessionStorage();
|
||||
|
||||
$entity = new AuthCodeEntity($this->server);
|
||||
$entity->setId($result['id']);
|
||||
$entity->setRedirectUri($result['client_redirect_uri']);
|
||||
$entity->setExpireTime($result['expire_time']);
|
||||
$entity->setSession($sessionStorage->getById($result['session_id']));
|
||||
$entity->setSessionId($result['session_id']);
|
||||
$entity->setRedirectUri($result['client_redirect_uri']);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function create($token, $expireTime, $sessionId, $redirectUri) {
|
||||
$payload = [
|
||||
$payload = Json::encode([
|
||||
'id' => $token,
|
||||
'expire_time' => $expireTime,
|
||||
'session_id' => $sessionId,
|
||||
'client_redirect_uri' => $redirectUri,
|
||||
];
|
||||
]);
|
||||
|
||||
(new Key($this->dataTable, $token))->setValue($payload)->expire($this->ttl);
|
||||
$this->key($token)->setValue($payload)->expireAt($expireTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getScopes(OriginalAuthCodeEntity $token) {
|
||||
$result = new Set($this->dataTable, $token->getId(), 'scopes');
|
||||
$response = [];
|
||||
foreach ($result as $scope) {
|
||||
// TODO: нужно проверить все выданные скоупы на их существование
|
||||
$response[] = (new ScopeEntity($this->server))->hydrate(['id' => $scope]);
|
||||
$scopes = $this->scopes($token->getId());
|
||||
$scopesEntities = [];
|
||||
foreach ($scopes as $scope) {
|
||||
if ($this->server->getScopeStorage()->get($scope) !== null) {
|
||||
$scopesEntities[] = (new ScopeEntity($this->server))->hydrate(['id' => $scope]);
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
return $scopesEntities;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function associateScope(OriginalAuthCodeEntity $token, ScopeEntity $scope) {
|
||||
(new Set($this->dataTable, $token->getId(), 'scopes'))->add($scope->getId())->expire($this->ttl);
|
||||
$this->scopes($token->getId())->add($scope->getId())->expireAt($token->getExpireTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function delete(OriginalAuthCodeEntity $token) {
|
||||
// Удаляем ключ
|
||||
(new Set($this->dataTable, $token->getId()))->delete();
|
||||
// Удаляем список скоупов для ключа
|
||||
(new Set($this->dataTable, $token->getId(), 'scopes'))->delete();
|
||||
$this->key($token->getId())->delete();
|
||||
$this->scopes($token->getId())->delete();
|
||||
}
|
||||
|
||||
private function key(string $token) : Key {
|
||||
return new Key($this->dataTable, $token);
|
||||
}
|
||||
|
||||
private function scopes(string $token) : Set {
|
||||
return new Set($this->dataTable, $token, 'scopes');
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,47 +3,58 @@ namespace api\components\OAuth2\Storage;
|
||||
|
||||
use api\components\OAuth2\Entities\RefreshTokenEntity;
|
||||
use common\components\Redis\Key;
|
||||
use common\components\Redis\Set;
|
||||
use common\models\OauthSession;
|
||||
use ErrorException;
|
||||
use League\OAuth2\Server\Entity\RefreshTokenEntity as OriginalRefreshTokenEntity;
|
||||
use League\OAuth2\Server\Storage\AbstractStorage;
|
||||
use League\OAuth2\Server\Storage\RefreshTokenInterface;
|
||||
use Yii;
|
||||
use yii\helpers\Json;
|
||||
|
||||
class RefreshTokenStorage extends AbstractStorage implements RefreshTokenInterface {
|
||||
|
||||
public $dataTable = 'oauth_refresh_tokens';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($token) {
|
||||
$result = json_decode((new Key($this->dataTable, $token))->getValue(), true);
|
||||
if (!$result) {
|
||||
return null;
|
||||
}
|
||||
$result = Json::decode((new Key($this->dataTable, $token))->getValue());
|
||||
|
||||
$entity = new RefreshTokenEntity($this->server);
|
||||
$entity->setId($result['id']);
|
||||
$entity->setAccessTokenId($result['access_token_id']);
|
||||
$entity->setSessionId($result['session_id']);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function create($token, $expireTime, $accessToken) {
|
||||
$payload = [
|
||||
$sessionId = $this->server->getAccessTokenStorage()->get($accessToken)->getSession()->getId();
|
||||
$payload = Json::encode([
|
||||
'id' => $token,
|
||||
'access_token_id' => $accessToken,
|
||||
];
|
||||
'session_id' => $sessionId,
|
||||
]);
|
||||
|
||||
(new Key($this->dataTable, $token))->setValue($payload);
|
||||
$this->key($token)->setValue($payload);
|
||||
$this->sessionHash($sessionId)->add($token);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function delete(OriginalRefreshTokenEntity $token) {
|
||||
(new Key($this->dataTable, $token->getId()))->delete();
|
||||
if (!$token instanceof RefreshTokenEntity) {
|
||||
throw new ErrorException('Token must be instance of ' . RefreshTokenEntity::class);
|
||||
}
|
||||
|
||||
$this->key($token->getId())->delete();
|
||||
$this->sessionHash($token->getSessionId())->remove($token->getId());
|
||||
}
|
||||
|
||||
public function sessionHash(string $sessionId) : Set {
|
||||
$tableName = Yii::$app->db->getSchema()->getRawTableName(OauthSession::tableName());
|
||||
return new Set($tableName, $sessionId, 'refresh_tokens');
|
||||
}
|
||||
|
||||
private function key(string $token) : Key {
|
||||
return new Key($this->dataTable, $token);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,13 +11,10 @@ use League\OAuth2\Server\Entity\ScopeEntity;
|
||||
use League\OAuth2\Server\Entity\SessionEntity as OriginalSessionEntity;
|
||||
use League\OAuth2\Server\Storage\AbstractStorage;
|
||||
use League\OAuth2\Server\Storage\SessionInterface;
|
||||
use yii\db\ActiveQuery;
|
||||
use yii\db\Exception;
|
||||
|
||||
class SessionStorage extends AbstractStorage implements SessionInterface {
|
||||
|
||||
private $cache = [];
|
||||
|
||||
/**
|
||||
* @param string $sessionId
|
||||
* @return SessionEntity|null
|
||||
@ -26,23 +23,10 @@ class SessionStorage extends AbstractStorage implements SessionInterface {
|
||||
return $this->hydrate($this->getSessionModel($sessionId));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getByAccessToken(OriginalAccessTokenEntity $accessToken) {
|
||||
/** @var OauthSession|null $model */
|
||||
$model = OauthSession::find()->innerJoinWith([
|
||||
'accessTokens' => function(ActiveQuery $query) use ($accessToken) {
|
||||
$query->andWhere(['access_token' => $accessToken->getId()]);
|
||||
},
|
||||
])->one();
|
||||
|
||||
return $this->hydrate($model);
|
||||
throw new ErrorException('This method is not implemented and should not be used');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getByAuthCode(OriginalAuthCodeEntity $authCode) {
|
||||
if (!$authCode instanceof AuthCodeEntity) {
|
||||
throw new ErrorException('This module assumes that $authCode typeof ' . AuthCodeEntity::class);
|
||||
@ -51,22 +35,17 @@ class SessionStorage extends AbstractStorage implements SessionInterface {
|
||||
return $this->getById($authCode->getSessionId());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getScopes(OriginalSessionEntity $session) {
|
||||
$result = [];
|
||||
foreach ($this->getSessionModel($session->getId())->getScopes() as $scope) {
|
||||
// TODO: нужно проверить все выданные скоупы на их существование
|
||||
$result[] = (new ScopeEntity($this->server))->hydrate(['id' => $scope]);
|
||||
if ($this->server->getScopeStorage()->get($scope) !== null) {
|
||||
$result[] = (new ScopeEntity($this->server))->hydrate(['id' => $scope]);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function create($ownerType, $ownerId, $clientId, $clientRedirectUri = null) {
|
||||
$sessionId = OauthSession::find()
|
||||
->select('id')
|
||||
@ -93,19 +72,17 @@ class SessionStorage extends AbstractStorage implements SessionInterface {
|
||||
return $sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function associateScope(OriginalSessionEntity $session, ScopeEntity $scope) {
|
||||
$this->getSessionModel($session->getId())->getScopes()->add($scope->getId());
|
||||
}
|
||||
|
||||
private function getSessionModel(string $sessionId) : OauthSession {
|
||||
if (!isset($this->cache[$sessionId])) {
|
||||
$this->cache[$sessionId] = OauthSession::findOne($sessionId);
|
||||
$session = OauthSession::findOne($sessionId);
|
||||
if ($session === null) {
|
||||
throw new ErrorException('Cannot find oauth session');
|
||||
}
|
||||
|
||||
return $this->cache[$sessionId];
|
||||
return $session;
|
||||
}
|
||||
|
||||
private function hydrate(OauthSession $sessionModel) {
|
||||
|
@ -24,7 +24,7 @@ class Key {
|
||||
}
|
||||
|
||||
public function setValue($value) {
|
||||
$this->getRedis()->set($this->key, json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
$this->getRedis()->set($this->key, $value);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@ -37,11 +37,16 @@ class Key {
|
||||
return (bool)$this->getRedis()->exists($this->key);
|
||||
}
|
||||
|
||||
public function expire($ttl) {
|
||||
public function expire(int $ttl) {
|
||||
$this->getRedis()->expire($this->key, $ttl);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function expireAt(int $unixTimestamp) {
|
||||
$this->getRedis()->expireat($this->key, $unixTimestamp);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function __construct(...$key) {
|
||||
if (empty($key)) {
|
||||
throw new InvalidArgumentException('You must specify at least one key.');
|
||||
|
@ -15,6 +15,7 @@ use yii\db\ActiveRecord;
|
||||
*
|
||||
* Отношения:
|
||||
* @property OauthSession $session
|
||||
* @deprecated
|
||||
*/
|
||||
class OauthAccessToken extends ActiveRecord {
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
namespace common\models;
|
||||
|
||||
use common\components\Redis\Set;
|
||||
use Yii;
|
||||
use yii\db\ActiveRecord;
|
||||
|
||||
/**
|
||||
@ -46,6 +47,14 @@ class OauthSession extends ActiveRecord {
|
||||
}
|
||||
|
||||
$this->getScopes()->delete();
|
||||
/** @var \api\components\OAuth2\Storage\RefreshTokenStorage $refreshTokensStorage */
|
||||
$refreshTokensStorage = Yii::$app->oauth->getAuthServer()->getRefreshTokenStorage();
|
||||
$refreshTokensSet = $refreshTokensStorage->sessionHash($this->id);
|
||||
foreach ($refreshTokensSet->members() as $refreshTokenId) {
|
||||
$refreshTokensStorage->delete($refreshTokensStorage->get($refreshTokenId));
|
||||
}
|
||||
|
||||
$refreshTokensSet->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user