Skip to content

Commit e44ce69

Browse files
authored
[AIDAPP-949]: Magiclink login gets invalidated by emails scanners like Outlook protection (#889)
Enhance MagicLinkLoginController to handle HEAD requests, preventing link scanning bots
1 parent 620f4fb commit e44ce69

File tree

2 files changed

+39
-1
lines changed

2 files changed

+39
-1
lines changed

app-modules/authorization/src/Http/Controllers/MagicLinkLoginController.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
use Filament\Facades\Filament;
4242
use Illuminate\Http\RedirectResponse;
4343
use Illuminate\Http\Request;
44+
use Illuminate\Http\Response;
4445
use Illuminate\Support\Facades\Auth;
4546
use Illuminate\Support\Facades\Crypt;
4647
use Illuminate\Support\Facades\Hash;
@@ -51,8 +52,13 @@ class MagicLinkLoginController
5152
/**
5253
* @throws Throwable
5354
*/
54-
public function __invoke(Request $request, LoginMagicLink $magicLink): RedirectResponse
55+
public function __invoke(Request $request, LoginMagicLink $magicLink): RedirectResponse|Response
5556
{
57+
if ($request->getMethod() === 'HEAD') {
58+
// Protection against link scanning bots, like Microsoft Outlook.
59+
return response()->noContent();
60+
}
61+
5662
abort_if(
5763
boolean: now()->greaterThanOrEqualTo($magicLink->created_at->addMinutes(15))
5864
|| $magicLink->used_at !== null,

app-modules/authorization/tests/Tenant/Feature/Http/Controllers/MagicLinkLoginControllerTest.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
use function Pest\Laravel\assertAuthenticatedAs;
4545
use function Pest\Laravel\assertGuest;
4646
use function Pest\Laravel\get;
47+
use function Pest\Laravel\head;
4748

4849
it('requires a valid signed URL ', function () {
4950
$code = Str::random();
@@ -204,3 +205,34 @@
204205

205206
expect($magicLink->used_at)->not->toBeNull();
206207
});
208+
209+
it('returns no content for HEAD requests to protect against link scanning bots', function () {
210+
$code = Str::random();
211+
212+
$magicLink = LoginMagicLink::factory()->withCode($code)->create();
213+
214+
$url = URL::temporarySignedRoute(
215+
name: 'magic-link.login',
216+
expiration: now()->addMinutes(10)->toImmutable(),
217+
parameters: [
218+
'magicLink' => $magicLink->getKey(),
219+
'payload' => urlencode(
220+
Crypt::encrypt(
221+
[
222+
'code' => $code,
223+
'user_id' => $magicLink->user_id,
224+
]
225+
)
226+
),
227+
],
228+
);
229+
230+
head($url)
231+
->assertNoContent();
232+
233+
$magicLink->refresh();
234+
235+
expect($magicLink->used_at)->toBeNull();
236+
237+
assertGuest(Filament::getPanel('admin')->getAuthGuard());
238+
});

0 commit comments

Comments
 (0)