# Forcing HTTPS URLs in Laravel with `URL::forceScheme('https')`

> Author: [Oussama Ghaieb](https://oussama.ghaieb.com/about-me)
> Canonical: https://oussama.ghaieb.com/posts/forcing-https-urls-in-laravel

# <span class="hover:bg-yellow-100">Forcing HTTPS URLs in Laravel with `URL::forceScheme('https')`</span>

In modern web applications, it's essential to ensure that all user traffic is served over a secure HTTPS connection. Not only does HTTPS protect user data, but it also enhances your site's credibility and SEO rankings. In Laravel, generating URLs with the correct scheme (HTTP or HTTPS) can sometimes be tricky, especially when your application is behind a reverse proxy or load balancer.

One powerful tool that Laravel offers to force HTTPS in your application is the `URL::forceScheme('https')` method. In this article, we'll explore how this method works, when to use it, and how to set it up correctly.

## What Is `URL::forceScheme('https')`?

Laravel's `URL::forceScheme('https')` method forces all URLs generated by Laravel's URL and route helpers (like `route()`, `url()`, and `asset()`) to use the HTTPS scheme, regardless of the current request's protocol.

This is particularly useful when your application is deployed behind a reverse proxy, such as Nginx or a load balancer, which terminates the HTTPS connection but the application itself doesn't detect the incoming request as secure (i.e., it may still consider it to be HTTP).

By calling `URL::forceScheme('https')`, you can ensure that all URLs generated by Laravel will be `https://`, even if the request itself came over HTTP.

## When Should You Use `URL::forceScheme('https')`?

### 1. **When Your Application is Behind a Proxy**
If your application is behind a proxy or load balancer that terminates the HTTPS connection and forwards the request to your application over HTTP, Laravel won't automatically detect the request as HTTPS. 

This is a common situation in production environments, where a reverse proxy (like Nginx or AWS Elastic Load Balancer) handles HTTPS termination but passes the request to Laravel over HTTP.

### 2. **Forcing HTTPS for All Routes**
If you want to ensure that all URLs generated within your application (including assets, routes, and links) are always served over HTTPS, `URL::forceScheme('https')` is a simple and effective solution.

This is especially important for applications that handle sensitive data (like user login, payments, or personal information) and need to enforce secure communication across the entire site.

### 3. **To Prevent Mixed Content Issues**
When a page is served over HTTPS but some of its resources (like images, scripts, or stylesheets) are loaded over HTTP, browsers will block these resources to protect users from potential security risks. By forcing the HTTPS scheme for all URLs, you can avoid these mixed content issues and ensure that all resources are loaded securely.

## How to Use `URL::forceScheme('https')`

### Step 1: Open `AppServiceProvider`

The best place to call `URL::forceScheme('https')` is within the `AppServiceProvider`. This allows you to globally enforce the HTTPS scheme throughout your entire Laravel application.

1. Open the `AppServiceProvider.php` file located in `app/Providers/AppServiceProvider.php`.
2. Inside the `boot()` method, add the following line of code:

```php
use Illuminate\Support\Facades\URL;

public function boot()
{
    // Force HTTPS scheme in production
    if ($this->app->environment('production')) {
        URL::forceScheme('https');
    }
}
```

### Step 2: Handle Different Environments

You may want to enforce HTTPS only in production to avoid issues in local or development environments. The above example ensures that `URL::forceScheme('https')` is only applied when the application is running in a production environment.

In local environments, URLs may still be generated with the HTTP scheme, allowing you to test the application without requiring HTTPS.

### Step 3: Clear Configuration Cache

Whenever you make changes to the `AppServiceProvider` or other configuration files, it’s a good practice to clear the configuration cache:

```bash
php artisan config:cache
```

This ensures that your changes take effect immediately.

## Troubleshooting Common Issues

### 1. **URLs Still Generated with HTTP**

If you notice that URLs are still being generated with HTTP after using `URL::forceScheme('https')`, check the following:

- **Ensure Your `APP_URL` Is Correct**: In your `.env` file, make sure the `APP_URL` is set to `https`:

  ```env
  APP_URL=https://yourdomain.com
  ```

- **Verify Your Web Server Configuration**: If you're behind a reverse proxy (like Nginx or Apache), ensure that the proxy forwards the correct headers, such as `X-Forwarded-Proto`, which indicates the original scheme of the request.

### 2. **Laravel Behind a Proxy**

If your application is behind a reverse proxy or load balancer, you may need to configure Laravel to trust these proxies. Open the `App\Http\Middleware\TrustProxies` middleware and set the `$proxies` property to the correct value:

```php
protected $proxies = '*'; // Trust all proxies, or set a specific IP or range
```

Also, ensure the `$headers` property is set correctly:

```php
protected $headers = Request::HEADER_X_FORWARDED_ALL;
```

### 3. **Mixed Content Warnings**

After enforcing HTTPS, ensure all assets (CSS, JS, images) are being loaded over HTTPS. If any resources are still being loaded via HTTP, browsers will display mixed content warnings. Always use the `asset()` helper or URLs with the correct scheme:

```php
<img src="https://oussama.ghaieb.com/images/logo.png" alt="Logo">
```

## Conclusion

Enforcing HTTPS is a crucial step in securing your Laravel application. By using `URL::forceScheme('https')`, you can ensure that all URLs generated by your application use the HTTPS scheme, preventing mixed content issues and safeguarding user data. This simple but powerful method is a must-have for any Laravel application deployed in a production environment, especially when it's behind a reverse proxy.

If you're running Laravel in production and want to force HTTPS across your application, make sure to call `URL::forceScheme('https')` in the `AppServiceProvider` and configure your server and proxy to pass the correct headers. By doing so, you can protect your users and ensure a seamless, secure experience on your site.
