1

When a user clicks on the link in my mail it will be forwarded to the signed url I created. The controller method looks like this:

public function show(Request $request)
{
    //Remove default sendinblue query parameters
    foreach (array_keys($request->all()) as $key) {
        if (! in_array($key, ['expires', 'signature'])) {
            $request->server->remove($key);
        }
    }

    if (! $request->hasValidSignature()) {
        return redirect()->to('https://snuffelbox.nl');
    }

    //Passes
}

The problem is that my mail provider is always adding query parameters like utm_source etc, making the request invalid. So that's why I'm stripping all query parameters except for expires and signature.

In the ->hasValidSignature() method Laravel is using this for getting the url:

$request->server->get('QUERY_STRING')

But no matter what I try I can't strip the query parameters from the url.

This is not working:

$request->server->remove($key);

And neither is this:

$request->request->remove($key);

Any idea how I can fix this problem?

--EDIT--

Url from mail:

https://link.com/2/SlqC4BRd?signature=00be549770a7c5aa5624c5941ce9dc7eaf583d27aa1ebb61a0dbcb96f0f80191&utm_source=mail

What it should become (then it's valid, already tested that):

https://link.com/2/SlqC4BRd?signature=00be549770a7c5aa5624c5941ce9dc7eaf583d27aa1ebb61a0dbcb96f0f80191

Signed route is created like this:

$link = URL::signedRoute('inertia.upsell.show', [$group->id, $order->token]);
Jamie
  • 10,302
  • 32
  • 103
  • 186
  • Could you add an example url with the corresponding route? – MaartenDev Aug 29 '21 at 11:24
  • Could you try using `$request->query->remove('utm_source');` instead of `$request->server->remove($key);`? – MaartenDev Aug 29 '21 at 11:35
  • @MaartenDev not working unfortunately. – Jamie Aug 29 '21 at 11:37
  • Could you add some debug points in `UrlGenerator.php` where the url is validated? You can checkout this answer for tips: https://stackoverflow.com/a/54034735/6310593 – MaartenDev Aug 29 '21 at 11:40
  • I don't think the additional query params would make the url invalid. What Laravel try to validate should only be the `signature` param. Have you verified if this is the case? – Kenny Horna Aug 29 '21 at 12:02
  • If nothing is working you can try this dumb idea of getting the URL and then redirecting again with only the ``expires `` parameter. – OMi Shah Aug 29 '21 at 12:03
  • can you try this ``if (! $request->hasValidSignature(false) )`` ? – OMi Shah Aug 29 '21 at 12:08
  • If I remove all query parameters except `signature` it's working, so additional query params are not allowed. Also laravel checks if there are other query parameters https://github.com/laravel/framework/blob/a69d9d61f488b2d58ffb72410c5863b271d67086/src/Illuminate/Routing/UrlGenerator.php#L408 – Jamie Aug 29 '21 at 12:11
  • @OMIShah not working. – Jamie Aug 29 '21 at 12:11
  • I guess laravel uses `$request->server->get('QUERY_STRING')` for validation. So Try editing the parameter like: `$customQueryString = http_build_query($request->only(['param1', 'param2' ..])); $request->server->set('QUERY_STRING', $customQueryString);` – iamab.in Aug 29 '21 at 12:22
  • @iamab.in thanks! That's working! – Jamie Aug 29 '21 at 12:32

1 Answers1

1

In Laravel 9.x, you can use hasValidSignatureWhileIgnoring method to ignore specific parameters:

if (! $request->hasValidSignatureWhileIgnoring(['utm_source', 'other_params'])) {
    abort(401);
}
apzeero
  • 43
  • 1
  • 5
  • Please provide an explanation to your code - it is very hard to understand something when it isn't explained. – ethry Jul 02 '22 at 21:19