While forcing HTTPS at the web server level (Apache/Nginx) is generally the more reliable and efficient approach, Laravel offers its own application-level solutions — useful on shared hosting without direct server config access, and for making sure Laravel's own generated URLs are correctly HTTPS.
Forcing HTTPS via middleware
// app/Http/Middleware/ForceHttps.php
class ForceHttps
{
public function handle(Request $request, Closure $next)
{
if (! $request->secure() && app()->environment('production')) {
return redirect()->secure($request->getRequestUri());
}
return $next($request);
}
}
// bootstrap/app.php (Laravel 11+) or Kernel.php (earlier versions)
$middleware->append(ForceHttps::class);
Checking app()->environment('production') before redirecting is deliberate — it avoids forcing HTTPS during local development, where the dev server typically doesn't have a valid SSL certificate configured at all.
Forcing Laravel's generated URLs to use HTTPS, without redirecting
// AppServiceProvider boot() method
public function boot(): void
{
if ($this->app->environment('production')) {
URL::forceScheme('https');
}
}
This is a distinct concern from actually redirecting requests — forceScheme('https') only affects how Laravel generates URLs internally (via route(), url(), asset helpers), which matters specifically when the app sits behind a load balancer or proxy that terminates SSL before the request reaches Laravel, making $request->secure() unreliable on its own.
Trusting proxies for accurate scheme detection
// bootstrap/app.php
$middleware->trustProxies(at: '*');
Behind a load balancer, AWS ELB, or similar reverse proxy, Laravel needs to trust the X-Forwarded-Proto header to correctly determine whether the original request was HTTPS — without this, $request->secure() can incorrectly report false even though the original client connection was genuinely secure.
Redirecting via .htaccess instead (Apache)
# public/.htaccess
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Redirecting via Nginx server block instead
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
Handling the redirect at the web server level (Apache or Nginx, as shown) is generally preferable to Laravel middleware — it's more efficient (rejecting or redirecting the request before it even reaches PHP) and works correctly even for non-Laravel-routed requests like static assets.
Setting the HSTS header, to prevent even the first insecure request
header('Strict-Transport-Security: max-age=31536000; includeSubDomains');
HSTS (HTTP Strict Transport Security) tells a browser that has visited the site before to always use HTTPS automatically, without even attempting an insecure HTTP request first — this closes a small window that a plain server-side redirect alone doesn't cover, where a single initial HTTP request could theoretically be intercepted before the redirect happens.