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.”
Tweet This
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>
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 <script>alert("spam spam spam!")</script>
This makes Laravel applications immune to this type of attack.
“With Laravel, you can rest assured that the most common attacks will be handled by default.”
Tweet This
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, you only have to write a few lines of code to get:
- A solid identity management solution, including single sign-on
- User management
- Support for social identity providers (like Facebook, GitHub, Twitter, etc.)
- Enterprise identity providers (Active Directory, LDAP, SAML, etc.)
- Our own database of users
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
You're now ready to implement Auth0 authentication in your Laravel API.
Dependencies and Setup
Install the
laravel-auth0
package by entering the following in your terminal:composer require auth0/login:"~5.0"
Generate the
laravel-auth0
package config file:php artisan vendor:publish
After the file is generated, it will be located at
config/laravel-auth0.php
. Double check your values match those found here.Now you need to open your
.env
file to create and fill in those variables. Add the following anywhere in your .env
file:AUTH0_DOMAIN=kabiyesi.auth0.com AUTH0_CLIENT_ID=xxxxxxxxxxxxxxxxxx AUTH0_CLIENT_SECRET=xxxxxxxxxxxxxxxxx AUTH0_AUDIENCE=http://mylaravelapi.com AUTH0_CALLBACK_URL=null
Now replace all of those placeholders with the corresponding value from your Auth0 dashboard.
Activate Provider and Facade
The
laravel-auth0
package comes with a provider 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 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 need 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 retrieve 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 with 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! You 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.