API Authentication with LDAP and Laravel Passport
This article takes us through installation and configuration of LDAP and Laravel Passport on a Laravel project. This will enable API authentication with access and refresh tokens using existing Active Directory accounts.
Laravel comes with a fluent auth out of the box. For those wanting to use it as an API that manages its own API authentication, Passport does a fantastic job in that regard. Going further, some enterprise systems will require you to use their existing Active Directory accounts so everyone is saved from having to save gazillion passwords. And yes, Laravel LDAP does that well too.
Wait, it looks like there is no case where this article can come in after all. Maybe not just yet. What if you are required to develop an API for a mobile app but to be used by an enterprise? They require their Active Directory. They memorize one password. And you, on the other hand, require Laravel Passport to manage the app’s authentication with those tokens. Let’s crack this one up!
First, let’s set up the laravel application with
laravel new ldap-passport
Then install the two composer packages
composer require adldap2/adldap2-laravelcomposer require laravel/passport
You can find the config details of
adaldap installation on their docs
Since traditionally you cannot use LDAP and Passport together out of the box, we will draw their lines in our
auth config file and in
LoginController so that LDAP handles the authentication with Active Directory, and pass on to Passport to issue tokens to the client.
To achieve this, first we change the
api guard to
users provider to
ldap as in the code snippet below.
Next we proceed to our login controller. We will attempt to login with our user provider defined above
Auth::attempt(['username' => request('username'), 'password' => request('password'), true)
Then we fetch the passport client to use with the request. We assume (of course we require) the consumers of the API to pass their client’s API key in the request header.
$client = PassportClient::findClientBySecret(request()->header("apiKey"));
And then we use the client to generate API tokens to return to the client
$passport = (new PassportAuthenticator($request)) ->authenticate($client, request('username'), request('password'));
And finally we have out API tokens!
return response()->json([ "access_token" => $passport->access_token, "expires_in" => $passport->expires_in, "refresh_token" => $passport->refresh_token, ], 200),
The complete login controller should like the one below
That sorts us out, right? Not just yet. At this stage, when subsequent requests are made, the API will try to authenticate with
auth:api guard and that won’t work. So we will modify the
Kernel to pass our custom middleware (which will refer to Passport Middleware anyway). Here is how…
'passport' => \Laravel\Passport\Http\Middleware\CheckClientCredentials::class,
We add that to the
routeMiddleware array of our Http Kernel. So instead of using
auth:api in our protected routes, we will use
The very last thing, as you might have noticed, we did some abstraction in the Login Controller. There is a little more happening in
PassportAuthenticator classes. That was necessary to keep our code concise and focus on the main objective of the tutorial. You can see what’s happening behind the scenes in the snippets below: