#Signed URL returns invalid signature exception when used with Nginx

1 messages · Page 1 of 1 (latest)

dusty ruin
#

I've deployed my Laravel application to a Ubuntu VPS with Nginx. but unfortunately, signed URLs returns invalid signature exception.

Here is the Nginx configuration.

server {
    listen 80;
    listen [::]:80;
    server_name dasun.dev;
    root /var/www/html/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

server {
    server_name dasun.dev;
    return 301 $scheme://www.dasun.dev$request_uri;
}

I was wondering if anyone could help resolve this.

urban shard
#

You have two instances running for
server_name dasun.dev;
And you're redirecting to www.dasun.dev

What precisely are th e issues you're experiencing?

dusty ruin
#

Hey Joe,

The second sever block for redirect non-www traffic to www.

So, simply when I visited to the signed url, I am getting the 403 error page.

urban shard
#

Okay, so what's a normal URL, and a signed one

If you edit the file:
app/Http/Middleware/TrustProxies.php
and set

protected $proxies = "*";

And ensure it's enabled in
(app/Http/Kernel.php to enable it in $middleware)

Does that fix the 403?

#

Are you passing parameters into your signed URL (e.g. page_number/order_by)

dusty ruin
#

I also tried with by wildcarding proxies, but i think there is no issue with proxies, since I am not behind a load balancer or reverse proxy.

urban shard
#

Can you provide an example signed URL that isn't working?

urban shard
#

As your Nginx is an HTTP, and you're sharing an HTTPS link, this can often cause a signature mismatch

dusty ruin
#

Make sense.

#

How did you know the Nginx is HTTP?

urban shard
#
server {
    listen 80;
    listen [::]:80;
#

So it's only listening on HTTP

#

You've got CloudFlare in front of it, so you do have a CDN/Load Balancer

#

In CloudFlare:
Generate an Origin Certificate key-pair
Add them to your server, and reference in your nginx config, and set your server to listen as 443 ssl, rather than 80

#

Then use CloudFlare to perform the http to https redirect for everything

dusty ruin
#

okay, let me try this.

urban shard
#

Finally check your APP_URL in your .env file and ensure it has the https prefix (rather than http)

dusty ruin
#

APP_URL has https prefix, confirmed.

urban shard
#

Once all of that is done, then it's likely to either be either:

  1. Additional parameters present in the URL
  2. TimeZone issues on the server (where the config app.timezone isn't set)

With your Route::get()
What does your validation/middleware look like?

#

Are you using hasValidSignature()?

dusty ruin
#

Yes

#

i'm using the default middleware

urban shard
#

Try changing it to:

hasValidSignatureWhileIgnoring(['email'])

dusty ruin
#

But, the email is required to create the newsletter subscriber

urban shard
#

Yep, it just ignores the email for signature purposes

dusty ruin
#

Is there any way to decode the signature and see the payload?

urban shard
#

Can you share the route where you're validating it plz

dusty ruin
#
Route::get('/newsletter/unsubscribe', [NewsletterController::class, 'unsubscribe'])->name('newsletter.unsubscribe');
urban shard
#

Okay, and the code where you're validating the signature

dusty ruin
#
class NewsletterController extends Controller
{
    public function confirmSubscription(Request $request)
    {
        if (! $request->hasValidSignature()) {
            throw new InvalidSignatureException;
        }

        $newsletterSubscriberRepository = app(NewsletterSubscriberRepository::class);

        $newsletterSubscriberRepository->verifyEmail(
            email: $request->email
        );

        return view('newsletter.subscription-confirmed');
    }
}
urban shard
#

In NewsletterController, what references do you have to Request in the namespace

dusty ruin
#
use Illuminate\Http\Request;
urban shard
#

have you added

use Illuminate\Http\Request;

Or is it using the Request facade?

#

Cool

dusty ruin
#

This is working on my local.

urban shard
#

It's likely the redirects/http vs https from CloudFlare tbh

dusty ruin
#

And also, this was works with the production environment before. but I was using Octane.

#

So, now I use php-fpm

urban shard
#

Just tested in a dev environment, and it's definitely working

#

With an Nginx/PHP-FPM environment

#

behind cloudflaer

#

cloudflare*

dusty ruin
#

because, octane reserved 200mb - 300mb when running the application.

#

I am trying to setup Cloudflare certs.

#

seems, I am missing something.

#
ERR_TOO_MANY_REDIRECTS
urban shard
#

Remove that second server in your nginx config

#

What does your nginx config look like for that site now

dusty ruin
#

I did, and I am suprised.

#

Once, removed the 2nd Nginx block, another Laravel app got running which an open source project that I'm working

#

🤣

urban shard
#

What does your first block look like now

#

If you're hitting another app, then you're not hitting that site/server definition, so it's reverting to the default/closest match

dusty ruin
#

oh yeah, got it.

#

here is the niginx conf.

server {
    #listen 80;
    #listen [::]:80;
    listen 443;
    ssl on;
    ssl_certificate       /etc/ssl/dasun.dev.pem;
    ssl_certificate_key   /etc/ssl/dasun.dev.key;

    server_name dasun.dev;
    root /home/laravel/dasun.dev/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
urban shard
#

Okay, and you've reloaded/restarted nginx?

dusty ruin
#

Yeah

urban shard
#
server {
    listen  443 ssl;
    ssl_certificate       /etc/ssl/dasun.dev.pem;
    ssl_certificate_key   /etc/ssl/dasun.dev.key;

    server_name dasun.dev www.dasun.dev;
    root /home/laravel/dasun.dev/public;

    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";

    index index.php;

    charset utf-8;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    error_page 404 /index.php;

    location ~ \.php$ {
        proxy_set_header REMOTE_ADDR $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}
dusty ruin
#

let me try.

urban shard
#

Do you have any other redirects enabled in Cloudflare?
Any packages/.htaccess etc to try and redirect http to https?
Do you see any requests hitting other sites?

find /etc/nginx/sites-enabled/* |  xargs grep 'server_name dasun.dev'

Just get the one result?

#

Likewise for:

find /etc/nginx/sites-enabled/* |  xargs grep 'server_name www.dasun.dev'
#

Also, can you share the route for "newsletter/confirm-subscription", which you shared earlier when you get a mo, as you shared the "unsubscribe" route

dusty ruin
#

just a moment.

urban shard
#

At a glance, it looks like you're looping around the params at the mo, so there's some looping going on somewhere, most likely within your nginx environment, or Cloudflare

Swapping out "fastcgi_param SCRIPT_FILENAME...." with

        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;

MAY work more smoothly btw (mixed opinions online)

dusty ruin
#

Hey, it works without the 2nd server block.

urban shard
#

Woo

#

Let CloudFlare handle any redirecting from HTTP to HTTPS, non-www to www etc

dusty ruin
#

yeah, even keeping the same first server block

urban shard
#

Nice!

dusty ruin
#

yeah, I am deleting ssl certs from server. no need anymore

urban shard
#

Always worth doing

#

End to End SSL is always best, but if it's something you're not too fussed about, then that's fine too

#

Having everything consistent prevents issues down the line too

dusty ruin
#

one more thing, I still wanted to be redirected to non-www to www.

#

now everything is working except this.

#

anyways, marking this thread as solved.