TL;DR: Laravel makes your applications more secure by default, which makes it the recommended PHP framework for mission-critical applications. In this article, we will briefly address how Laravel can help you create mission-critical, production-ready applications.

Introduction

For a mission-critical application, there are two levels of security that matters: application security and server security. Laravel is a development framework and, as such, it won't make your server more secure, just your application.

Laravel features allow you to use everything securely. All the data is sanitized where needed unless you're using Laravel with raw queries. Then, you're on your own basically. The point is, Laravel gives you security for common vulnerabilities.

So, in this article, you will learn about the most important security features of Laravel.

"Learn why Laravel is the best PHP framework for mission-critical, production-ready applications."

Protecting Laravel Applications from SQL Injection

Laravel protects you from SQL injection as long as you're using the Fluent Query Builder or Eloquent.

Laravel does this by making prepared statements which are going to escape any user input that may come in through your forms. If hackers add a new input to a form, they may try to insert a quote and then run their own custom SQL query to damage or read your application database. However, this won't work since you are using Eloquent. Eloquent is going to escape this SQL command and the invalid query will just be saved as text into the database.

The take away is: if you're using the Fluent Query Builder or Eloquent, your application is safe from SQL injections.

To learn more about SQL injection protection on Laravel check out this article.

Protecting Cookies on Laravel Applications

Laravel will also protect your cookies. For that, you will need to generate a new Application Key. If it’s a new project, use the PHP artisan key:generate command.

For existing projects running on Laravel 3, you will need to switch to a text editor, then go to your application's config directory and open the application.php file. There, you will find the key under the Application Key section.

On Laravel 5 and above, Application Key is called Encryption Key. You can find this key in the app.php file that resides in the config folder.

The Application Key or Encryption Key uses encryption and cookie classes to generate secure encrypted strings and hashes. It is extremely important that this key remains secret and should not be shared with anyone. Also, make it about 32 characters of random gibberish so that nobody can guess it as Laravel uses this key to validate the cookie.

As mentioned above, Laravel auto-generates the Application Key; however, if required, you can edit it from the application.php file.

The cookie class uses the Application key to generate secure encrypted strings and hashes. Laravel will protect your cookies by using a hash and making sure that no one tampers with them.

Cross-Site Request Forgery (CSRF) Protection on Laravel

To protect your application from a CSRF attack, Laravel uses the Form Classes Token method, which creates a unique token in a form. So, if you look at the source code of a target form, you will see a hidden form field called CSRF token.

<form name="test">
{!! csrf_field() !!}
<!-- Other inputs can come here-->
</form>

The token makes sure that the request is coming from your application and not from somewhere else. With that token, you need to make sure that it's checking for a forged request. Laravel has CSRF-protection enabled by default.

Laravel adds a pre-defined CSRF filter in your app that looks like this:

<?php
Route::filter('csrf', function() {
   if (Session::token() != Input::get('_token')) {
       throw new Illuminate\Session\TokenMismatchException;
   }
});

The CSRF filter allows you to check for a forged request and if it has been forged, it's going to return an HTTP 500 error. You can use the Form Classes Token method and CSRF filter together to protect your application routes.

Mass Assignment Vulnerabilities on Laravel

Object-relational mapping tools (like Eloquent) have the ability to mass-assign properties directly into the database, which is a security vulnerability.

For those who don’t know, Laravel’s ORM (Eloquent) offer a simple Active-Record implementation for working with your database. Each database table has a corresponding Model_Class that interacts with that table.

Mass assignment let you set a bunch of fields on the model in a single go, rather than sequentially, something like:

$user = new User(Input::all());

The command above sets all value at the same time, in one go.

For example, your application can have a user table and with a user_type field. This field can have values of: user or admin.

In this case, you don’t want your users to update this field manually. However, the above code could allow someone to inject a new user_type field. After that, they can switch their account to admin.

By adding to the code:

$fillable = array('name', 'password', 'email');

You make sure only the above values are updatable with mass assignment.

To be able to update the user_type value, you need to explicitly set it on the model and save it, as shown here:

$user->user_type = 'admin';
$user->save();

Cross-Site Scripting Protection on Laravel

Laravel's @{{}} syntax will escape any HTML objects that are the part of a view variable. It’s a big-deal, considering that a malevolent user can authorize the subsequent string into a comment or user profile:

My list <script>alert("spam spam spam!")</script>

Avoiding cross-site scripting attacks on Laravel applications.

Without cross-site scripting protection, a view variable like the one above would be presented in a web page in the form of an annoying alert window, causing this form of attack called cross-site scripting. This may sound like a minor exasperation associated with more erudite attacks which might hasten the user to supply some bank information via a JavaScript model which are afterward sent to third-party websites.

Fortunately, when a variable is rendered within the @{{}} escape tags, Laravel will render in its place a string as the following one:

My list &lt;script&gt;alert("spam spam spam!")&lt;/script&gt;

This makes Laravel applications immune to this type of attack.

Laravel applications are immune to cross-site scripting attacks.

"With Laravel, you can rest assured that the most common attacks will be handled by default."

Aside: Securing Laravel APIs with Auth0

Securing Laravel APIs with Auth0 is very easy and brings a lot of great features to the table. With Auth0, we only have to write a few lines of code to get:

Sign Up for Auth0

You'll need an Auth0 account to manage authentication. You can sign up for a free account here. Next, set up an Auth0 API.

Set Up an API

Go to APIs in your Auth0 dashboard and click on the "Create API" button. Enter a name for the API. Set the Identifier to a URL(existent or non-existent URL). The Signing Algorithm should be RS256.

Create API on Auth0 dashboard Create API on Auth0 dashboard

We're now ready to implement Auth0 authentication on our Laravel backend API.

Dependencies and Setup

Install the laravel-auth0 package via composer like so:

composer require auth0/login:"~5.0"

Generate the laravel-auth0 package config file like so:

php artisan vendor:publish

After the file is generated, it will be located at config/laravel-auth0.php. Ensure you replace the placeholder values with the authentic values from the Auth0 Admin Dashboard. Double check your values with laravel-auth0.

Your .env file should have the AUTH0_DOMAIN, AUTH0_CLIENT_ID, AUTH0_CLIENT_SECRET and AUTH0_CALLBACK_URL values like so:

AUTH0_DOMAIN=kabiyesi.auth0.com
AUTH0_CLIENT_ID=xxxxxxxxxxxxxxxxxx
AUTH0_CLIENT_SECRET=xxxxxxxxxxxxxxxxx
AUTH0_AUDIENCE=http://mylaravelapi.com
AUTH0_CALLBACK_URL=null

Activate Provider and Facade

The laravel-auth0 package comes with a provder called LoginServiceProvider. Add this to the list of application providers.

// config/app.php
'providers' => array(
    // ...
    \Auth0\Login\LoginServiceProvider::class,
);

If you would like to use the Auth0 Facade, add it to the list of aliases.

// config/app.php

'aliases' => array(
    // ...
    'Auth0' => \Auth0\Login\Facade\Auth0::class,
);

The user information can now be accessed with Auth0::getUser(). Finally, you need to bind a class that provides a user (your app model user) each time the user is logged in or an access_token is decoded. You can use the Auth0UserRepository provided by this package or you can build your own class.

To use Auth0UserRepository, add the following lines to your app's AppServiceProvider:

// app/Providers/AppServiceProvider.php

public function register()
{

    $this->app->bind(
      \Auth0\Login\Contract\Auth0UserRepository::class, 
      \Auth0\Login\Repository\Auth0UserRepository::class
    );

}

Configure Authentication Driver

The laravel-auth0 package comes with an authentication driver called auth0. This driver defines a user structure that wraps the normalized user profile defined by Auth0. It doesn't actually persist the object but rather simply stores it in the session for future calls.

This is adequate for basic testing or if you don't have a requirement to persist the user. At any point you can call Auth::check() to determine if there is a user logged in and Auth::user() to retreive the wrapper with the user information.

Configure the driver in config/auth.php to use auth0.

// app/config/auth.php

// ...
'providers' => [
    'users' => [
        'driver' => 'auth0'
    ],
],

Secure API Routes

Your API routes are defined in routes/api.php for Laravel 5.3+ apps.

// routes/api.php

<?php

use Illuminate\Http\Request;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::get('/public', function (Request $request) {
  return response()->json(["message" => "Hello from a public endpoint! You don't need any token to access this URL..Yaaaay!"]);
});

Route::get('/wakanda', function (Request $request) {
  return response()->json(["message" => "Access token is valid. Welcome to this private endpoint. You need elevated scopes to access Vibranium."]);
})->middleware('auth:api');

Now, you can send a request to your protected endpoint which includes an access_token.

curl --request GET \
  --url http://localhost:8000/api/wakanda \
  --header 'authorization: Bearer <ACCESS TOKEN>'

Once a user hits the api/wakanda endpoint, a valid JWT access_token will be required before the resource can be released. With this in place, private routes can be secured.

More Resources

That's it! We have an authenticated Laravel API with protected routes. To learn more, check out the following resources:

Conclusion

As you may know, there are other things you must do to protect your mission-critical applications, such as disabling verbose error reporting to stop sensitive details about your application being made visible to a bad actor. Nevertheless, Laravel ensures a much more secure application by protecting again these common attack vectors, reducing the attack surface out-of-the-box.

Laravel is one of the reasons behind the renewed interest in the PHP developer community. Using a more secure base application and following the familiar model–view–controller (MVC) architectural pattern, it's popularity grew fast. As a free, open-source framework, created by Taylor Otwell and based on Symfony, Laravel took over as the defacto framework within a few years of its introduction.