Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Session Expiration Laravel Package

ajgl/session-expiration

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Package

    composer require ajgl/session-expiration
    

    For Symfony bundles:

    composer require ajgl/session-expiration-bundle
    
  2. Register the Listener Subscribe the SessionExpirationListener to the kernel.response event in your Symfony kernel (e.g., Kernel.php):

    // src/Kernel.php
    protected function build(RequestContext $requestContext): void
    {
        $this->bus->subscribeTo('kernel.response', SessionExpirationListener::class);
    }
    
  3. Configure Idle Timeout Set the idle timeout (in seconds) via config (e.g., config/packages/ajgl_session_expiration.yaml):

    ajgl_session_expiration:
        idle_timeout: 1800  # 30 minutes
    

    Or programmatically:

    $listener = new SessionExpirationListener();
    $listener->setIdleTimeout(1800); // 30 minutes
    
  4. First Use Case Test by navigating to a protected route, leaving the browser idle, and verifying the session expires after the configured timeout.


Implementation Patterns

Core Workflow

  1. Event-Driven Session Check The listener triggers on every kernel.response event, checking if the session is idle (no activity) and expired.

  2. Integration with Symfony Security

    • Works seamlessly with Symfony’s built-in session and security systems.
    • Extend the SessionExpirationListener to customize behavior (e.g., logging, redirects, or custom responses).
  3. Activity Tracking

    • Session activity is tracked via the lastActivity attribute in the session storage.
    • Example: Update activity on authenticated routes:
      // src/EventListener/ActivityListener.php
      public function onKernelRequest(GetResponseEvent $event)
      {
          if ($event->isMasterRequest() && $this->security->isGranted('IS_AUTHENTICATED')) {
              $event->getRequest()->getSession()->set('lastActivity', time());
          }
      }
      
  4. Bundle Integration For Symfony bundles, enable the bundle in config/bundles.php:

    return [
        // ...
        Ajgl\SessionExpirationBundle\AjglSessionExpirationBundle::class => ['all' => true],
    ];
    

    Configure via config/packages/ajgl_session_expiration.yaml.

  5. Custom Responses Override the default behavior (e.g., redirect to login) by extending the listener:

    class CustomSessionExpirationListener extends SessionExpirationListener
    {
        public function onKernelResponse(FilterResponseEvent $event)
        {
            if ($this->isSessionExpired($event->getRequest())) {
                $event->setResponse(new RedirectResponse('/custom-expired-page'));
            }
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Session Storage Compatibility

    • Ensure your session storage (e.g., symfony/session) supports the lastActivity attribute.
    • For custom storage (e.g., Redis), verify the attribute is persisted correctly.
  2. Event Order Matters

    • The kernel.response event fires after the response is built. If you need to modify the response early (e.g., abort), use kernel.controller or kernel.exception instead.
  3. Double Event Subscription

    • Avoid subscribing the listener multiple times (e.g., in both kernel and bundle). Use Symfony’s EventDispatcher to check for existing subscribers:
      $dispatcher = $this->get('event_dispatcher');
      if (!$dispatcher->hasListeners('kernel.response') || !$dispatcher->hasSubscriber(SessionExpirationListener::class)) {
          $dispatcher->addListener('kernel.response', [new SessionExpirationListener(), 'onKernelResponse']);
      }
      
  4. Time Zone Awareness

    • The lastActivity timestamp uses the server’s time zone. For consistency, ensure all activity updates use time() (UTC) or normalize to a specific time zone.
  5. CSRF Token Issues

    • If using Symfony’s CSRF protection, expired sessions may break forms. Regenerate CSRF tokens after session revival:
      $event->getRequest()->getSession()->regenerateId(true); // Force new session ID
      

Debugging Tips

  1. Log Session Activity Add debug logs to track lastActivity updates:

    public function onKernelResponse(FilterResponseEvent $event)
    {
        $session = $event->getRequest()->getSession();
        $this->logger->debug('Last activity:', ['timestamp' => $session->get('lastActivity')]);
        // ... rest of the logic
    }
    
  2. Test with Short Timeout Set idle_timeout: 10 in config to quickly test expiration behavior during development.

  3. Check for Silent Failures

    • If sessions aren’t expiring, verify:
      • The listener is subscribed to kernel.response.
      • The lastActivity attribute is being updated on every request.
      • No middleware is interfering with the session.

Extension Points

  1. Custom Expiration Logic Extend the listener to implement dynamic timeouts (e.g., based on user roles):

    public function getIdleTimeout(Request $request)
    {
        $user = $this->security->getUser();
        return $user && $user->isAdmin() ? 3600 : 1800; // Admins get 1 hour
    }
    
  2. Grace Period for Inactivity Add a grace period before expiration (e.g., warn users 5 minutes before timeout):

    public function onKernelResponse(FilterResponseEvent $event)
    {
        $session = $event->getRequest()->getSession();
        $inactivity = time() - $session->get('lastActivity', 0);
        if ($inactivity > $this->getIdleTimeout() - 300) { // 5-minute warning
            $this->addWarningToResponse($event->getResponse());
        }
    }
    
  3. Integration with Symfony Guard For Guard-authenticated users, ensure the lastActivity is updated in the authenticated event:

    $event->getRequest()->getSession()->set('lastActivity', time());
    
  4. Session Revival Allow users to revive expired sessions via a "Stay Logged In" button:

    public function reviveSession(Request $request)
    {
        $request->getSession()->set('lastActivity', time());
        return new JsonResponse(['status' => 'revived']);
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui