Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Laravel Livewire Turbolinks Blade component to keep session alive
{{-- You do not need to add this component if you are using the permanent option in the head component --}}
<script>
if (!window.sessionTimerPermanent && window.Livewire) {
window.livewire.hook('afterDomUpdate', startSessionTimer)
}
// if you are on livewire > 1.3.1 and want to avoid the default error alert
// https://github.com/livewire/livewire/pull/1146
window.livewire.onError(statusCode => {
if (statusCode === 419) {
return
}
})
*/
</script>
@props([ 'permanent' => false, 'expiresIn' => 10 ])
@php
$session = config('session.lifetime');
$message = trans('messages.session_expiration_warning', ['expires' => $expiresIn]); //example: 'Your session will expire in :expires minutes, due to inactivity! Click OK to avoid being logged out.'
@endphp
<script>
let sessionTimer = null
function clearTimer() {
clearTimeout(sessionTimer)
sessionTimer = null
}
function handleSessionWarning() {
alert('{{ $message }}')
checkAuth() // remove if you want to run this automatically on window.focus after clicking the alert, see end of script.
}
function startSessionTimer() {
clearTimer()
sessionTimer = setTimeout(handleSessionWarning, 1000 * 60 * {{ $session - $expiresIn }})
}
function checkAuth() {
if (document.hasFocus()) { //remove this if you want to keep the session alive even if the window is out of focus
// console.info('fetching')
fetch('/check-auth')
.then(response => response.text())
.then(auth => {
if (auth !== 'true') {
window.location.href = "{{ route('login') }}"
}
@if(!$permanent)
startSessionTimer()
@endif
})
}
}
@if($permanent)
window.sessionTimerPermanent = true
setInterval(checkAuth, 1000 * 60 * {{ $session - 2 }})
@else
window.sessionTimerPermanent = false
// document.addEventListener('turbolinks:load', startSessionTimer) //uncomment if you use turbolinks
document.addEventListener('DOMContentLoaded', startSessionTimer) //remove if you use tubolinks
@endif
// window.addEventListener('focus', checkAuth) //uncomment this if you remove checkAuth() above, observe that this makes an extra request on each window.focus
</script>
Route::get('check-auth', fn () => response(auth()->check() ? 'true' : 'false'))->middleware('auth');
@tanthammar
Copy link
Author

tanthammar commented Jun 20, 2020

  1. Option to keep session alive permanently. (has been tested with sleeping computer, macosx)
  2. Resets on Turbolinks and Livewire loaded events
  3. Alerts the User 10 minutes before session is ending
  4. Does not poll the server if the window is not in focus, (can be changed)
  5. If the window has been out of focus it checks if the session is active, else redirects to login
  6. Redirects to login if the session has expired.
  7. Uses config('session.lifetime') for the session timer
  8. You can use it without Turbolinks and Livewire

Use

In the head

<x-session-timeout-alert-head :permanent="false" :expiresIn="10" />
</head>

After livewire scripts, not needed if permanent=true, or the page doesn't use Turbolinks/Livewire

@livewireScripts
<x-session-timeout-alert-after-livewire-scripts />
</body>

@tanthammar
Copy link
Author

tanthammar commented Aug 21, 2020

UPDATE: Livewire v1.3.1 has error handling.

If you do not wish to use the timer and simply want to redirect the user to the login page you can ignore all the code above and instead add this to your main layout.

     window.livewire.onError(statusCode => {
        if (statusCode === 419) {
            window.location.href = "{{ route('login') }}"
        }
     })

Source ->

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment