VOOZH about

URL: https://deepwiki.com/mathsgod/light/5.3-user-model-and-sessions

⇱ User Model and Sessions | mathsgod/light | DeepWiki


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

User Model and Sessions

Overview

The User model src/Model/User.php48 serves as the central identity object in the Light framework. It extends Light\Model and provides:

  • User profile data (name, email, contact information)
  • Authentication credentials and linked OAuth accounts
  • Session lifecycle management via the UserLog table
  • Active session queries and individual session revocation
  • Account lockout protection against brute-force attacks
  • Permission and role queries via RBAC integration
  • User preferences (language, menu, styles)

Sessions are tracked through the UserLog table, which records every login attempt (successful or failed) and maintains session state including JWT identifiers (jti), login/logout timestamps, client IP addresses, and last access times. The User model provides methods to query active sessions, revoke specific sessions, and enforce account lockout policies based on failed login attempts.

For authentication methods (password, JWT, OAuth, WebAuthn, 2FA), see page 5.2. For JWT token validation and user context injection, see page 5.4. For RBAC permission checking, see page 5.5.

User Model Properties

The User model src/Model/User.php48 extends Light\Model and contains properties across several categories. All properties are exposed via GraphQL annotations src/Model/User.php29-46

Identity and Profile Fields

PropertyTypeGraphQL TypePurpose
user_idintIntPrimary key
usernamestringStringUnique login identifier
first_namestringStringUser's first name
last_namestringStringUser's last name
emailstringStringEmail address
phonestringStringPhone number
addr1stringStringAddress line 1
addr2stringStringAddress line 2
addr3stringStringAddress line 3

Authentication and Security Fields

PropertyTypePurpose
passwordstringBcrypt hashed password
password_dtdatetimePassword creation timestamp (for expiration)
secretstringTOTP secret for 2FA (NULL if not enabled)
credentialarrayWebAuthn credential objects for biometric auth
googlestringLinked Google account identifier
microsoftstringLinked Microsoft account identifier
facebookstringLinked Facebook account identifier
statusint0=active, 1=disabled

Preference and Configuration Fields

PropertyTypePurpose
languagestringPreferred UI language code
default_pagestringDefault landing page path
stylearrayUser-specific style preferences (JSON)
menuarrayCustom menu configuration (JSON)
join_datestringAccount creation date
expiry_datestringAccount expiration date (NULL if no expiration)

User Model Property Categories


Sources: src/Model/User.php18-46

Session Tracking with UserLog

Sessions are tracked through the UserLog table, which records both successful and failed login attempts. Each login attempt creates a UserLog record with the following structure:

FieldTypePurpose
userlog_idintPrimary key
user_idintForeign key to User table
jtistringJWT ID (unique session identifier, NULL for failed attempts)
login_dtdatetimeLogin attempt timestamp
logout_dtdatetimeSession termination timestamp (NULL if active)
resultenum"SUCCESS" or "FAIL"
ipstringClient IP address
user_agentstringBrowser/client user agent string
last_access_timedatetimeMost recent authenticated request timestamp

Key Characteristics:

  • Successful logins create records with result="SUCCESS" and a unique jti value
  • Failed logins create records with result="FAIL" and jti=NULL
  • Active sessions have logout_dt=NULL
  • Terminated sessions have logout_dt set to the logout timestamp
  • Session activity is tracked via last_access_time, updated on each authenticated request

The jti (JWT ID) field links the UserLog record to the refresh token issued during login. This enables precise session tracking and individual session revocation.

Session Lifecycle: UserLog Record Creation and Updates


Sources: src/Model/User.php50-54 src/Model/User.php201-204 src/Auth/Service.php28-80

Querying Active Sessions

The getSessions() method src/Model/User.php56-82 returns all currently active sessions for a user. This is exposed as a GraphQL field on the User type.

Query Logic

The method constructs a UserLog query with the following filters:

  1. user_id matches the current user
  2. result = "SUCCESS" (only successful logins)
  3. logout_dt IS NULL (session not explicitly logged out)
  4. login_dt > now() - access_token_expire (within token validity window)

The access token expiration time is retrieved from App::getAccessTokenExpire() src/Model/User.php59 Only sessions whose login time falls within this window are considered active.

Returned Session Data

Each session object contains:

FieldTypeSource
is_currentbooleanCompares UserLog.jti with current request's jti
jtistringJWT ID from UserLog.jti
ipstringClient IP from UserLog.ip
login_dtdatetimeLogin timestamp from UserLog.login_dt
user_agentstringBrowser/client from UserLog.user_agent
locationmixedIP geolocation via App::getIpLocation(ip)
last_access_timedatetimeMost recent activity from UserLog.last_access_time

The is_current flag identifies which session belongs to the current request by comparing JWT IDs src/Model/User.php70

getSessions() Query Flow


GraphQL Query Example


Sources: src/Model/User.php56-82

Session Revocation

The revokeSession() method src/Model/User.php50-54 enables users to terminate individual sessions without logging out all devices.

Revocation Process

The method takes a jti (JWT ID) parameter and performs the following operation:


This updates the UserLog record to set logout_dt to the current timestamp, marking the session as terminated. The WHERE clause ensures:

  • The session belongs to the current user (user_id match)
  • Only the specific session is revoked (jti match)

Impact on Token Lifecycle

Session revocation affects tokens as follows:

Token TypeEffectTimeline
Refresh TokenImmediately invalidCannot be used at /refresh_token endpoint
Access TokenRemains validExpires naturally (default 15 minutes)

The revokeSession() method only updates the database record. For immediate access token invalidation, the system also uses cache-based revocation (see page 5.2.2). The AuthController::logout() method adds the jti to a cache key revoked_token_{jti}, which is checked by Auth\Service during request validation src/Auth/Service.php58-60

Session Revocation: Database vs Cache


Sources: src/Model/User.php50-54 src/Auth/Service.php58-60

Session Activity Tracking

The saveLastAccessTime() method src/Model/User.php201-204 updates the UserLog.last_access_time field on each authenticated request. This enables:

  • Active session identification: Distinguish between actively used and idle sessions
  • Security auditing: Track when each session was last used
  • Idle timeout policies: Identify sessions eligible for automatic expiration

Implementation


The method is called by Auth\Service during JWT validation src/Auth/Service.php71 When a valid access token is presented, the authentication service:

  1. Decodes the JWT and extracts the jti
  2. Loads the User object by ID
  3. Calls saveLastAccessTime() with the jti
  4. Updates the UserLog record with the current timestamp

This occurs on every authenticated request, providing real-time visibility into session activity. The getSessions() method includes this field in its response, allowing users to see when each of their sessions was last active.

Activity Tracking Flow


Sources: src/Model/User.php201-204 src/Auth/Service.php69-72

Account Lockout Protection

The isAuthLocked() method src/Model/User.php206-227 implements brute-force protection by temporarily locking accounts after repeated failed login attempts.

Lockout Logic

The method performs the following steps:

  1. Get client IP: Retrieves IP address from $_SERVER["REMOTE_ADDR"] src/Model/User.php208
  2. Load configuration: Reads lockout parameters from Config model:
    • auth_lockout_duration: Minutes account remains locked (default: 15)
    • auth_lockout_attempts: Failed attempts before lockout (default: 5)
  3. Query recent failures: Queries UserLog for records matching:
    • user_id = current user
    • ip = client IP address
    • login_dt > (current time - lockout duration)
  4. Count failures: Iterates through records ordered by userlog_id src/Model/User.php218
  5. Check threshold: Returns true if failure count >= lockout attempts threshold

The lockout is per-user per-IP, meaning different IP addresses can attempt login independently for the same user account.

Configuration Parameters

Config KeyDefaultPurpose
auth_lockout_duration15Minutes an account remains locked after threshold reached
auth_lockout_attempts5Number of consecutive failures before lockout triggers

These values are retrieved via Config::Value() src/Model/User.php213-215 and can be modified at runtime without code changes.

Account Lockout Check Flow


Login Flow with Lockout Check


Sources: src/Model/User.php206-227

Lockout Characteristics

The implementation has the following behavior:

  • Per-user per-IP: Each user/IP combination has independent failure tracking
  • Time-windowed: Only failures within the lockout duration window count
  • Automatic expiry: After the duration window passes, the account automatically unlocks
  • Successful login clears: A successful login from any IP does not affect lockout state (each IP tracked separately)

Integration with Login Flow

The AuthController::login() method checks lockout status before attempting password verification. If locked, the login attempt is rejected with an error message indicating the remaining lockout time. Failed password verifications create UserLog records with result="FAIL" and jti=NULL, which increment the failure counter.

Sources: src/Model/User.php206-227

Additional User Methods for Session Management

Beyond the core session methods, the User model provides several additional capabilities related to user context and permissions:

Permission and Role Queries

MethodReturn TypePurpose
getPermissions()string[]Returns all permissions granted to user via RBAC src/Model/User.php192-199
getRoles()string[]Returns role names assigned to user src/Model/User.php297-311
isGranted()boolChecks if user has specific permission src/Model/User.php283-291
isGrantedRights()string[]Filters permission list to those user has src/Model/User.php268-280
is()boolChecks if user has specific role src/Model/User.php337-340

These methods delegate to the Light\Rbac system (see page 5.5 for details).

Menu and Navigation

MethodReturn TypePurpose
getMenu()arrayReturns user's custom menu configuration src/Model/User.php88-94
isAllowedPath()boolChecks if user can access menu path src/Model/User.php97-123

Audit Logs

MethodReturn TypePurpose
getUserLog()QueryReturns user's login history src/Model/User.php375-378
getEventLog()QueryReturns user's action audit trail src/Model/User.php385-388

User Management

MethodReturn TypePurpose
canDelete()boolChecks if user can be deleted by another user src/Model/User.php317-335
canUpdate()boolChecks if user can be updated by another user src/Model/User.php350-368
getName()stringReturns concatenated first and last name src/Model/User.php344-347

Sources: src/Model/User.php88-388

UserLog Schema

The UserLog model tracks all login attempts and session lifecycle events. Key fields include:

FieldTypePurpose
userlog_idintPrimary key
user_idintForeign key to User
jtistringJWT ID for this session (NULL for failed attempts)
login_dtdatetimeWhen the login attempt occurred
logout_dtdatetimeWhen the session was terminated (NULL if active)
resultstring"SUCCESS" or "FAIL"
ipstringClient IP address
user_agentstringBrowser/client identifier
last_access_timedatetimeMost recent authenticated request

This data enables:

  • Active session listing via User::getSessions()
  • Account lockout enforcement via User::isAuthLocked()
  • Security auditing and login history via User::getUserLog()
  • Session revocation via User::revokeSession()

Sources: src/Model/User.php375-378 src/Controller/AuthController.php343-347 src/Controller/AuthController.php409-415