From 7f52c9cd8e0f728be25f3320dfbb0e6e8ea6c880 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Thu, 23 Apr 2026 16:15:51 -0400 Subject: [PATCH] Fix elevated session redirect for POST endpoints Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ElevatedSessionAuthorizationException.php | 18 +++++- tests/Auth/ElevatedSessionTest.php | 56 +++++++++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/Exceptions/ElevatedSessionAuthorizationException.php b/src/Exceptions/ElevatedSessionAuthorizationException.php index 1ff335b631..4cf4f13100 100644 --- a/src/Exceptions/ElevatedSessionAuthorizationException.php +++ b/src/Exceptions/ElevatedSessionAuthorizationException.php @@ -3,6 +3,7 @@ namespace Statamic\Exceptions; use Illuminate\Http\Request; +use Statamic\Facades\URL; use Statamic\Statamic; class ElevatedSessionAuthorizationException extends \Exception @@ -22,6 +23,21 @@ public function render(Request $request) ? cp_route('confirm-password') : route('statamic.elevated-session'); - return redirect()->setIntendedUrl($request->fullUrl())->to($redirectUrl); + $intendedUrl = $request->isMethod('GET') + ? $request->fullUrl() + : $this->refererForIntendedUrl($request); + + return redirect()->setIntendedUrl($intendedUrl)->to($redirectUrl); + } + + private function refererForIntendedUrl(Request $request) + { + $referer = $request->headers->get('referer'); + + if ($referer && ! URL::isExternalToApplication($referer)) { + return $referer; + } + + return $request->fullUrl(); } } diff --git a/tests/Auth/ElevatedSessionTest.php b/tests/Auth/ElevatedSessionTest.php index 811911199a..32b1324e9b 100644 --- a/tests/Auth/ElevatedSessionTest.php +++ b/tests/Auth/ElevatedSessionTest.php @@ -45,9 +45,17 @@ protected function resolveApplicationConfiguration($app) return 'ok'; })->middleware(Middleware\RequireElevatedSession::class); + Route::post('/requires-elevated-session', function () { + return 'ok'; + })->middleware(Middleware\RequireElevatedSession::class); + Route::get('/cp/requires-elevated-session', function () { return 'ok'; })->middleware(Middleware\CP\RequireElevatedSession::class); + + Route::post('/cp/requires-elevated-session', function () { + return 'ok'; + })->middleware(Middleware\CP\RequireElevatedSession::class); }); } @@ -309,6 +317,54 @@ public function middleware_denies_request_when_elevated_session_has_expired() ->assertRedirect('/cp/auth/confirm-password'); } + #[Test] + public function middleware_uses_referer_as_intended_url_for_post_requests() + { + $this->actingAs($this->user); + + $this + ->withElevatedSession(now()->subMinutes(16)) + ->post('/cp/requires-elevated-session', [], ['referer' => 'http://localhost/cp/some-form']) + ->assertRedirect('/cp/auth/confirm-password') + ->assertSessionHas('url.intended', 'http://localhost/cp/some-form'); + } + + #[Test] + public function middleware_falls_back_to_full_url_when_referer_is_external_for_post_requests() + { + $this->actingAs($this->user); + + $this + ->withElevatedSession(now()->subMinutes(16)) + ->post('/cp/requires-elevated-session', [], ['referer' => 'https://evil.example.com/form']) + ->assertRedirect('/cp/auth/confirm-password') + ->assertSessionHas('url.intended', 'http://localhost/cp/requires-elevated-session'); + } + + #[Test] + public function middleware_falls_back_to_full_url_when_referer_is_missing_for_post_requests() + { + $this->actingAs($this->user); + + $this + ->withElevatedSession(now()->subMinutes(16)) + ->post('/cp/requires-elevated-session') + ->assertRedirect('/cp/auth/confirm-password') + ->assertSessionHas('url.intended', 'http://localhost/cp/requires-elevated-session'); + } + + #[Test] + public function middleware_uses_full_url_as_intended_url_for_get_requests() + { + $this->actingAs($this->user); + + $this + ->withElevatedSession(now()->subMinutes(16)) + ->get('/cp/requires-elevated-session', ['referer' => 'http://localhost/cp/some-form']) + ->assertRedirect('/cp/auth/confirm-password') + ->assertSessionHas('url.intended', 'http://localhost/cp/requires-elevated-session'); + } + #[Test] public function middleware_denies_request_when_elevated_session_has_expired_via_json() {