Skip to content

Laravel - Security

Security is a critical aspect of any web application. Laravel provides numerous built-in features and follows best practices to help you build secure applications. Here are some key security considerations:

Laravel’s Hash facade provides secure Bcrypt and Argon2 hashing for storing user passwords. Bcrypt is the default hashing algorithm.

To hash a password, use the make method:

use Illuminate\Support\Facades\Hash;
$password = 'my-secret-password';
$hashedPassword = Hash::make($password);

To verify a password against a stored hash, use the check method:

if (Hash::check('my-secret-password', $hashedPassword)) {
// The passwords match...
}

The check() method returns true if the plain-text password matches the hashed password, and false otherwise.

Laravel makes implementing authentication very simple. You can quickly scaffold authentication views and routes using starter kits like Laravel Breeze or Laravel Jetstream. Underneath, Laravel’s built-in authentication services, like the Auth facade, handle user verification.

The Auth::attempt method is commonly used to handle authentication attempts from a login form. It takes an array of credentials as its first argument:

use Illuminate\Support\Facades\Auth;
// Example in a login controller method
public function login(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate(); // Important for security
return redirect()->intended('dashboard');
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
]);
}

The attempt method verifies the credentials against the database. If authentication is successful, it returns true and establishes an authenticated session. The intended method redirects the user to the URL they were trying to access before being intercepted by the authentication middleware, or to a fallback URI.

Protecting Against Cross-Site Request Forgery (CSRF)

Section titled “Protecting Against Cross-Site Request Forgery (CSRF)”

CSRF attacks occur when a malicious website tricks a user’s browser into making an unintended request to your application while the user is authenticated. Laravel automatically generates a CSRF “token” for each active user session. This token is used to verify that authenticated users are the ones actually making requests to the application.

Anytime you define an HTML form in your application that makes a POST, PUT, PATCH, or DELETE request, you should include a hidden CSRF token field using the @csrf Blade directive:

<form method="POST" action="/profile">
@csrf
<!-- ... other form fields ... -->
<button type="submit">Submit</button>
</form>

Laravel’s VerifyCsrfToken middleware, included in the web middleware group, automatically verifies this token for all non-GET requests.

Protecting Against Cross-Site Scripting (XSS)

Section titled “Protecting Against Cross-Site Scripting (XSS)”

XSS attacks occur when attackers inject client-side scripts (usually JavaScript) into pages viewed by other users. To prevent XSS, you should never trust user-submitted data and always escape it before rendering it in your HTML.

Blade’s double-brace syntax {{ $variable }} automatically escapes output using PHP’s htmlspecialchars function, preventing XSS:

<div>{{ $userInput }}</div>

If you need to render unescaped HTML (and you are certain the content is safe), use the {!! $variable !!} syntax. Use this with extreme caution.

SQL injection vulnerabilities occur when an application inserts unfiltered user input into SQL queries. Laravel’s Eloquent ORM and Query Builder use PDO parameter binding by default, which protects against SQL injection. As long as you use these tools correctly, your database queries will be safe from this type of attack.

// Safe: Eloquent uses parameter binding
User::where('email', $request->email)->first();
// Safe: Query Builder uses parameter binding
DB::table('users')->where('email', $request->email)->first();
// Unsafe: Raw SQL query with direct concatenation (AVOID THIS)
// DB::select(DB::raw("SELECT * FROM users WHERE email = '" . $request->email . "'"));

By default, all cookies generated by Laravel are encrypted and signed so they can’t be modified or read by the client-side JavaScript. The APP_KEY in your .env file is used as the encryption key. If this key is changed, all existing cookies will be invalidated.

Always use HTTPS (HTTP Secure) for your production applications, especially when sensitive data is being transmitted (e.g., login credentials, personal information, session data). HTTPS encrypts data in transit, preventing attackers on the same network from intercepting it. You can configure your web server (Nginx, Apache) to enforce HTTPS.

Consider implementing a Content Security Policy (CSP) header. CSP is an added layer of security that helps to detect and mitigate certain types of attacks, including XSS and data injection. You can configure CSP headers through middleware or by using packages like spatie/laravel-csp.

Additional Resources: Regularly review the Laravel security documentation and stay updated on common web vulnerabilities through resources like OWASP (Open Web Application Security Project).