Files
preauth/src/Trait/MakeNonceTrait.php
T
lyra cb378e20bc
Sync GitHub / sync (push) Failing after 5s
Tests / test (pull_request) Successful in 49s
chore: add php-cs-fixer with PSR-12 config and CI check
- Add friendsofphp/php-cs-fixer to require-dev
- Create .php-cs-fixer.dist.php configured for @PSR12 ruleset
- Add php-cs-fixer dry-run step to CI pipeline
- Auto-fix existing PSR-12 violations
- Document code style tooling in readme.md
2026-08-11 08:30:05 -04:00

59 lines
1.7 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Trait;
use Exception;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Cache\InvalidArgumentException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Contracts\Service\Attribute\Required;
trait MakeNonceTrait
{
use HasLoggerTrait;
use StringTrait;
/* 15 bytes neatly fits in base64 */
private const int NONCE_LENGTH = 15;
private const int NONCE_TTL = 120;
protected readonly CacheItemPoolInterface $nonceCache;
#[Required]
public function setNonceCache(CacheItemPoolInterface $nonceCache): void
{
$this->nonceCache = $nonceCache;
}
/** @throws InvalidArgumentException|Exception */
protected function makeNonce(int $retries = 3): string
{
/* convert raw binary into base64url */
$nonce = rtrim(strtr(base64_encode(random_bytes(
static::NONCE_LENGTH
)), '+/', '-_'), '=');
$nonceItem = $this->nonceCache->getItem($this->makeCacheKey($nonce));
if ($nonceItem->isHit()) {
if ($retries < 1) {
$this->logger->error("aborting: multiple nonce collisions");
throw new HttpException(
Response::HTTP_INTERNAL_SERVER_ERROR,
'Internal Server Error'
);
}
/* managed to have a collision, try again */
return $this->makeNonce($retries - 1);
}
$nonceItem->set(true); /* valid */
$nonceItem->expiresAfter(static::NONCE_TTL);
$this->logger->debug("added nonce: $nonce");
$this->nonceCache->save($nonceItem);
return $nonce;
}
}