Wayne Fulcher
Wayne Fulcher

Reputation: 861

How to fix Laravel request/routes/urls - it thinks url is http when it is really https

My server uses SSL and thus all my routes/urls use https. I recently discovered a bug in Laravel 5.7 which was exposed when trying to use Email Verification, which does not work on a server with https. I wont go into the specifics of that problem as I have another question for that. I want to keep this simple. I have the following settings in my .env file:

APP_USE_HTTPS=true
APP_URL=https://www.example.com
APP_ENV=production

And I have the following in the boot() method of the AppServiceProvider

    if (env('APP_USE_HTTPS')) {
        Log::info('AppServiceProvider: forcing URLs to use https');
        URL::forceScheme('https');
    }

And it may be overkill but to try to resolve the issue I also put the following code at the top of my web.php routes file"

if (env('APP_USE_HTTPS')) {
    Log::info('Routes: forcing URLs to use https');
    URL::forceScheme('https');
}

Route::get('/', 'PublicController@getHome');
Route::get('home', 'PublicController@getHome');

Then in my PublicController.getHome() method I put this code:

public function getHome()
{
    $currentPath= Request::fullUrl();
    Log::info($currentPath);

    return view('public.home');
}

Now I go to my browser and enter this in the address bar:

https://www.example.com

And I get this in my log file:

AppServiceProvider: forcing URLs to use https
Routes: forcing URLs to use https
http://www.example.com

So as you can see from the last log message the fact that laravel always uses http instead of https is beginning to create issues. Starting with signed routes. I am trying to use the built-in Email Verification but the signature is being generated using https route and the email sent to user does have https in the url for going back to the same server. However the validation for the route is using http (even though https was used) so it generates a different signature and thus all verifications links fail with a 403 error.

Is there anything I am missing? I can't seem to find code that shows me how Laravel knows to use https or http or is it just hard coded for http?

Thanks for any help you can give me.

*** Update to show problem with Shaielndra Gupta answer ****

After implementing the middleware below is the code I used but as you will see the core problem exists in ALL methods dealing with url. So for example:

$request->secure()

returns false even when https was used. Then by calling:

redirect()->secure($request->getRequestUri());

does no good because that will cause the route to loop back into this method again which still returns false for secure(), basically creating an infinite loop (or infinite too many redirects)

class ForceHttpsProtocol {

public function handle($request, Closure $next) {
    Log::info('request uri: '.$request->fullUrl());
    Log::info('secure: '.($request->secure() ? 'yes' : 'no'));

    if (!$request->secure() && env('APP_USE_HTTPS')) {
        return redirect()->secure($request->getRequestUri());
    }

    return $next($request);
}

}

The log from the above code will produce the following when you make 1 attempt to go to any page even when using https://www.example.com

request uri: http://www.example.com
secure: no
request uri: http://www.example.com
secure: no
request uri: http://www.example.com
secure: no
request uri: http://www.example.com
secure: no

< over and over till page times out >

Upvotes: 3

Views: 7247

Answers (5)

wonder
wonder

Reputation: 31

There is a very useful way: set:

$this->app['request']->server->set('HTTPS','on');

instead of:

URL::forceScheme('https');

only this can slove the page link http to https. when use proxy.

Upvotes: 1

satej sarker
satej sarker

Reputation: 328

if anyone is struggling with apache proxy and $request->server()

you can overwrite Request lib default behaviour by add this line in AppServiceProvider

$this->app['request']->server->set('HTTPS','on')

Upvotes: 1

Wayne Fulcher
Wayne Fulcher

Reputation: 861

After much research I finally discovered what the issue is. My live server is installed on an Amazon EC2 server which is behind a Load Balancer. The load balancer is receiving the (https) request and handling all the SSL requirements and then forwarding the request to my website as http. To fix this issue I had to install the fideloper/TrustedProxy package. This package allows my site to trust the proxy and get the valid headers for the request so it now knows the request was actually sent using https.

Laravel wrote an article which describes my condition exactly. https://laravel-news.com/trusted-proxy

This is the package I installed: https://github.com/fideloper/TrustedProxy

Upvotes: 6

Shailendra Gupta
Shailendra Gupta

Reputation: 1128

change in your config/session.php

'http_only' => true,

change it to

'http_only' => false,

or make a middlewere HttpsProtocol.php

namespace MyApp\Http\Middleware;

use Closure;
use Illuminate\Support\Facades\App;

class HttpsProtocol {

    public function handle($request, Closure $next)
    {
        if (!$request->secure() && App::environment() === 'production') 
        {
             return redirect()->secure($request->getRequestUri());
        }
        return $next($request); 
    }
}

Then, apply this middleware to every request adding setting the rule at Kernel.php file in protected $routeMiddleware array,

'https'=>App\Http\Middleware\HttpsProtocol::class

Upvotes: -1

FULL STACK DEV
FULL STACK DEV

Reputation: 15961

change This

APP_USE_HTTPS=true
APP_URL=https://www.example.com

to this

APP_URL=http://www.example.com
APP_USE_HTTPS=false

Because Laravel uses APP_URL to generate urls.

Upvotes: -1

Related Questions