| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162 |
- <?php
- declare(strict_types=1);
- namespace App\Domain\Auth;
- /**
- * A parsed `Authorization: Bearer ...` value, after format validation but
- * before DB lookup. Used as a parsing intermediate in
- * TokenAuthenticationMiddleware.
- *
- * `parse()` is permissive about whitespace but strict about format: it
- * rejects malformed prefixes, wrong base32 alphabet, and wrong body length
- * up front so the middleware can return 401 without a DB hit.
- */
- final class Token
- {
- private const BODY_PATTERN = '/^[A-Z2-7]{32}$/';
- public function __construct(
- public readonly TokenKind $kind,
- public readonly string $raw,
- ) {
- }
- public static function parse(string $raw): ?self
- {
- if (!str_starts_with($raw, 'irdb_')) {
- return null;
- }
- $parts = explode('_', $raw, 3);
- if (count($parts) !== 3) {
- return null;
- }
- [$prefix, $kindCode, $body] = $parts;
- if ($prefix !== 'irdb') {
- return null;
- }
- $kind = TokenKind::fromCode($kindCode);
- if ($kind === null) {
- return null;
- }
- if (preg_match(self::BODY_PATTERN, $body) !== 1) {
- return null;
- }
- return new self($kind, $raw);
- }
- /**
- * The `token_prefix` we persist for ops/log readability. First 8 chars
- * of the raw token — enough to identify a token without revealing it.
- */
- public function prefix(): string
- {
- return substr($this->raw, 0, 8);
- }
- }
|