DEV Community

Basim Ghouri
Basim Ghouri

Posted on • Updated on

Security in Laravel: How to Protect Your App Part 1

SQL Injections

In plain PHP, we need to bind all the parameters on SQL queries. But in Laravel, we have the query builder and Eloquent ORM that provides automatic protection against SQL injections by adding param binding by default. Even with this, you should watch out for malicious requests, like for example:

User::query()->create($request->all());
Enter fullscreen mode Exit fullscreen mode

This code could lead to a mass assignment. In this case, a user can send a payload like this:

{
    "name": "Basim Ghouri",
    "email": "basim@gmail.com",
    "role_id": "admin" 
}
Enter fullscreen mode Exit fullscreen mode

Another code that could lead to the same issue could be:

$user->fill($request->all());
$user->save();
Enter fullscreen mode Exit fullscreen mode

In this example, we are hydrating an eloquent model with all the data from a request and then saving it.

A malicious user can try with different payloads. Or, they can add extra inputs with different names and try to find a weak implementation like this.

Hopefully, with this example, we can see that we need to take care of mass assignments. We cannot trust any user request, because any user can open the browser inspector and add an input in a monolith or modify the payload from an API.

Laravel provides different ways to handle this:

Set Fillable Property

We can prevent mass assignment by adding explicitly the fields that a model contains by using protected properties, "fillable" or "guarded":

protected $fillable = ['name', 'email', 'password', 'role_id'];
Enter fullscreen mode Exit fullscreen mode

In this case, we are adding explicitly the columns that a model contains. You can use the guarded property as an empty array. Personally, I do not like this approach as many projects have more than one developer and there is no guaranty that other developers would validate the data.

The forceFill() method can skip this protection, so take care when you are using this method.

Validate Request Data

You should validate any type of resource no matter where it came from. The best policy is to not trust the user. Laravel provides FormRequest so we only need to create one with artisan:

php artisan make:request UserRequest
Enter fullscreen mode Exit fullscreen mode

You can define the rules to validate your requests:

public function authorize() 
{
    return $this->user()->check(); 
} 

public function rules() 
{     
    return [
        'name' => ['required', 'string', 'min:5', 'max:255'],
        'email' => ['required', 'email', 'unique:users'],
        'password' =>   ['required', Password::default()]
    ]; 
}
Enter fullscreen mode Exit fullscreen mode

The authorize method must return a boolean. It is a convenient way to return an authorization validation before starting to validate the requested content. This is something to take in mind and it would apply in any route that has the middleware auth for web or sanctum/API if you are using token-based authentication.

The rules method returns an array with the rules that are validating your request. You can use a lot of rules out of the box or create your own custom rules. If you are interested to dive in deeper into this topic, you can find all the rules in the doc: https://laravel.com/docs/8.x/validation#available-validation-rules.

Oldest comments (2)

Collapse
 
basimghouri profile image
Basim Ghouri

Follow And like for more laravel security parts

Collapse
 
julia_kot profile image
Julia K

I have read all 4 parts of this article. thanks for the info