How to add SAML2 login on Laravel in 10 minutes
SAML2 is an authentication protocol used often in enterprise companies. Its goal is to enable the company employees to sign into various applications using the same credentials (this is called Single Sign On).
The communication is made with an exchange of XML contents, that typically require much time to create, write, test and maintain during the entire product lifecycle. The aim of this article is to show how easy it is to add a SAML2 login in Laravel by using the correct packages.
We will use only Laravel Socialite, a package used to handle the sign in using external providers such as Google and Apple. Like many other packages in the Laravel ecosystem, it provides many features out of the box that are ready to be used.
Basic terminology
Identity Provider (IdP): the system who manages the users;
Service Provider (SP): the app that will redirect to the IdP login page and that want to know what user is authenticated.
For example, if you will add the “Sign in with Google”, you are the Service Provider and Google is the Identity Provider.
Install Socialite
Let’s start. The first step is to install Laravel Socialite and the SAML2 provider.
composer require laravel/socialite
composer require socialiteproviders/saml2
Adding the Identity Provider’s metadata
When dealing with Single Sign On, and in particular with SAML2, there are some informations that must be shared between the Identity Provider and the Service Provider. For example, the SP must know the URL of the IdP login page, and the IdP must know the callback URL of the SP. In this way, the Identity Provider knows where to redirect after the user login that will process user authentication data.
I suggest to use Auth0 with the free plan to test the SAML2 integration. Check this tutorial made by Auth0 to know how.
How to add the IdP metadata? There are two ways, the first is to pass a public URL containing the XML metadata, and the second is to use a local file.
In config/services.php
, you will have to add:
'saml2' => [
'metadata' => 'https://idp.co/metadata/xml', # if url
'metadata' => file_get_contents('/path/to/metadata/xml'), # if file
],
Now, the IdP metadata will be automatically discovered.
Redirect to the IdP login page
One important information in the IdP metadata is the redirect url, the link to open the IdP login page. Instead of retrieving the url from the metadata, you can use the following directive inside a controller that automatically redirect the user to the login page.
Route::get('/auth/redirect', function () {
return Socialite::driver('saml2')->stateless()->redirect();
});
I use the stateless method because the request is not initiated by the IdP but from the Service Provider (i.e. our app). If this is not necessary for you, you can consider to remove it.
If everything is good, calling the route /auth/redirect
will redirect you to the IdP login page.
Create the callback
Now that you have access to the login page from your app, it is possible to create the callback. It is a POST
route that will be called from the IdP after the user login, in which an XML content is passed containing all the users informations.
You can create a route with the POST method to return the user informations.
Route::post('/auth/saml2/callback', function () {
$user = Socialite::driver('saml2')->stateless()->user();
return $user;
});
If everything is good, you will be able to see the user data. But there could be a problem: how you will pass the callback url to the IdP? We have to generate the Service Provider metadata.
Generate the Service Provider metadata
The IdP gave you its metadata, but know you have to send them yours.
Typically, if you are using a common Identity Provider, it should provide in the interface to upload the XML metadata, but sometimes the implementations are made by the customer, so you will have to send the metadata through email or another similar system.
To generate the XML Service Provider metadata, there is a code out of the box ready to give you the file.
Route::get('/auth/saml2/metadata', function () {
return Socialite::driver('saml2')->getServiceProviderMetadata();
});
Now, go to this route, download it and send to your customer.
✅ All done! Now, you should be able to test the entire login workflow.
PS:Refer to the documentation to see all the available configurations.