Menu Close

Add Session and CSRF protection to Lumen application

lumen

From version 5.2 onward, the Lumen PHP micro-framework made a big leap towards improving its performance and introduced some significant changes to its underlying philosophy and purpose. The framework made a shift towards focusing on stateless APIs, and removed a lot of features which used to come packaged with older versions. While these features were not essential in a RESTful API service, many developers still build traditional websites on Lumen given its speed and the ability to upgrade to Laravel easily should their project scale. Using the full Laravel framework is considerable overhead for such small projects.

Sessions were one of the features removed from Lumen in version 5.2, and as an essential requirement for persisting information across requests, is a cant-live-without feature in any web based application. In this post, I intend to discuss how to get back sessions in Lumen version 5.6 without significant draw-down in performance.

Of course, the easiest way to go about is to use PHP’s built in sessions. But a better approach that I personally favor is to use Laravel’s session handler so that you can make use of a lot of built in functions and helper methods that Laravel provides. Thus it becomes easier to upgrade the application to Laravel in the future if needed. Anyways I will discuss both methods below giving more emphasis and details to the second approach.

Using PHP’s built in sessions

A session can be easily started by calling the session_start() native method in PHP. You can include this code either directly in the bootstrap/app.php file or in a middleware. By default, PHP stores all session data in a file on disk, please read here to know more about PHP’s sessions and configuration. To use CSRF protection using this method, you will have to generate your own token and save it in a session variable, and then compare it on subsequent requests.

Using Laravel Session

This is the favored approach considering both functionality and scalability. To start with, you have to import Laravel’s session component illuminate/session into your application. You can install it easily using composer.

composer require illuminate/session

Now that you have installed the illuminate/session component, you have to configure it. You can copy the default configuration file for sessions from Laravel’s official repository to your application’s config folder. Create the folder if it does not exist. You can use the file as it is or change it to suit your needs.

By default, the session driver is set to file. If you want to change this, you can create a SESSION_DRIVER variable in your .env file. If you are going with the default configuration, you have to make sure that the folder where the session data is saved exists, and is writable by the application. See which folder is being used to store session data files in the files section of session.php and make sure the folder is writable. Default folder used by Laravel is storage/framework/sessions. So create it and give it write access.

Now open your bootstrap/app.php file and add the following lines under “Register Container Bindings” section to register the bindings for Illuminate\Session\SessionManager.

$app->singleton(Illuminate\Session\SessionManager::class, function () use ($app) {
    return new Illuminate\Session\SessionManager($app);
});

Then add the middleware Illuminate\Session\Middleware\StartSession to the list of global middlewares in the “Register Middleware” section.

$app->middleware([
    //other middlewares ...
    Illuminate\Session\Middleware\StartSession::class,
]);

Finally register the service provider. Unlike Laravel, Lumen does not automatically read the contents of config folder, so you have to use the configure() method on the container to load the configuration settings you had saved in config/session.php file. Under the “Register Service Providers” section, add

$app->configure('session');
$app->register(Illuminate\Session\SessionServiceProvider::class);

Accessing Session Data

To access sessions, you can call the session() method on the Request object. Even though the global helper method session() is not available in Lumen, you can access all functionality documented here.

For example, to read or write session data, you can use

$value = $request->session()->get('key');
$request->session()->put('key', 'value');
$request->session()->push('user.teams', 'developers');
$value = $request->session()->pull('key', 'default');

Or to flash temporary data

$request->session()->flash('status', 'Task was successful!');

You can now start using convenience methods on View objects as well.

return view('home')->with('message','session test');

Add CSRF protection

The Laravel session component automatically generates an _token session variable for every session. You can include this token in your forms as shown below.

<input type="hidden" name="_token" value="{{ app('request')->session()->get('_token') }}">

Or the cleaner way is to pass the token to the view

return view('home')->with('csrf_token', $request->session()->get('_token'));

and then access it in the view

<input type="hidden" name="_token" value="{{ $csrf_token }}">

And finally, add the VerifyCsrfToken middleware to validate the tokens. You can use this modified version of Laravel’s VerifyCsrfToken middleware, copy it to app/Http/Middleware folder and include this in your bootstrap/app.php file.

$app->middleware([
    //other middleware ...
    App\Http\Middleware\VerifyCsrfToken::class,
]);

You can also comment out line 40 in the VerifyCsrfToken file if you do not want to create a new token for every request. If you comment out the below line, one token will be issued per session.

$request->session()->regenerateToken();

Now everytime an invalid token is received by your application it will throw an Exception and deny to service that request.

Conclusion

Although Lumen is not intended for normal web applications anymore, I hope this tutorial will be useful for someone who is looking for session functionality in their Lumen application. Thanks for reading, and please feel free to drop your comments below.

Leave a Reply

Your email address will not be published. Required fields are marked *