[PLUGIN][OAuth2] Fix some static issues

This commit is contained in:
Diogo Peralta Cordeiro 2022-02-04 18:34:08 +00:00
parent 4dd976eb22
commit 81f6d496c6
Signed by: diogo
GPG Key ID: 18D2D35001FBFAB0
15 changed files with 206 additions and 202 deletions

View File

@ -78,7 +78,8 @@ class Authorize extends Controller
public function __construct(private int $id)
{
}
public function getIdentifier()
public function getIdentifier(): int
{
return $this->id;
}

View File

@ -38,6 +38,8 @@ use App\Core\DB\DB;
use function App\Core\I18n\_m;
use App\Core\Log;
use App\Util\Exception\ClientException;
use App\Util\Exception\ServerException;
use Exception;
use Plugin\OAuth2\Entity;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
@ -50,6 +52,11 @@ use Symfony\Component\HttpFoundation\Request;
*/
class Client extends Controller
{
/**
* @throws ClientException
* @throws Exception
* @throws ServerException
*/
public function onPost(Request $request): JsonResponse
{
Log::debug('OAuth2 Apps: Received a POST request.');
@ -60,8 +67,9 @@ class Client extends Controller
throw new ClientException(_m('Invalid request'), code: 400);
}
$identifier = hash('sha256', random_bytes(16)); // TODO maybe use password_hash and verify
$secret = hash('sha256', random_bytes(64));
$identifier = hash('md5', random_bytes(16));
// Random string Length should be between 43 and 128, thus 57
$secret = hash('sha256', random_bytes(57));
// TODO more validation
$client = Entity\Client::create([

View File

@ -34,6 +34,7 @@ namespace Plugin\OAuth2\Entity;
use DateTimeInterface;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use Plugin\OAuth2\Util\Token;
class AccessToken extends Token implements AccessTokenEntityInterface
{
@ -47,20 +48,14 @@ class AccessToken extends Token implements AccessTokenEntityInterface
private bool $revoked;
private DateTimeInterface $created;
public function setId(string $id): self
{
$this->id = mb_substr($id, 0, 64);
return $this;
}
public function getId(): string
{
return $this->id;
}
public function setExpiry(DateTimeInterface $expiry): self
public function setId(string $id): self
{
$this->expiry = $expiry;
$this->id = mb_substr($id, 0, 64);
return $this;
}
@ -69,9 +64,9 @@ class AccessToken extends Token implements AccessTokenEntityInterface
return $this->expiry;
}
public function setUserId(?int $user_id): self
public function setExpiry(DateTimeInterface $expiry): self
{
$this->user_id = $user_id;
$this->expiry = $expiry;
return $this;
}
@ -80,9 +75,9 @@ class AccessToken extends Token implements AccessTokenEntityInterface
return $this->user_id;
}
public function setClientId(string $client_id): self
public function setUserId(?int $user_id): self
{
$this->client_id = mb_substr($client_id, 0, 64);
$this->user_id = $user_id;
return $this;
}
@ -91,9 +86,9 @@ class AccessToken extends Token implements AccessTokenEntityInterface
return $this->client_id;
}
public function setTokenScopes(string $token_scopes): self
public function setClientId(string $client_id): self
{
$this->token_scopes = $token_scopes;
$this->client_id = mb_substr($client_id, 0, 64);
return $this;
}
@ -102,9 +97,9 @@ class AccessToken extends Token implements AccessTokenEntityInterface
return $this->token_scopes;
}
public function setRevoked(bool $revoked): self
public function setTokenScopes(string $token_scopes): self
{
$this->revoked = $revoked;
$this->token_scopes = $token_scopes;
return $this;
}
@ -113,9 +108,9 @@ class AccessToken extends Token implements AccessTokenEntityInterface
return $this->revoked;
}
public function setCreated(DateTimeInterface $created): self
public function setRevoked(bool $revoked): self
{
$this->created = $created;
$this->revoked = $revoked;
return $this;
}
@ -124,13 +119,19 @@ class AccessToken extends Token implements AccessTokenEntityInterface
return $this->created;
}
public function setCreated(DateTimeInterface $created): self
{
$this->created = $created;
return $this;
}
// @codeCoverageIgnoreEnd
// }}} Autocode
public CryptKey $private_key;
public function setPrivateKey(CryptKey $private_key)
public function setPrivateKey(CryptKey $privateKey)
{
$this->private_key = $private_key;
$this->private_key = $privateKey;
}
public function __toString()

View File

@ -34,6 +34,7 @@ namespace Plugin\OAuth2\Entity;
use DateTimeInterface;
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
use Plugin\OAuth2\Repository;
use Plugin\OAuth2\Util\Token;
class AuthCode extends Token implements AuthCodeEntityInterface
{
@ -47,20 +48,14 @@ class AuthCode extends Token implements AuthCodeEntityInterface
private bool $revoked;
private DateTimeInterface $created;
public function setId(string $id): self
{
$this->id = mb_substr($id, 0, 64);
return $this;
}
public function getId(): string
{
return $this->id;
}
public function setExpiry(DateTimeInterface $expiry): self
public function setId(string $id): self
{
$this->expiry = $expiry;
$this->id = mb_substr($id, 0, 64);
return $this;
}
@ -69,9 +64,9 @@ class AuthCode extends Token implements AuthCodeEntityInterface
return $this->expiry;
}
public function setUserId(?int $user_id): self
public function setExpiry(DateTimeInterface $expiry): self
{
$this->user_id = $user_id;
$this->expiry = $expiry;
return $this;
}
@ -80,20 +75,9 @@ class AuthCode extends Token implements AuthCodeEntityInterface
return $this->user_id;
}
public function setClientId(string $client_id): self
public function setUserId(?int $user_id): self
{
$this->client_id = mb_substr($client_id, 0, 64);
return $this;
}
public function getClientId(): string
{
return $this->client_id;
}
public function setTokenScopes(string $token_scopes): self
{
$this->token_scopes = $token_scopes;
$this->user_id = $user_id;
return $this;
}
@ -102,9 +86,9 @@ class AuthCode extends Token implements AuthCodeEntityInterface
return $this->token_scopes;
}
public function setRevoked(bool $revoked): self
public function setTokenScopes(string $token_scopes): self
{
$this->revoked = $revoked;
$this->token_scopes = $token_scopes;
return $this;
}
@ -113,9 +97,9 @@ class AuthCode extends Token implements AuthCodeEntityInterface
return $this->revoked;
}
public function setCreated(DateTimeInterface $created): self
public function setRevoked(bool $revoked): self
{
$this->created = $created;
$this->revoked = $revoked;
return $this;
}
@ -124,25 +108,38 @@ class AuthCode extends Token implements AuthCodeEntityInterface
return $this->created;
}
public function setCreated(DateTimeInterface $created): self
{
$this->created = $created;
return $this;
}
// @codeCoverageIgnoreEnd
// }}} Autocode
/**
* @return null|string
*/
public function getRedirectUri()
public function getClientId(): string
{
return (new Repository\Client)->getClientEntity($this->getClientId())->getRedirectUri();
return $this->client_id;
}
/**
* @param string $uri
*/
public function setRedirectUri($uri)
public function setClientId(string $client_id): self
{
$this->client_id = mb_substr($client_id, 0, 64);
return $this;
}
public function getRedirectUri(): ?string
{
/** @var Client $client */
$client = (new Repository\Client)->getClientEntity($this->getClientId());
$client->setRedirectUris($uri);
return $client->getRedirectUris();
}
public function setRedirectUri($uri): Client
{
/** @var Client $client */
$client = (new Repository\Client)->getClientEntity($this->getClientId());
return $client->setRedirectUris($uri);
}
public static function schemaDef(): array

View File

@ -52,20 +52,14 @@ class Client extends Entity implements ClientEntityInterface
private DateTimeInterface $created;
private DateTimeInterface $modified;
public function setId(string $id): self
{
$this->id = mb_substr($id, 0, 64);
return $this;
}
public function getId(): string
{
return $this->id;
}
public function setSecret(string $secret): self
public function setId(string $id): self
{
$this->secret = mb_substr($secret, 0, 64);
$this->id = mb_substr($id, 0, 64);
return $this;
}
@ -74,9 +68,9 @@ class Client extends Entity implements ClientEntityInterface
return $this->secret;
}
public function setActive(bool $active): self
public function setSecret(string $secret): self
{
$this->active = $active;
$this->secret = mb_substr($secret, 0, 64);
return $this;
}
@ -85,9 +79,9 @@ class Client extends Entity implements ClientEntityInterface
return $this->active;
}
public function setPlainPcke(bool $plain_pcke): self
public function setActive(bool $active): self
{
$this->plain_pcke = $plain_pcke;
$this->active = $active;
return $this;
}
@ -96,9 +90,9 @@ class Client extends Entity implements ClientEntityInterface
return $this->plain_pcke;
}
public function setIsConfidential(bool $is_confidential): self
public function setPlainPcke(bool $plain_pcke): self
{
$this->is_confidential = $is_confidential;
$this->plain_pcke = $plain_pcke;
return $this;
}
@ -107,9 +101,9 @@ class Client extends Entity implements ClientEntityInterface
return $this->is_confidential;
}
public function setRedirectUris(string $redirect_uris): self
public function setIsConfidential(bool $is_confidential): self
{
$this->redirect_uris = $redirect_uris;
$this->is_confidential = $is_confidential;
return $this;
}
@ -118,9 +112,9 @@ class Client extends Entity implements ClientEntityInterface
return $this->redirect_uris;
}
public function setGrants(string $grants): self
public function setRedirectUris(string $redirect_uris): self
{
$this->grants = $grants;
$this->redirect_uris = $redirect_uris;
return $this;
}
@ -129,9 +123,9 @@ class Client extends Entity implements ClientEntityInterface
return $this->grants;
}
public function setScopes(string $scopes): self
public function setGrants(string $grants): self
{
$this->scopes = $scopes;
$this->grants = $grants;
return $this;
}
@ -140,6 +134,12 @@ class Client extends Entity implements ClientEntityInterface
return $this->scopes;
}
public function setScopes(string $scopes): self
{
$this->scopes = $scopes;
return $this;
}
public function setClientName(string $client_name): self
{
$this->client_name = mb_substr($client_name, 0, 191);
@ -151,20 +151,14 @@ class Client extends Entity implements ClientEntityInterface
return $this->client_name;
}
public function setWebsite(?string $website): self
{
$this->website = $website;
return $this;
}
public function getWebsite(): ?string
{
return $this->website;
}
public function setCreated(DateTimeInterface $created): self
public function setWebsite(?string $website): self
{
$this->created = $created;
$this->website = $website;
return $this;
}
@ -173,9 +167,9 @@ class Client extends Entity implements ClientEntityInterface
return $this->created;
}
public function setModified(DateTimeInterface $modified): self
public function setCreated(DateTimeInterface $created): self
{
$this->modified = $modified;
$this->created = $created;
return $this;
}
@ -184,6 +178,11 @@ class Client extends Entity implements ClientEntityInterface
return $this->modified;
}
public function setModified(DateTimeInterface $modified): self
{
$this->modified = $modified;
return $this;
}
// @codeCoverageIgnoreEnd
// }}} Autocode

View File

@ -32,9 +32,11 @@ declare(strict_types = 1);
namespace Plugin\OAuth2\Entity;
use App\Core\Entity;
use DateTimeImmutable;
use DateTimeInterface;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use Plugin\OAuth2\Repository;
class RefreshToken extends Entity implements RefreshTokenEntityInterface
{
@ -46,20 +48,14 @@ class RefreshToken extends Entity implements RefreshTokenEntityInterface
private bool $revoked;
private DateTimeInterface $created;
public function setId(string $id): self
{
$this->id = mb_substr($id, 0, 64);
return $this;
}
public function getId(): string
{
return $this->id;
}
public function setExpiry(DateTimeInterface $expiry): self
public function setId(string $id): self
{
$this->expiry = $expiry;
$this->id = mb_substr($id, 0, 64);
return $this;
}
@ -68,9 +64,9 @@ class RefreshToken extends Entity implements RefreshTokenEntityInterface
return $this->expiry;
}
public function setAccessTokenId(?string $access_token_id): self
public function setExpiry(DateTimeInterface $expiry): self
{
$this->access_token_id = \is_null($access_token_id) ? null : mb_substr($access_token_id, 0, 64);
$this->expiry = $expiry;
return $this;
}
@ -79,9 +75,9 @@ class RefreshToken extends Entity implements RefreshTokenEntityInterface
return $this->access_token_id;
}
public function setRevoked(bool $revoked): self
public function setAccessTokenId(?string $access_token_id): self
{
$this->revoked = $revoked;
$this->access_token_id = \is_null($access_token_id) ? null : mb_substr($access_token_id, 0, 64);
return $this;
}
@ -90,9 +86,9 @@ class RefreshToken extends Entity implements RefreshTokenEntityInterface
return $this->revoked;
}
public function setCreated(DateTimeInterface $created): self
public function setRevoked(bool $revoked): self
{
$this->created = $created;
$this->revoked = $revoked;
return $this;
}
@ -101,45 +97,21 @@ class RefreshToken extends Entity implements RefreshTokenEntityInterface
return $this->created;
}
public function setCreated(DateTimeInterface $created): self
{
$this->created = $created;
return $this;
}
// @codeCoverageIgnoreEnd
// }}} Autocode
/**
* Get the token's identifier.
*
* @return string
* Get the access token that the refresh token was originally associated with.
*/
public function getIdentifier()
public function getAccessToken(): AccessTokenEntityInterface
{
return $this->getId();
}
/**
* Set the token's identifier.
*/
public function setIdentifier($identifier)
{
$this->setId($identifier);
}
/**
* Get the token's expiry date time.
*
* @return DateTimeImmutable
*/
public function getExpiryDateTime()
{
return $this->getExpiry();
}
/**
* Set the date time when the token expires.
*
* @param DateTimeImmutable $dateTime
*/
public function setExpiryDateTime(\DateTimeImmutable $dateTime)
{
$this->setExpiry($dateTime);
return (new Repository\AccessToken())->getAccessTokenEntity($this->getAccessTokenId());
}
/**
@ -150,14 +122,27 @@ class RefreshToken extends Entity implements RefreshTokenEntityInterface
$this->setAccessTokenId($accessToken->getIdentifier());
}
/**
* Get the access token that the refresh token was originally associated with.
*
* @return AccessTokenEntityInterface
*/
public function getAccessToken()
public function setIdentifier($identifier): self
{
return (new Repository\AccessToken)->getAccessTokenEntity($this->getAccessTokenId());
return $this->setId($identifier);
}
public function getIdentifier(): string
{
return $this->getId();
}
/**
* Set the date time when the token expires.
*/
public function setExpiryDateTime(DateTimeImmutable $dateTime)
{
$this->setExpiry($dateTime);
}
public function getExpiryDateTime(): DateTimeImmutable
{
return DateTimeImmutable::createFromInterface($this->getExpiry());
}
public static function schemaDef(): array

View File

@ -39,6 +39,7 @@ use App\Core\Router\RouteLoader;
use App\Core\Router\Router;
use App\Util\Common;
use DateInterval;
use Exception;
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Grant\AuthCodeGrant;
@ -57,13 +58,16 @@ class OAuth2 extends Plugin
public const OAUTH_REQUEST_TOKEN_REL = 'http://apinamespace.org/oauth/request_token';
public const OAUTH_ACCESS_TOKEN_REL = 'http://apinamespace.org/oauth/access_token';
public const OAUTH_AUTHORIZE_REL = 'http://apinamespace.org/oauth/authorize';
public static ?AuthorizationServer $authorization_server = null;
public function version(): string
{
return '3.0.0';
}
public static ?AuthorizationServer $authorization_server = null;
/**
* @throws Exception
*/
public function onInitializePlugin()
{
self::$authorization_server = new AuthorizationServer(
@ -102,9 +106,9 @@ class OAuth2 extends Plugin
public function onEndHostMetaLinks(array &$links): bool
{
$links[] = new XML_XRD_Element_link(self::OAUTH_REQUEST_TOKEN_REL, Router::url('oauth2_client', type: Router::ABSOLUTE_URL));
$links[] = new XML_XRD_Element_link(self::OAUTH_AUTHORIZE_REL, Router::url('oauth2_authorize', type: Router::ABSOLUTE_URL));
$links[] = new XML_XRD_Element_link(self::OAUTH_ACCESS_TOKEN_REL, Router::url('oauth2_token', type: Router::ABSOLUTE_URL));
$links[] = new XML_XRD_Element_Link(self::OAUTH_REQUEST_TOKEN_REL, Router::url('oauth2_client', type: Router::ABSOLUTE_URL));
$links[] = new XML_XRD_Element_Link(self::OAUTH_AUTHORIZE_REL, Router::url('oauth2_authorize', type: Router::ABSOLUTE_URL));
$links[] = new XML_XRD_Element_Link(self::OAUTH_ACCESS_TOKEN_REL, Router::url('oauth2_token', type: Router::ABSOLUTE_URL));
return Event::next;
}
}

View File

@ -41,6 +41,10 @@ use Plugin\OAuth2\Entity;
class AccessToken implements AccessTokenRepositoryInterface
{
/**
* @throws \App\Util\Exception\DuplicateFoundException
* @throws \App\Util\Exception\NotFoundException
*/
public function getAccessTokenEntity(string $identifier): Entity\AccessToken
{
return DB::findOneBy(Entity\AccessToken::class, ['id' => $identifier]);
@ -56,12 +60,12 @@ class AccessToken implements AccessTokenRepositoryInterface
// Some logic here to revoke the access token
}
public function isAccessTokenRevoked($tokenId)
public function isAccessTokenRevoked($tokenId): bool
{
return false; // Access token hasn't been revoked
}
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null)
public function getNewToken(ClientEntityInterface $clientEntity, array $scopes, $userIdentifier = null): Entity\AccessToken
{
$accessToken = new Entity\AccessToken();
$accessToken->setClient($clientEntity);

View File

@ -50,12 +50,12 @@ class AuthCode implements AuthCodeRepositoryInterface
// Some logic to revoke the auth code in a database
}
public function isAuthCodeRevoked($codeId)
public function isAuthCodeRevoked($codeId): bool
{
return false; // The auth code has not been revoked
}
public function getNewAuthCode()
public function getNewAuthCode(): Entity\AuthCode
{
return new Entity\AuthCode();
}

View File

@ -40,12 +40,12 @@ use Plugin\OAuth2\Entity;
class Client implements ClientRepositoryInterface
{
public function getClientEntity($clientIdentifier)
{
return DB::findOneBy(Entity\Client::class, ['id' => $clientIdentifier]);
}
public function validateClient($clientIdentifier, $clientSecret, $grantType)
/**
* @param string $clientIdentifier
* @param null|string $clientSecret
* @param null|string $grantType
*/
public function validateClient($clientIdentifier, $clientSecret, $grantType): bool
{
try {
/** @var Entity\Client $client */
@ -58,4 +58,13 @@ class Client implements ClientRepositoryInterface
}
return true;
}
/**
* @throws \App\Util\Exception\DuplicateFoundException
* @throws NotFoundException
*/
public function getClientEntity($clientIdentifier)
{
return DB::findOneBy(Entity\Client::class, ['id' => $clientIdentifier]);
}
}

View File

@ -40,9 +40,9 @@ use Plugin\OAuth2\Entity;
class RefreshToken implements RefreshTokenRepositoryInterface
{
public function persistNewRefreshToken(RefreshtokenEntityInterface $refreshtokenEntity)
public function persistNewRefreshToken(RefreshtokenEntityInterface $refreshTokenEntity)
{
DB::persist($refreshtokenEntity);
DB::persist($refreshTokenEntity);
}
public function revokeRefreshToken($tokenId)
@ -50,12 +50,12 @@ class RefreshToken implements RefreshTokenRepositoryInterface
// Some logic to revoke the auth token in a database
}
public function isRefreshtokenRevoked($tokenId)
public function isRefreshtokenRevoked($tokenId): bool
{
return false; // The auth token has not been revoked
}
public function getNewRefreshToken()
public function getNewRefreshToken(): Entity\RefreshToken
{
return new Entity\RefreshToken();
}

View File

@ -40,9 +40,9 @@ use League\OAuth2\Server\Repositories\ScopeRepositoryInterface;
class Scope implements ScopeRepositoryInterface
{
/**
* @return ?ScopeEntityInterface
* @param string $identifier
*/
public function getScopeEntityByIdentifier($scopeIdentifier)
public function getScopeEntityByIdentifier($identifier): ?ScopeEntityInterface
{
$scopes = [
'basic' => [
@ -62,19 +62,21 @@ class Scope implements ScopeRepositoryInterface
],
];
if (\array_key_exists($scopeIdentifier, $scopes) === false) {
return;
if (\array_key_exists($identifier, $scopes) === false) {
return null;
}
return new class($scopeIdentifier) implements ScopeEntityInterface {
return new class($identifier) implements ScopeEntityInterface {
public function __construct(private string $identifier)
{
}
public function getIdentifier()
public function getIdentifier(): string
{
return $this->identifier;
}
public function jsonSerialize(): mixed
public function jsonSerialize(): string
{
return $this->getIdentifier();
}
@ -86,7 +88,7 @@ class Scope implements ScopeRepositoryInterface
$grantType,
ClientEntityInterface $clientEntity,
$userIdentifier = null,
) {
): array {
return $scopes;
}
}

View File

@ -33,18 +33,19 @@ declare(strict_types = 1);
namespace Plugin\OAuth2\Util;
use App\Entity\Actor;
use App\Util\Exception\BugFoundException;
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
class ExpandedBearerTokenResponse extends BearerTokenResponse
{
/**
* @return array
* @throws BugFoundException
*/
protected function getExtraParams(AccessTokenEntityInterface $access_token)
protected function getExtraParams(AccessTokenEntityInterface $accessToken): array
{
return [
'me' => Actor::getById($access_token->getUserIdentifier())->getUri(),
'me' => Actor::getById($accessToken->getUserIdentifier())->getUri(),
];
}
}

View File

@ -29,9 +29,10 @@ declare(strict_types = 1);
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
*/
namespace Plugin\OAuth2\Entity;
namespace Plugin\OAuth2\Util;
use App\Core\Entity;
use DateTimeImmutable;
use Functional as F;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
@ -40,7 +41,7 @@ use Plugin\OAuth2\Repository;
abstract class Token extends Entity implements TokenInterface
{
public function getIdentifier()
public function getIdentifier(): string
{
return $this->getId();
}
@ -52,20 +53,16 @@ abstract class Token extends Entity implements TokenInterface
/**
* Get the token's expiry date time.
*
* @return DateTimeImmutable
*/
public function getExpiryDateTime()
public function getExpiryDateTime(): DateTimeImmutable
{
return $this->getExpiry();
}
/**
* Set the date time when the token expires.
*
* @param DateTimeImmutable $dateTime
*/
public function setExpiryDateTime(\DateTimeImmutable $dateTime)
public function setExpiryDateTime(DateTimeImmutable $dateTime)
{
$this->setExpiry($dateTime);
}
@ -82,20 +79,16 @@ abstract class Token extends Entity implements TokenInterface
/**
* Get the token user's identifier.
*
* @return null|int|string
*/
public function getUserIdentifier()
public function getUserIdentifier(): int|string|null
{
return $this->getUserId();
}
/**
* Get the client that the token was issued to.
*
* @return ClientEntityInterface
*/
public function getClient()
public function getClient(): ClientEntityInterface
{
return (new Repository\Client)->getClientEntity($this->getClientId());
}
@ -122,7 +115,7 @@ abstract class Token extends Entity implements TokenInterface
*
* @return ScopeEntityInterface[]
*/
public function getScopes()
public function getScopes(): array
{
return F\map(
explode(' ', $this->getTokenScopes()),