Skip to content

Commit

Permalink
Merge pull request #195 from trikoder/v3.x
Browse files Browse the repository at this point in the history
Merge v3.x into master
  • Loading branch information
HypeMC authored Apr 10, 2020
2 parents 99101c4 + 7eeb932 commit 5831863
Show file tree
Hide file tree
Showing 22 changed files with 495 additions and 13 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## [3.1.0] - 2020-04-09
### Added
- Ability to revoke credentials (access tokens, authorization codes and refresh tokens) programmatically ([fee109d](https://github.com/trikoder/oauth2-bundle/commit/fee109da2d52d73dfc81501d0af3d66216f09de6))
- Support for registering custom grant types ([6b37588](https://github.com/trikoder/oauth2-bundle/commit/6b3758807b7cca6835c00504f1632ea78de563a5))

### Fixed
- Console command `trikoder:oauth2:list-clients` not being able to list clients without a secret ([da38b7a](https://github.com/trikoder/oauth2-bundle/commit/da38b7ab77060b4d43aca405559d5ffbd7a34d8d))

## [3.0.0] - 2020-02-26
### Added
- Ability to restrict clients from using the `plain` challenge method during PKCE ([4562a1f](https://github.com/trikoder/oauth2-bundle/commit/4562a1ff306375fd651aa91c85d0d4fd6f4c1b13))
Expand Down
2 changes: 1 addition & 1 deletion Command/ListClientsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ private function getRows(array $clients, array $columns): array
];

return array_map(static function (string $column) use ($values): string {
return $values[$column];
return $values[$column] ?? '';
}, $columns);
}, $clients);
}
Expand Down
10 changes: 10 additions & 0 deletions DependencyInjection/TrikoderOAuth2Extension.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,15 @@
use Trikoder\Bundle\OAuth2Bundle\DBAL\Type\RedirectUri as RedirectUriType;
use Trikoder\Bundle\OAuth2Bundle\DBAL\Type\Scope as ScopeType;
use Trikoder\Bundle\OAuth2Bundle\EventListener\ConvertExceptionToResponseListener;
use Trikoder\Bundle\OAuth2Bundle\League\AuthorizationServer\GrantTypeInterface;
use Trikoder\Bundle\OAuth2Bundle\Manager\Doctrine\AccessTokenManager;
use Trikoder\Bundle\OAuth2Bundle\Manager\Doctrine\AuthorizationCodeManager;
use Trikoder\Bundle\OAuth2Bundle\Manager\Doctrine\ClientManager;
use Trikoder\Bundle\OAuth2Bundle\Manager\Doctrine\RefreshTokenManager;
use Trikoder\Bundle\OAuth2Bundle\Manager\ScopeManagerInterface;
use Trikoder\Bundle\OAuth2Bundle\Model\Scope as ScopeModel;
use Trikoder\Bundle\OAuth2Bundle\Security\Authentication\Token\OAuth2TokenFactory;
use Trikoder\Bundle\OAuth2Bundle\Service\CredentialsRevoker\DoctrineCredentialsRevoker;

final class TrikoderOAuth2Extension extends Extension implements PrependExtensionInterface, CompilerPassInterface
{
Expand Down Expand Up @@ -70,6 +72,9 @@ public function load(array $configs, ContainerBuilder $container)
'method' => 'onKernelException',
'priority' => $config['exception_event_listener_priority'],
]);

$container->registerForAutoconfiguration(GrantTypeInterface::class)
->addTag('trikoder.oauth2.authorization_server.grant');
}

/**
Expand Down Expand Up @@ -268,6 +273,11 @@ private function configureDoctrinePersistence(ContainerBuilder $container, array
->replaceArgument('$entityManager', $entityManager)
;

$container
->getDefinition(DoctrineCredentialsRevoker::class)
->replaceArgument('$entityManager', $entityManager)
;

$container->setParameter('trikoder.oauth2.persistence.doctrine.enabled', true);
$container->setParameter('trikoder.oauth2.persistence.doctrine.manager', $entityManagerName);
}
Expand Down
27 changes: 27 additions & 0 deletions League/AuthorizationServer/GrantConfigurator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Trikoder\Bundle\OAuth2Bundle\League\AuthorizationServer;

use League\OAuth2\Server\AuthorizationServer;

final class GrantConfigurator
{
/**
* @var iterable|GrantTypeInterface[]
*/
private $grants;

public function __construct(iterable $grants)
{
$this->grants = $grants;
}

public function __invoke(AuthorizationServer $authorizationServer): void
{
foreach ($this->grants as $grant) {
$authorizationServer->enableGrantType($grant, $grant->getAccessTokenTTL());
}
}
}
13 changes: 13 additions & 0 deletions League/AuthorizationServer/GrantTypeInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

declare(strict_types=1);

namespace Trikoder\Bundle\OAuth2Bundle\League\AuthorizationServer;

use DateInterval;
use League\OAuth2\Server\Grant\GrantTypeInterface as LeagueGrantTypeInterface;

interface GrantTypeInterface extends LeagueGrantTypeInterface
{
public function getAccessTokenTTL(): ?DateInterval;
}
5 changes: 2 additions & 3 deletions Manager/ClientManagerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
namespace Trikoder\Bundle\OAuth2Bundle\Manager;

use Trikoder\Bundle\OAuth2Bundle\Model\Client;
use Trikoder\Bundle\OAuth2Bundle\Service\ClientFinderInterface;

interface ClientManagerInterface
interface ClientManagerInterface extends ClientFinderInterface
{
public function find(string $identifier): ?Client;

public function save(Client $client): void;

public function remove(Client $client): void;
Expand Down
7 changes: 0 additions & 7 deletions Model/Grant.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@

namespace Trikoder\Bundle\OAuth2Bundle\Model;

use RuntimeException;
use Trikoder\Bundle\OAuth2Bundle\OAuth2Grants;

class Grant
{
/**
Expand All @@ -16,10 +13,6 @@ class Grant

public function __construct(string $grant)
{
if (!OAuth2Grants::has($grant)) {
throw new RuntimeException(sprintf('The \'%s\' grant is not supported.', $grant));
}

$this->grant = $grant;
}

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ security:
* [Basic setup](docs/basic-setup.md)
* [Controlling token scopes](docs/controlling-token-scopes.md)
* [Password grant handling](docs/password-grant-handling.md)
* [Implementing custom grant type](docs/implementing-custom-grant-type.md)
## Development
Expand Down
3 changes: 3 additions & 0 deletions Resources/config/doctrine/model/AccessToken.orm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
<many-to-one field="client" target-entity="Trikoder\Bundle\OAuth2Bundle\Model\Client">
<join-column name="client" referenced-column-name="identifier" nullable="false" on-delete="CASCADE" />
</many-to-one>
<indexes>
<index columns="userIdentifier" />
</indexes>
</entity>
</doctrine-mapping>
3 changes: 3 additions & 0 deletions Resources/config/doctrine/model/AuthorizationCode.orm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
<many-to-one field="client" target-entity="Trikoder\Bundle\OAuth2Bundle\Model\Client">
<join-column name="client" referenced-column-name="identifier" nullable="false" />
</many-to-one>
<indexes>
<index columns="userIdentifier" />
</indexes>
</entity>
</doctrine-mapping>
7 changes: 7 additions & 0 deletions Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
<services>
<service id="Trikoder\Bundle\OAuth2Bundle\Service\ClientFinderInterface" alias="Trikoder\Bundle\OAuth2Bundle\Manager\ClientManagerInterface" />

<!-- The league repositories -->
<service id="Trikoder\Bundle\OAuth2Bundle\League\Repository\ClientRepository">
<argument type="service" id="Trikoder\Bundle\OAuth2Bundle\Manager\ClientManagerInterface" />
Expand Down Expand Up @@ -70,13 +72,18 @@
</service>
<service id="trikoder.oauth2.security.firewall.oauth2_listener" alias="Trikoder\Bundle\OAuth2Bundle\Security\Firewall\OAuth2Listener" />

<service id="Trikoder\Bundle\OAuth2Bundle\League\AuthorizationServer\GrantConfigurator">
<argument key="$grants" type="tagged_iterator" tag="trikoder.oauth2.authorization_server.grant" />
</service>

<!-- The league authorization server -->
<service id="League\OAuth2\Server\AuthorizationServer">
<argument key="$clientRepository" type="service" id="League\OAuth2\Server\Repositories\ClientRepositoryInterface" />
<argument key="$accessTokenRepository" type="service" id="League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface" />
<argument key="$scopeRepository" type="service" id="League\OAuth2\Server\Repositories\ScopeRepositoryInterface" />
<argument key="$privateKey" />
<argument key="$encryptionKey" />
<configurator service="Trikoder\Bundle\OAuth2Bundle\League\AuthorizationServer\GrantConfigurator"/>
</service>
<service id="league.oauth2.server.authorization_server" alias="League\OAuth2\Server\AuthorizationServer" />

Expand Down
5 changes: 5 additions & 0 deletions Resources/config/storage/doctrine.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
<service id="Trikoder\Bundle\OAuth2Bundle\Manager\AuthorizationCodeManagerInterface" alias="Trikoder\Bundle\OAuth2Bundle\Manager\Doctrine\AuthorizationCodeManager" />

<!-- Services -->
<service id="Trikoder\Bundle\OAuth2Bundle\Service\CredentialsRevokerInterface" alias="Trikoder\Bundle\OAuth2Bundle\Service\CredentialsRevoker\DoctrineCredentialsRevoker" />
<service id="Trikoder\Bundle\OAuth2Bundle\Service\CredentialsRevoker\DoctrineCredentialsRevoker">
<argument key="$entityManager" />
</service>

<service id="Trikoder\Bundle\OAuth2Bundle\Manager\Doctrine\ClientManager">
<argument key="$entityManager" />
</service>
Expand Down
15 changes: 15 additions & 0 deletions Service/ClientFinderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace Trikoder\Bundle\OAuth2Bundle\Service;

use Trikoder\Bundle\OAuth2Bundle\Model\Client;

/**
* @api
*/
interface ClientFinderInterface
{
public function find(string $identifier): ?Client;
}
101 changes: 101 additions & 0 deletions Service/CredentialsRevoker/DoctrineCredentialsRevoker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
<?php

declare(strict_types=1);

namespace Trikoder\Bundle\OAuth2Bundle\Service\CredentialsRevoker;

use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Trikoder\Bundle\OAuth2Bundle\Model\AccessToken;
use Trikoder\Bundle\OAuth2Bundle\Model\AuthorizationCode;
use Trikoder\Bundle\OAuth2Bundle\Model\Client;
use Trikoder\Bundle\OAuth2Bundle\Model\RefreshToken;
use Trikoder\Bundle\OAuth2Bundle\Service\CredentialsRevokerInterface;

final class DoctrineCredentialsRevoker implements CredentialsRevokerInterface
{
/**
* @var EntityManagerInterface
*/
private $entityManager;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}

public function revokeCredentialsForUser(UserInterface $user): void
{
$userIdentifier = $user->getUsername();

$this->entityManager->createQueryBuilder()
->update(AccessToken::class, 'at')
->set('at.revoked', true)
->where('at.userIdentifier = :userIdentifier')
->setParameter('userIdentifier', $userIdentifier)
->getQuery()
->execute();

$queryBuilder = $this->entityManager->createQueryBuilder();
$queryBuilder
->update(RefreshToken::class, 'rt')
->set('rt.revoked', true)
->where($queryBuilder->expr()->in(
'rt.accessToken',
$this->entityManager->createQueryBuilder()
->select('at.identifier')
->from(AccessToken::class, 'at')
->where('at.userIdentifier = :userIdentifier')
->getDQL()
))
->setParameter('userIdentifier', $userIdentifier)
->getQuery()
->execute();

$this->entityManager->createQueryBuilder()
->update(AuthorizationCode::class, 'ac')
->set('ac.revoked', true)
->where('ac.userIdentifier = :userIdentifier')
->setParameter('userIdentifier', $userIdentifier)
->getQuery()
->execute();
}

public function revokeCredentialsForClient(Client $client): void
{
$doctrineClient = $this->entityManager
->getRepository(Client::class)
->findOneBy(['identifier' => $client->getIdentifier()]);

$this->entityManager->createQueryBuilder()
->update(AccessToken::class, 'at')
->set('at.revoked', true)
->where('at.client = :client')
->setParameter('client', $doctrineClient)
->getQuery()
->execute();

$queryBuilder = $this->entityManager->createQueryBuilder();
$queryBuilder->update(RefreshToken::class, 'rt')
->set('rt.revoked', true)
->where($queryBuilder->expr()->in(
'rt.accessToken',
$this->entityManager->createQueryBuilder()
->select('at.identifier')
->from(AccessToken::class, 'at')
->where('at.client = :client')
->getDQL()
))
->setParameter('client', $doctrineClient)
->getQuery()
->execute();

$this->entityManager->createQueryBuilder()
->update(AuthorizationCode::class, 'ac')
->set('ac.revoked', true)
->where('ac.client = :client')
->setParameter('client', $doctrineClient)
->getQuery()
->execute();
}
}
21 changes: 21 additions & 0 deletions Service/CredentialsRevokerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Trikoder\Bundle\OAuth2Bundle\Service;

use Symfony\Component\Security\Core\User\UserInterface;
use Trikoder\Bundle\OAuth2Bundle\Model\Client;

/**
* Service responsible for revoking credentials on client-level and user-level.
* Credentials = access tokens, refresh tokens and authorization codes.
*
* @api
*/
interface CredentialsRevokerInterface
{
public function revokeCredentialsForUser(UserInterface $user): void;

public function revokeCredentialsForClient(Client $client): void;
}
Loading

0 comments on commit 5831863

Please sign in to comment.