1. Go to this page and download the library: Download ecourty/token-bundle library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
use Ecourty\TokenBundle\Contract\TokenSubjectInterface;
class User implements TokenSubjectInterface
{
public function getTokenSubjectId(): string
{
return (string) $this->id;
}
}
use Ecourty\TokenBundle\Service\TokenManager;
class PasswordResetService
{
public function __construct(private TokenManager $tokenManager) {}
public function sendResetLink(User $user): void
{
$token = $this->tokenManager->create(
type: 'password_reset',
subject: $user,
expiresIn: '+1 hour',
singleUse: true,
);
// $token->getToken() — the secure random string to
$token = $this->tokenManager->get($tokenString, 'password_reset');
// Token is valid — show the reset form, resolve the subject, etc.
$user = $this->tokenManager->resolveSubject($token);
// By token string
$token = $this->tokenManager->consume($tokenString, 'password_reset');
// Or by Token entity (e.g. after a get() call)
$token = $this->tokenManager->get($tokenString, 'password_reset');
// ... display a form, check the subject, etc.
$this->tokenManager->consume($token);
use Ecourty\TokenBundle\Exception\TokenAlreadyConsumedException;
use Ecourty\TokenBundle\Exception\TokenExpiredException;
use Ecourty\TokenBundle\Exception\TokenMaxUsesReachedException;
use Ecourty\TokenBundle\Exception\TokenNotFoundException;
use Ecourty\TokenBundle\Exception\TokenRevokedException;
try {
$token = $this->tokenManager->consume($tokenString, 'password_reset');
} catch (TokenNotFoundException) {
// Token does not exist or wrong type
} catch (TokenExpiredException) {
// Token has expired
} catch (TokenRevokedException) {
// Token was manually revoked
} catch (TokenAlreadyConsumedException) {
// Single-use token already used
} catch (TokenMaxUsesReachedException) {
// Max uses reached
}
// Revoke a specific token by its string value
$this->tokenManager->revoke($tokenString);
// Revoke all password_reset tokens for a user
$count = $this->tokenManager->revokeAll($user, 'password_reset');
// Revoke ALL tokens for a subject regardless of type
$count = $this->tokenManager->revokeAll($user);
$token = $this->tokenManager->findValid($user, 'password_reset');
if ($token === null) {
// No valid token exists — create a new one
}
$token = $this->tokenManager->consume($tokenString, 'password_reset');
$user = $this->tokenManager->resolveSubject($token);
if ($user === null) {
// Subject entity was deleted
}
use Ecourty\TokenBundle\Attribute\RequiresToken;
use Ecourty\TokenBundle\Entity\Token;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
class DocumentController
{
#[RequiresToken(type: 'share')]
public function view(Request $request): JsonResponse
{
// The validated Token entity is available in the request
$token = $request->attributes->get('_token');
assert($token instanceof Token);
return new JsonResponse(['document' => '...']);
}
}
use Ecourty\TokenBundle\Resolver\QueryStringTokenResolver;
#[RequiresToken(type: 'share', resolver: QueryStringTokenResolver::class)]
public function sharedDocument(Request $request): JsonResponse
{
// Token is read from ?token=...
}
use Ecourty\TokenBundle\Contract\TokenResolverInterface;
use Symfony\Component\HttpFoundation\Request;
class BearerTokenResolver implements TokenResolverInterface
{
public function resolve(Request $request): ?string
{
$header = $request->headers->get('Authorization');
if ($header !== null && str_starts_with($header, 'Bearer ')) {
return substr($header, 7);
}
return null;
}
}
#[RequiresToken(type: 'api_access', resolver: BearerTokenResolver::class)]
public function apiEndpoint(Request $request): JsonResponse
{
// Token is extracted from the Authorization header
}
use Ecourty\TokenBundle\Event\TokenAccessDeniedEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
use Symfony\Component\HttpFoundation\JsonResponse;
#[AsEventListener]
class TokenAccessDeniedHandler
{
public function __invoke(TokenAccessDeniedEvent $event): void
{
$event->setResponse(new JsonResponse(
['error' => 'Invalid or missing token'],
403,
));
}
}
use Ecourty\TokenBundle\Event\TokenCreatedEvent;
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
#[AsEventListener]
class TokenCreatedListener
{
public function __invoke(TokenCreatedEvent $event): void
{
// e.g. log, send notification, audit trail...
}
}