mirror of
https://github.com/elyby/accounts.git
synced 2025-05-31 14:11:46 +05:30
Fixed almost everything, but all functional tests are broken at the last minute :(
This commit is contained in:
@@ -3,8 +3,8 @@ namespace api\components\OAuth2\Storage;
|
||||
|
||||
use api\components\OAuth2\Entities\ClientEntity;
|
||||
use api\components\OAuth2\Entities\ScopeEntity;
|
||||
use api\rbac\Permissions as P;
|
||||
use Assert\Assert;
|
||||
use common\rbac\Permissions as P;
|
||||
use League\OAuth2\Server\Storage\AbstractStorage;
|
||||
use League\OAuth2\Server\Storage\ScopeInterface;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace api\components\Tokens;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Lcobucci\JWT\Builder;
|
||||
use Lcobucci\JWT\Parser;
|
||||
@@ -11,8 +12,6 @@ use yii\base\Component as BaseComponent;
|
||||
|
||||
class Component extends BaseComponent {
|
||||
|
||||
private const EXPIRATION_TIMEOUT = 3600; // 1h
|
||||
|
||||
private const PREFERRED_ALGORITHM = 'ES256';
|
||||
|
||||
/**
|
||||
@@ -41,10 +40,10 @@ class Component extends BaseComponent {
|
||||
private $algorithmManager;
|
||||
|
||||
public function create(array $payloads = [], array $headers = []): Token {
|
||||
$time = time();
|
||||
$now = Carbon::now();
|
||||
$builder = (new Builder())
|
||||
->issuedAt($time)
|
||||
->expiresAt($time + self::EXPIRATION_TIMEOUT);
|
||||
->issuedAt($now->getTimestamp())
|
||||
->expiresAt($now->addHour()->getTimestamp());
|
||||
foreach ($payloads as $claim => $value) {
|
||||
$builder->withClaim($claim, $value);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ declare(strict_types=1);
|
||||
|
||||
namespace api\components\Tokens;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use common\models\Account;
|
||||
use common\models\AccountSession;
|
||||
use Lcobucci\JWT\Token;
|
||||
@@ -20,7 +21,7 @@ class TokensFactory {
|
||||
if ($session === null) {
|
||||
// If we don't remember a session, the token should live longer
|
||||
// so that the session doesn't end while working with the account
|
||||
$payloads['exp'] = time() + 60 * 60 * 24 * 7; // 7d
|
||||
$payloads['exp'] = Carbon::now()->addDays(7)->getTimestamp();
|
||||
} else {
|
||||
$payloads['jti'] = $session->id;
|
||||
}
|
||||
|
||||
@@ -5,10 +5,6 @@ namespace api\components\User;
|
||||
|
||||
use common\models\Account;
|
||||
use common\models\AccountSession;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use Yii;
|
||||
use yii\web\UnauthorizedHttpException;
|
||||
use yii\web\User as YiiUserComponent;
|
||||
|
||||
/**
|
||||
@@ -38,29 +34,11 @@ class Component extends YiiUserComponent {
|
||||
*/
|
||||
public $identityClass = IdentityFactory::class;
|
||||
|
||||
public function findIdentityByAccessToken($accessToken): ?IdentityInterface {
|
||||
if (empty($accessToken)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return IdentityFactory::findIdentityByAccessToken($accessToken);
|
||||
} catch (UnauthorizedHttpException $e) {
|
||||
// TODO: if this exception is catched there, how it forms "Token expired" exception?
|
||||
// Do nothing. It's okay to catch this.
|
||||
} catch (Exception $e) {
|
||||
Yii::error($e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The method searches AccountSession model, which one has been used to create current JWT token.
|
||||
* null will be returned in case when any of the following situations occurred:
|
||||
* - The user isn't authorized
|
||||
* - There is no header with a token
|
||||
* - Token validation isn't passed and some exception has been thrown
|
||||
* - The user isn't authorized via JWT token
|
||||
* - No session key found in the token. This is possible if the user chose not to remember me
|
||||
* or just some old tokens, without the support of saving the used session
|
||||
*
|
||||
@@ -71,18 +49,13 @@ class Component extends YiiUserComponent {
|
||||
return null;
|
||||
}
|
||||
|
||||
$bearer = $this->getBearerToken();
|
||||
if ($bearer === null) {
|
||||
/** @var IdentityInterface $identity */
|
||||
$identity = $this->getIdentity();
|
||||
if (!$identity instanceof JwtIdentity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
$token = Yii::$app->tokens->parse($bearer);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$sessionId = $token->getClaim('jti', false);
|
||||
$sessionId = $identity->getToken()->getClaim('jti', false);
|
||||
if ($sessionId === false) {
|
||||
return null;
|
||||
}
|
||||
@@ -111,13 +84,4 @@ class Component extends YiiUserComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private function getBearerToken(): ?string {
|
||||
$authHeader = Yii::$app->request->getHeaders()->get('Authorization');
|
||||
if ($authHeader === null || !preg_match('/^Bearer\s+(.*?)$/', $authHeader, $matches)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $matches[1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
||||
namespace api\components\User;
|
||||
|
||||
use api\components\Tokens\TokensFactory;
|
||||
use Carbon\Carbon;
|
||||
use common\models\Account;
|
||||
use Exception;
|
||||
use Lcobucci\JWT\Token;
|
||||
@@ -36,22 +37,27 @@ class JwtIdentity implements IdentityInterface {
|
||||
throw new UnauthorizedHttpException('Incorrect token');
|
||||
}
|
||||
|
||||
if ($token->isExpired()) {
|
||||
$now = Carbon::now();
|
||||
if ($token->isExpired($now)) {
|
||||
throw new UnauthorizedHttpException('Token expired');
|
||||
}
|
||||
|
||||
if (!$token->validate(new ValidationData())) {
|
||||
if (!$token->validate(new ValidationData($now->getTimestamp()))) {
|
||||
throw new UnauthorizedHttpException('Incorrect token');
|
||||
}
|
||||
|
||||
$sub = $token->getClaim('sub', false);
|
||||
if ($sub !== false && strpos($sub, TokensFactory::SUB_ACCOUNT_PREFIX) !== 0) {
|
||||
if ($sub !== false && strpos((string)$sub, TokensFactory::SUB_ACCOUNT_PREFIX) !== 0) {
|
||||
throw new UnauthorizedHttpException('Incorrect token');
|
||||
}
|
||||
|
||||
return new self($token);
|
||||
}
|
||||
|
||||
public function getToken(): Token {
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
public function getAccount(): ?Account {
|
||||
$subject = $this->token->getClaim('sub', false);
|
||||
if ($subject === false) {
|
||||
@@ -77,6 +83,7 @@ class JwtIdentity implements IdentityInterface {
|
||||
return (string)$this->token;
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
public function getAuthKey() {
|
||||
throw new NotSupportedException('This method used for cookie auth, except we using Bearer auth');
|
||||
}
|
||||
@@ -89,4 +96,6 @@ class JwtIdentity implements IdentityInterface {
|
||||
throw new NotSupportedException('This method used for cookie auth, except we using Bearer auth');
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user