How to force HTTPS in a Laravel project?
Published 23 November 2019 15:36 (4-minute read)
Sometimes people don't link to the secure (https) version of your site, this can be an old link or the user who placed the link is just lazy to add the extra character.
There are a few ways to redirect you HTTP website to a HTTPS connection. In this article I've described the method for using a Middleware.
In this post I explain how you can force HTTPS with the following methodes:
- Laravel Middleware
- nginx (preferred)
- .htaccess
- Cloudflare
- Laravel Forge
The solutions mentioned below work from Laravel 5 till the latest available.
Force HTTPS with a Middleware
"Middleware provide a convenient mechanism for filtering HTTP requests entering your application." (source laravel.com/docs/8.x/middleware)
To force redirect a http url to https I use in some cases a middleware to handle the redirect. This is just a simple solution and don't require a change to the server or nginx configuration.
You can make the middleware by running "php artisan make:middleware HttpsProtocolMiddleware" and it will generate a file like below (or just copy and paste this file in app/Http/Middleware/HttpsProtocolMiddleware.php). This will check if the request is secure, if it is not secure, it will redirect the user to the secure/https URL.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\App;
class HttpsProtocolMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (!$request->secure() && app()->environment('production')) {
return redirect()->secure($request->getRequestUri());
}
return $next($request);
}
}
In your HTTP Kernel (app/Http/Kernel.php) you can place the created middleware in the web group, which is applied to every request to your Laravel application.
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\HttpsProtocolMiddleware::class
],
'api' => [
'throttle:60,1',
'bindings',
],
];
But why don't you just use \Illuminate\Support\Facades\URL::forceScheme('https'); ? It's a simple answer, this method don't redirect the user to the secure version of your site, so the user still access the unsecure/http version, it just force Laravel to generate secure/https links.
Please be aware, when you use a middleware for redirecting your HTTP to HTTPS, it will only work for your Laravel-routes. So any files that are not served via Laravel (for example, `/js/app.js`) will NOT be redirected to HTTPS because this is a static asset that is handled by your webserver (apache or nginx) before it hits your Laravel application.
Force HTTPS with Laravel Forge
Laravel Forge automatically redirects HTTP to HTTPS when you activate the SSL certificate. This is done by nginx that handles the certificate on your server, this also includes the traffic that's not being served by your Laravel application (for example static files, like /js/app.js or /css/app.css).
Force HTTPS with nginx
To force your HTTP website to be redirected to HTTPS, you can force it by changing your nginx configuration.
In the following example, I've used example.com (and the www.example.com alias) as the domain to redirect to HTTPS using nginx.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://example.com$request_uri;
}
What this does is listening on port 80 (HTTP traffic) and redirect all traffic to example.cm & www.example.com to the new HTTPS-URL, example.com/*.
Based on the $request_uri parameter, nginx will redirect the user to its original URL but then the HTTPS version.
Force HTTPS with .htaccess
Via a .htaccess file it's possible to redirect all your HTTP requests to HTTPS. It's just a few lines of code, that will check if the request is not HTTPS, if so, it will be redirected to the HTTPS version of your application.
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Force HTTPS with Cloudflare
When you have Cloudflare in front of your site, then you can enable the "redirect all traffic to HTTPS" feature within Cloudflare's dashboard. This redirects all your Laravel endpoints and static files for that (sub)domain to a secure HTTPS connection. This is done before the request actually hits your server, therefor you need to have the Cloudflare Proxy (the orange cloud next to the DNS record) feature enabled.
To force all traffic to HTTPS, enable the "Always use HTTPS" feature within the Edge Certificates tab of the Cloudflare SSL/TLS app or via the Page Rules app.
More information can be found on Cloudflare support website where they wrote an article for SSL related questions.