Bind app sessions to the platform auth session.
Deploy Ladill Transfer / deploy (push) Successful in 29s
Deploy Ladill Transfer / deploy (push) Successful in 29s
Clear local sessions when auth.ladill.com signs out and ping the platform session from keepalive. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -138,6 +138,18 @@ class SsoLoginController extends Controller
|
|||||||
return redirect()->away($this->defaultSignedOutUrl());
|
return redirect()->away($this->defaultSignedOutUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Platform session ended — clear this app and offer silent sign-in again. */
|
||||||
|
public function platformSignedOut(Request $request): RedirectResponse
|
||||||
|
{
|
||||||
|
Auth::logout();
|
||||||
|
$request->session()->invalidate();
|
||||||
|
$request->session()->regenerateToken();
|
||||||
|
|
||||||
|
return redirect()->route('sso.connect', [
|
||||||
|
'redirect' => (string) $request->query('redirect', ''),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
public function logoutBridge(Request $request): View
|
public function logoutBridge(Request $request): View
|
||||||
{
|
{
|
||||||
$return = $this->safeReturnUrl((string) $request->query('return', ''));
|
$return = $this->safeReturnUrl((string) $request->query('return', ''));
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App sessions are subordinate to the platform (auth.ladill.com) session.
|
||||||
|
* When the platform session ends, clear this app's local session too.
|
||||||
|
*/
|
||||||
|
class EnsurePlatformSession
|
||||||
|
{
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
if (! Auth::check()) {
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
$authDomain = trim((string) config('app.auth_domain', ''));
|
||||||
|
if ($authDomain === '') {
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cookieHeader = (string) $request->headers->get('Cookie', '');
|
||||||
|
if ($cookieHeader === '') {
|
||||||
|
return $this->clearAppSession($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = Http::withHeaders(['Cookie' => $cookieHeader])
|
||||||
|
->timeout(3)
|
||||||
|
->get('https://'.$authDomain.'/sso/ping');
|
||||||
|
} catch (\Throwable) {
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($response->status() === 401) {
|
||||||
|
return $this->clearAppSession($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function clearAppSession(Request $request): Response
|
||||||
|
{
|
||||||
|
Auth::logout();
|
||||||
|
$request->session()->invalidate();
|
||||||
|
$request->session()->regenerateToken();
|
||||||
|
|
||||||
|
return redirect()->route('sso.connect', [
|
||||||
|
'redirect' => $request->fullUrl(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,9 @@ return Application::configure(basePath: dirname(__DIR__))
|
|||||||
$middleware->web(append: [
|
$middleware->web(append: [
|
||||||
\App\Http\Middleware\SetActingAccount::class,
|
\App\Http\Middleware\SetActingAccount::class,
|
||||||
]);
|
]);
|
||||||
|
$middleware->alias([
|
||||||
|
'platform.session' => \App\Http\Middleware\EnsurePlatformSession::class,
|
||||||
|
]);
|
||||||
})
|
})
|
||||||
->withExceptions(function (Exceptions $exceptions): void {
|
->withExceptions(function (Exceptions $exceptions): void {
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,11 +1,19 @@
|
|||||||
@if (auth()->check())
|
@if (auth()->check())
|
||||||
@php $authPing = 'https://'.config('app.auth_domain').'/sso/ping'; @endphp
|
@php
|
||||||
{{-- Same-site pings keep the shared auth.ladill.com session warm while using this app. --}}
|
$authPing = 'https://'.config('app.auth_domain').'/sso/ping';
|
||||||
<iframe src="{{ $authPing }}" hidden width="0" height="0" title=""></iframe>
|
$platformSignedOutUrl = route('sso.platform-signed-out', ['redirect' => url()->current()]);
|
||||||
|
@endphp
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
const pingUrl = @js($authPing);
|
const pingUrl = @js($authPing);
|
||||||
const ping = () => fetch(pingUrl, { credentials: 'include', mode: 'no-cors' }).catch(() => {});
|
const signedOutUrl = @js($platformSignedOutUrl);
|
||||||
|
const ping = () => fetch(pingUrl, { credentials: 'include' })
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status === 401) {
|
||||||
|
window.location.href = signedOutUrl;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
ping();
|
ping();
|
||||||
setInterval(ping, 5 * 60 * 1000);
|
setInterval(ping, 5 * 60 * 1000);
|
||||||
})();
|
})();
|
||||||
|
|||||||
+2
-1
@@ -25,6 +25,7 @@ Route::get('/sso/callback', [SsoLoginController::class, 'callback'])->name('sso.
|
|||||||
Route::post('/logout', [SsoLoginController::class, 'logout'])->name('logout');
|
Route::post('/logout', [SsoLoginController::class, 'logout'])->name('logout');
|
||||||
Route::get('/sso/logout-bridge', [SsoLoginController::class, 'logoutBridge'])->name('sso.logout-bridge');
|
Route::get('/sso/logout-bridge', [SsoLoginController::class, 'logoutBridge'])->name('sso.logout-bridge');
|
||||||
Route::get('/sso/logout-frontchannel', [SsoLoginController::class, 'frontchannelLogout'])->name('sso.logout-frontchannel');
|
Route::get('/sso/logout-frontchannel', [SsoLoginController::class, 'frontchannelLogout'])->name('sso.logout-frontchannel');
|
||||||
|
Route::get('/sso/platform-signed-out', [SsoLoginController::class, 'platformSignedOut'])->name('sso.platform-signed-out');
|
||||||
Route::get('/signed-out', fn () => auth()->check() ? redirect()->route('transfer.dashboard') : view('transfer.signed-out'))->name('transfer.signed-out');
|
Route::get('/signed-out', fn () => auth()->check() ? redirect()->route('transfer.dashboard') : view('transfer.signed-out'))->name('transfer.signed-out');
|
||||||
|
|
||||||
Route::get('/q/{shortCode}', [QrScanController::class, 'resolve'])->name('qr.public.resolve');
|
Route::get('/q/{shortCode}', [QrScanController::class, 'resolve'])->name('qr.public.resolve');
|
||||||
@@ -34,7 +35,7 @@ Route::get('/q/{shortCode}/transfer', [TransferPublicController::class, 'landing
|
|||||||
Route::post('/q/{shortCode}/transfer/unlock', [TransferPublicController::class, 'unlock'])->name('qr.public.transfer.unlock');
|
Route::post('/q/{shortCode}/transfer/unlock', [TransferPublicController::class, 'unlock'])->name('qr.public.transfer.unlock');
|
||||||
Route::get('/q/{shortCode}/transfer/files/{file}', [TransferPublicController::class, 'download'])->name('qr.public.transfer.download');
|
Route::get('/q/{shortCode}/transfer/files/{file}', [TransferPublicController::class, 'download'])->name('qr.public.transfer.download');
|
||||||
|
|
||||||
Route::middleware(['auth'])->group(function () {
|
Route::middleware(['auth', 'platform.session'])->group(function () {
|
||||||
Route::get('/notifications', [NotificationController::class, 'index'])->name('notifications.index');
|
Route::get('/notifications', [NotificationController::class, 'index'])->name('notifications.index');
|
||||||
Route::get('/notifications/unread', [NotificationController::class, 'unread'])->name('notifications.unread');
|
Route::get('/notifications/unread', [NotificationController::class, 'unread'])->name('notifications.unread');
|
||||||
Route::post('/notifications/{id}/read', [NotificationController::class, 'markAsRead'])->name('notifications.mark-read');
|
Route::post('/notifications/{id}/read', [NotificationController::class, 'markAsRead'])->name('notifications.mark-read');
|
||||||
|
|||||||
Reference in New Issue
Block a user