2

I've setup two routes

Route::get('/bugreport', 'SomeController@create')
    ->middleware('signed')
    ->name('bugreport');

Route::get('/getlink', function() {
    return dd(\URL::signedRoute('bugreport', ['data' => 3]));
});

When APP_ENV=local I can visit /getlink then hit the resulting url and have it show. When APP_ENV=production (the actual physical environment has not changed when changing the variable) this no longer works... stating invalid signature. Any suggestions?

UPDATE:

We do have... which might be part of it

class AppServiceProvider extends ServiceProvider
{
/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    if (!config('app.is_local')) {
        URL::forceScheme('https');
    }
}

Note: removing the above code actually does fix this issue, but then it breaks e.g. login... so either need to understand why, or this isn't an option :(.

Update Update:

The environment is heroku and the .htaccess has (as per https://help.heroku.com/J2R1S4T8/can-heroku-force-an-application-to-use-ssl-tls)

#### FORCE SSL
## see - https://help.heroku.com/J2R1S4T8/can-heroku-force-an-application-to-use-ssl-tls
RewriteCond %{HTTP_HOST} !=localhost
# If we receive a forwarded http request from a proxy...
RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR]

# ...or just a plain old http request directly from the client
RewriteCond %{HTTP:X-Forwarded-Proto} =""
RewriteCond %{HTTPS} !=on

# Redirect to https version
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
### End Force SSL
Dan
  • 2,830
  • 19
  • 37
  • Have you cleared the cache and config using `php artisan config:cache`? – Hiren Gohel Oct 18 '18 at 04:38
  • Try commenting out the code in `AppServiceProvider::boot()` function. I think absence of SSL certificate in the dev environment is the issue. – linuxartisan Oct 18 '18 at 04:52
  • @HirenGohel yes, and also heroku rebuilds it all each deploy anyway, so we can rule that out :(. – Dan Oct 18 '18 at 21:20
  • @linuxartisan this is in production. So if I change the APP_ENV param to local in production it works. Removing the `::boot()` in our setup completely breaks login... which I don't really understand. – Dan Oct 18 '18 at 21:22
  • Of course you can't remove `boot()`. But commenting out the code for forcing https solves the issue (I hope). Also, changing the APP_ENV to local works for you. Which means there's a problem with the `URL::forceScheme('https');` statement. The code seems correct. So I guess your SSL is not configured properly. That's why you must be getting Invalid Signature error. – linuxartisan Oct 21 '18 at 03:58
  • Thanks for taking a look. I did mean only removing the contents of the `::boot()` method. The solution I posted below explains why ::forceScheme appeared to be breaking it (it was impossible to hit the app with https as far as laravel is concerned with heroku setup). – Dan Oct 21 '18 at 22:14

2 Answers2

8

I had a similar problem - it can be solved very easy if you use the TrustedProxy Middleware.

If you are on Heroku or AWS behind Load Balancers, and you have SSL offloaded to load balancers, you might want to Trust all proxies, so that Laravel's Request can detect that you are actually on a SSL connection. Then Signed URL Validation will work.

You can see the doku here:
Laravel 5.7 https://laravel.com/docs/5.7/requests#configuring-trusted-proxies
Laravel 5.6 https://laravel.com/docs/5.6/requests#configuring-trusted-proxies

naabster
  • 1,494
  • 12
  • 14
0

Update: Use the accepted answer instead.

I finally isolated this down to the Heroku changing the protocol on the requests, so that even when the client makes a request in https laravel will always receive it as http in the request object. The workaround was

    if (!config('app.is_local') && strpos($request->url(), 'http:') !== false) 
    {
        $url = str_replace('http:', 'https:', $request->fullUrl());
        $request = Request::create($url);
    }

    if (!$request->hasValidSignature()) {
        return abort(403);
    }

This was sufficient for my needs.

Dan
  • 2,830
  • 19
  • 37