Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
}
],
"require": {
"pdsinterop/solid-auth": "v0.13.0",
"pdsinterop/solid-auth": "dev-feature/configurable-repositoryFactory",
"pdsinterop/solid-crud": "v0.8.1",
"phpmailer/phpmailer": "^6.10",
"sweetrdf/easyrdf": "~1.15.0",
Expand Down
6 changes: 6 additions & 0 deletions init.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ function initDatabase() {
type VARCHAR(255) NOT NULL,
expires TEXT NOT NULL
)',
'CREATE TABLE IF NOT EXISTS oauth2Repository (
type VARCHAR(255) NOT NULL,
key VARCHAR(255) NOT NULL,
value TEXT NOT NULL,
expires TEXT NOT NULL
)',
];

try {
Expand Down
111 changes: 111 additions & 0 deletions lib/Repository/RefreshToken.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php
namespace Pdsinterop\PhpSolid\Repository;

use Pdsinterop\PhpSolid\Db;
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException;
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
use Pdsinterop\Solid\Auth\Entity\RefreshToken as RefreshTokenEntity;

class RefreshToken implements RefreshTokenRepositoryInterface
{
/**
* Creates a new refresh token
*
* @return RefreshTokenEntityInterface|null
*/
public function getNewRefreshToken() : ?RefreshTokenEntityInterface
{
return new RefreshTokenEntity();
}

/**
* Called when a new refresh token is created
*
* @param RefreshTokenEntityInterface $refreshTokenEntity
*
* @throws UniqueTokenIdentifierConstraintViolationException
*/
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity) : void
{
// throw new UniqueTokenIdentifierConstraintViolationException;
/*/
When a new refresh token is created this method will be called. You don’t have to do anything here but for
auditing you might want to.

The refresh token entity passed in has a number of methods you can call which contain data worth saving to
a database:

getIdentifier() : string this is randomly generated unique identifier (of 80+ characters in length) for the refresh token.
getExpiryDateTime() : \DateTime the expiry date and time of the refresh token.
getAccessToken()->getIdentifier() : string the linked access token’s identifier.

JWT access tokens contain an expiry date and so will be rejected automatically when used. You can safely
clean up expired access tokens from your database.
/*/
Db::connect();
$query = Db::$pdo->prepare(
'INSERT INTO oauth2Repository VALUES(:type, :key, :value, :expiry)'
);
// FIXME: value should not be the identifier of the refresh token, but the refresh token itself?
$query->execute([
':type' => 'refreshToken',
':key' => $refreshTokenEntity->getIdentifier(),
':value' => $refreshTokenEntity->getAccessToken()->getIdentifier(),
':expiry' => $refreshTokenEntity->getExpiryDateTime()->getTimestamp()
]);
}

/**
* Revoke the refresh token.
*
* @param string $tokenId
*/
public function revokeRefreshToken($tokenId) : void
{
/*/
This method is called when a refresh token is used to reissue an access token.

The original refresh token is revoked a new refresh token is issued.
/*/
Db::connect();
$now = new \DateTime();
$query = Db::$pdo->prepare(
'DELETE FROM oauth2Repository WHERE type = :type AND key = :key'
);
$query->execute([
':type' => 'refreshToken',
':key' => $tokenId
]);
}

/**
* Check if the refresh token has been revoked.
*
* @param string $tokenId
*
* @return bool Return true if this token has been revoked
*/
public function isRefreshTokenRevoked($tokenId) : bool
{
/*/
This method is called when an refresh token is used to issue a new access token.

Return true if the refresh token has been manually revoked before it expired.
If the token is still valid return false.
/*/
return false;
}

public static function cleanup() {
Db::connect();
$now = new \DateTime();
$query = Db::$pdo->prepare(
'DELETE FROM oauth2Repository WHERE type = :type AND expires < :now'
);
$query->execute([
':type' => 'refreshToken',
':now' => $now->getTimestamp()
]);
}
}
6 changes: 5 additions & 1 deletion lib/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
namespace Pdsinterop\PhpSolid;

use Pdsinterop\Solid\Auth\Factory\AuthorizationServerFactory;
use Pdsinterop\Solid\Auth\Factory\RepositoryFactory;
use Laminas\Diactoros\Response;
use Pdsinterop\Solid\Auth\Server as SolidAuthServer;
use Pdsinterop\Solid\Auth\Factory\ConfigFactory;
Expand All @@ -13,6 +14,8 @@
use Pdsinterop\Solid\Auth\TokenGenerator;
use Pdsinterop\PhpSolid\ClientRegistration;
use Pdsinterop\PhpSolid\JtiStore;
use Pdsinterop\Solid\Auth\Enum\Repository;
use Pdsinterop\PhpSolid\Repository\RefreshToken as RefreshTokenRepository;

class Server {
public static function generateKeySet() {
Expand Down Expand Up @@ -40,6 +43,7 @@ public static function generateKeySet() {
public static function getAuthServer() {
$authServerConfig = self::getAuthServerConfig();
$authServerFactory = new AuthorizationServerFactory($authServerConfig);
$authServerFactory->setRepository(Repository::REFRESH_TOKEN, new RefreshTokenRepository());
$authServer = $authServerFactory->create();
$response = new Response();
$server = new SolidAuthServer($authServer, $authServerConfig, $response);
Expand All @@ -60,7 +64,7 @@ public static function getAuthServerConfig() {
$authServerConfig = $authServerConfigFactory->create();
return $authServerConfig;
}

public static function getConfigClient() {
$clientId = $_GET['client_id'] ?? $_POST['client_id'] ?? null;
if ($clientId) {
Expand Down
Loading