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 Bundle Laravel Package

ajgl/session-expiration-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle

    composer require ajgl/session-expiration-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        Ajgl\SessionExpirationBundle\AjglSessionExpirationBundle::class => ['all' => true],
    ];
    
  2. Configure Expiration Add configuration to config/packages/ajgl_session_expiration.yaml:

    ajgl_session_expiration:
        idle_timeout: 300  # 5 minutes (in seconds)
        absolute_timeout: 1800  # 30 minutes (optional)
        check_interval: 60  # Check every 60 seconds
        storage: session  # or 'database' if using custom storage
    
  3. First Use Case: Basic Idle Session Handling The bundle automatically tracks user inactivity. No additional code is needed for core functionality. Test by:

    • Opening a browser, logging in, and leaving it idle.
    • Returning after the idle_timeout period—you should be redirected to a login page or see a session expired notice.

Implementation Patterns

Core Workflows

  1. Event-Based Integration Listen to the session.expiration event to customize behavior (e.g., logging, notifications):

    // src/EventListener/SessionExpirationListener.php
    namespace App\EventListener;
    
    use Ajgl\SessionExpirationBundle\Event\SessionExpirationEvent;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    
    class SessionExpirationListener implements EventSubscriberInterface
    {
        public static function getSubscribedEvents()
        {
            return [
                SessionExpirationEvent::NAME => 'onSessionExpiration',
            ];
        }
    
        public function onSessionExpiration(SessionExpirationEvent $event)
        {
            // Custom logic (e.g., log user out gracefully)
            $event->getUser()->getRoles(); // Access user data
        }
    }
    
  2. Custom Storage (Database Example) Extend the bundle’s storage interface to use a database:

    // src/Storage/DatabaseSessionStorage.php
    namespace App\Storage;
    
    use Ajgl\SessionExpirationBundle\Storage\SessionStorageInterface;
    use Doctrine\ORM\EntityManagerInterface;
    
    class DatabaseSessionStorage implements SessionStorageInterface
    {
        public function __construct(private EntityManagerInterface $em) {}
    
        public function updateLastActivity(string $sessionId, int $timestamp): void
        {
            $entity = $this->em->getRepository(Session::class)->find($sessionId);
            $entity->setLastActivity($timestamp);
            $this->em->flush();
        }
    
        public function isExpired(string $sessionId, int $idleTimeout): bool
        {
            $entity = $this->em->getRepository(Session::class)->find($sessionId);
            return $entity && (time() - $entity->getLastActivity()) > $idleTimeout;
        }
    }
    

    Register the service in config/services.yaml:

    services:
        App\Storage\DatabaseSessionStorage: ~
        ajgl_session_expiration.storage: '@App\Storage\DatabaseSessionStorage'
    
  3. Excluding Routes Skip session checks for specific routes (e.g., API endpoints) by tagging them:

    # config/routes.yaml
    api_login:
        path: /api/login
        controller: App\Controller\ApiAuthController::login
        methods: POST
        ajgl_session_expiration: false  # Disable session check
    
  4. Dynamic Timeout Adjustment Override the timeout per user or role via a listener:

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        if ($request->hasPreviousSession()) {
            $user = $request->getUser();
            if ($user && $user->hasRole('ADMIN')) {
                $this->sessionExpiration->setIdleTimeout(1800); // 30 mins for admins
            }
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Symfony Version Mismatch The bundle requires Symfony 2.3+ (per composer.json). Test thoroughly if using Symfony 3/4/5—some features (e.g., event dispatching) may behave differently.

    • Fix: Use a compatible version or fork the bundle for modern Symfony.
  2. Session Storage Conflicts The default session storage relies on PHP’s native session handling. If using custom session handlers (e.g., Redis, Memcached), ensure they support session_start() and session_write_close().

    • Fix: Implement SessionStorageInterface for your storage backend.
  3. Event Dispatching Timing The session.expiration event fires after the session is marked expired. If you need to act before (e.g., warn the user), use a kernel.request listener to manually check expiration:

    public function onKernelRequest(GetResponseEvent $event)
    {
        if ($event->isMasterRequest() && !$this->isSessionActive($event->getRequest())) {
            $event->setResponse(new RedirectResponse('/session-expired'));
        }
    }
    
  4. Absolute Timeout Overrides Idle Timeout If both idle_timeout and absolute_timeout are set, the session expires at the earlier of the two times. Test edge cases (e.g., a user active right before absolute_timeout).

Debugging Tips

  1. Log Expiration Events Enable debug mode and log the event:

    # config/services.yaml
    Ajgl\SessionExpirationBundle\EventListener\SessionExpirationListener:
        tags:
            - { name: kernel.event_subscriber }
        arguments:
            $logger: '@logger'
    

    Then implement logging in your subscriber.

  2. Check Session Data Dump session data to verify the bundle is tracking activity:

    // In a controller or listener
    dump($_SESSION['ajgl_session_expiration_last_activity']);
    
  3. Disable for Testing Temporarily disable the bundle in config/bundles.php during tests:

    Ajgl\SessionExpirationBundle\AjglSessionExpirationBundle::class => ['test' => false],
    

Extension Points

  1. Custom Expiration Logic Override the Ajgl\SessionExpirationBundle\SessionExpiration service to add logic:

    # config/services.yaml
    services:
        ajgl_session_expiration:
            class: App\Service\CustomSessionExpiration
            parent: ajgl_session_expiration
            arguments:
                $storage: '@App\Storage\DatabaseSessionStorage'
    
  2. Add a "Stay Logged In" Option Extend the bundle to support a "remember me" checkbox that resets the idle timer:

    // In your login form handler
    if ($form->isSubmitted() && $form->isValid() && $form->get('remember_me')->isClicked()) {
        $this->sessionExpiration->setIdleTimeout(2592000); // 30 days
    }
    
  3. Integrate with Security Events Trigger a security.interactive_login event when a session is revived after expiration:

    public function onSessionExpiration(SessionExpirationEvent $event)
    {
        if ($event->isRevived()) {
            $this->eventDispatcher->dispatch(
                new InteractiveLoginEvent($event->getUser(), $event->getRequest()),
                'security.interactive_login'
            );
        }
    }
    
  4. Localization Support Customize the expiration message in Twig:

    {% if app.session_expired %}
        {{ 'session.expired.message'|trans({
            '%timeout%': ajgl_session_expiration.idle_timeout|date('i minutes')
        }) }}
    {% endif %}
    

    Add translations to translations/messages.en.yaml.

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