VOOZH about

URL: https://deepwiki.com/mathsgod/light/5.2.2-jwt-token-system

⇱ JWT Token System | mathsgod/light | DeepWiki


Loading...
Last indexed: 31 January 2026 (cf9511)
Menu

JWT Token System

Overview

The JWT Token System provides stateless authentication for the Light framework using signed tokens. Tokens are generated by App::userLogin(), transported via HttpOnly cookies, validated by Auth\Service, and revoked through cache-based blocklists. The system uses the firebase/php-jwt library for encoding/decoding and ramsey/uuid for generating unique token identifiers (JTI).

Related Documentation:

  • Authentication methods and credential validation: Page 5.2.1
  • Token refresh mechanism: Page 5.2.2
  • Auth Service for user context management: Page 5.4
  • User model and session management: Page 5.3

Token Generation

JWT tokens are generated by the App::userLogin() method after successful authentication. The method creates a signed token containing user identity and session metadata, stores the JWT ID (JTI) for audit purposes, and sets the token as an HttpOnly cookie.

Login Flow with Token Generation


Sources: src/App.php631-685 src/Controller/AuthController.php374-456

Token Payload Structure

The access token payload is constructed at src/App.php636-644:

ClaimTypeValue SourcePurpose
issstring"light server"Issuer identification
jtistringUuid::uuid4()->toString()Unique token ID for revocation
iatintegertime()Issued-at timestamp
expintegertime() + $access_token_expireExpiration timestamp
rolestring"Users"Default RBAC role
idinteger$user->user_idUser primary key
typestring"access_token"Distinguishes from refresh tokens

The token is encoded at src/App.php647 using JWT::encode($payload, $_ENV["JWT_SECRET"], "HS256"). The JTI claim links the token to its UserLog record and enables cache-based revocation.

Refresh Token Payload

A separate refresh token is generated at src/App.php661-668 with a simplified payload:

ClaimTypeValuePurpose
jtistringSame as access tokenLinks to UserLog record
expintegertime() + $refresh_token_expireTypically 7 days
idinteger$user->user_idUser identity
typestring"refresh_token"Prevents misuse as access token

The refresh token is set with a restricted path at src/App.php677-684 to /refresh_token endpoint only.

Sources: src/App.php631-685


Token Transport and Storage

Cookie-Based Transport

Tokens are stored in HttpOnly cookies to prevent JavaScript access. The App::setAccessTokenCookie() method at src/App.php614-629 configures the cookie with security attributes:

ParameterValueEnvironment VariableDefault
name"access_token"N/AN/A
valueJWT token stringN/AN/A
path"/"N/AN/A
domainEmpty or shared domain$_ENV["COOKIE_DOMAIN"]""
securetrue/false$_ENV["COOKIE_SECURE"]false
httponlytrueN/AAlways enabled
samesiteLax/Strict/None$_ENV["COOKIE_SAMESITE"]"Lax"

Partitioned Cookie Support

For HTTPS deployments with $_ENV["COOKIE_PARTITIONED"] == "true", the method appends ;Partitioned to the SameSite value at src/App.php616-620 This enables cookies in third-party contexts with CHIPS (Cookies Having Independent Partitioned State).

Refresh Token Cookie

The refresh token uses a different path configuration at src/App.php677-684:

  • Cookie name: "refresh_token"
  • Path: "{API_PREFIX}/refresh_token" (restricted endpoint)
  • Expires: time() + $refresh_token_expire (typically 7 days)
  • Other settings: Same as access token

Sources: src/App.php614-629 src/App.php677-684


Token Validation

Token validation occurs in the Auth\Service class during request processing. The middleware extracts the token from the cookie, decodes it using the JWT library, and verifies the signature and expiration.

Validation Flow

Token validation occurs in Auth\Service during the App::process() middleware phase:


The Auth\Service constructor performs validation and stores the user context. GraphQL resolvers access the authenticated user via #[InjectUser] annotations or $authService->getUser().

Validation Steps:

  1. Extract access_token from $request->getCookieParams()
  2. Decode with JWT::decode($token, new Key($_ENV["JWT_SECRET"], "HS256"))
  3. Check $cache->get("revoked_token_{$jti}") for revocation
  4. Load User::Get($payload->id) if token is valid

Sources: src/App.php500-537


Token Revocation

The Light framework implements immediate token revocation using a cache-based blocklist. When a user logs out, the token's JTI is stored in cache with a TTL matching the token's remaining lifetime.

Logout and Revocation Mechanism

The AuthController::logout() mutation at src/Controller/AuthController.php334-370 implements immediate token revocation:


Sources: src/Controller/AuthController.php334-370

Revocation Implementation

The revocation logic at src/Controller/AuthController.php336-340 uses cache with a TTL matching the refresh token lifetime:


Key characteristics:

AspectImplementation
Cache key"revoked_token_{$jti}"
Cache valuetrue (boolean)
TTL$app->getRefreshTokenExpire() (typically 7 days)
Check locationAuth\Service during token validation

The cache-based approach provides:

  • O(1) Lookup: No database query during validation
  • Automatic Expiration: Cache entries self-clean after token lifetime
  • Distributed Support: Works across multiple servers with shared cache
  • Immediate Effect: Revocation active on next request

The UserLog table is updated at src/Controller/AuthController.php343-347 with the logout timestamp for audit trails.

Sources: src/Controller/AuthController.php334-370


User Activity Logging

Every token generation creates a corresponding record in the UserLog table, establishing a complete audit trail of authentication events.

UserLog Schema Integration


The UserLog::_table()->insert() call at src/App.php650-657 creates audit records:

ColumnValue SourceExample
user_id$user->user_id42
login_dtdate("Y-m-d H:i:s")"2024-01-15 14:30:00"
result"SUCCESS" or "FAIL""SUCCESS"
ip$_SERVER["REMOTE_ADDR"]"192.168.1.100"
user_agent$_SERVER["HTTP_USER_AGENT"]"Mozilla/5.0..."
jti$jti from UUID generation"550e8400-..."

The jti column links the JWT token to its audit record and is used for revocation lookups. On logout, UserLog::_table()->update() at src/Controller/AuthController.php343-347 sets the logout_dt field.

Failed login attempts are logged at src/Controller/AuthController.php409-415 with result = "FAIL" to support auth lockout mechanisms.

Sources: src/App.php650-657 src/Controller/AuthController.php343-347 src/Controller/AuthController.php409-415


Token Expiration Configuration

Token lifetimes are configurable through the Config model:

Access Token Expiration

The App::getAccessTokenExpire() method at src/App.php602-606 returns:


Default: 900 seconds (15 minutes)

Refresh Token Expiration

The App::getRefreshTokenExpire() method at src/App.php608-612 returns:


Default: 604,800 seconds (7 days)

Impact on System Behavior

ConfigurationAffected Components
access_token_expireJWT exp claim at src/App.php640
refresh_token_expireRefresh token exp claim at src/App.php665 revocation cache TTL at src/Controller/AuthController.php339

The refresh token lifetime determines how long revoked JTIs remain in cache, as the cache TTL must cover the maximum token validity period.

Sources: src/App.php602-612 src/App.php636-644 src/App.php661-668 src/Controller/AuthController.php336-340


Integration Points

App Class Methods

The App class provides the core token generation method:

AuthController Methods

The AuthController exposes GraphQL mutations for authentication:

Dependencies

The JWT system relies on:

  • firebase/php-jwt: Token encoding and decoding library
  • ramsey/uuid: JTI generation via UUID v4
  • Symfony Cache: Token revocation blocklist storage
  • UserLog Model: Audit trail persistence

Sources: src/App.php6 src/App.php29 src/Controller/AuthController.php7-8