In trying to build a very small micro-service I decided to use client credential grant tokens. I didn’t need users or personal tokens. I just needed one of my other sites to be able to access data for this new micro-service.
According to Taylor, “The client credentials grant is suitable for machine-to-machine authentication” which sounds just great. So I set off to build the entire service using TDD with Passport::actingAs() to mimic authorization knowing I’d do a final external test once it all was working.
All is working great and my tests are passing with my testing database. So, I run migrations on my real database, create my passport client with “php artisan passport:client,” give it a user id of 1, “ApiAccess” for the name for funsies, and keep the default for the redirect. This gives me a Client ID and Client secret.
I head over to Postman, pop those in, send a post and get my access token.
So far, so good. Now, I grab the access token, throw it in my headers, and fire off a post to my api waiting to be stunned by my own greatness…
After a 2ish hours, I figured out how to implement it without making a mess. These instructions assume you know what Client Credential Grant Tokens are for (read the above link about “machine-to-machine”) and why you might use them. Also it doesn’t address a funky token expiration issue that some found in postman. This, it turned out, didn’t affect me but did lead me on a wild goose chase for a bit.
To start with, move all your API routes that you want to use client credential authorization on out of:
and move them into a new route file titled:
This will allow us to separate these routes so we don’t affect any other necessary API routing in the future.
Next, we need to begin using this new routes file. To do this, I updated:
by adding a new method and calling it in the existing “map” method. I’ve abbreviated the file to show only the necessary updates:
class RouteServiceProvider extends ServiceProvider
// existing map method
public function map()
// ref new method for adding client credentials
// new client credentials method
protected function mapClientCredentialRoutes()
Route::prefix('api') // I still want /api/ urls
->middleware('client_credentials') // new middleware I'll set up in a bit
->group(base_path('routes/client_credentials.php')); // referencing my new routes file
Now that our routes are setup, we need to get that middleware working. We’re going to add it into the same file where the rest of our middleware is defined:
Here I created a new middleware group for client_credentials (“client_credentials” is the string we used in RouteServiceProvider.php for our new middleware). This file has been abbreviated to show only the updated info.
class Kernel extends HttpKernel
protected $middlewareGroups = [
'web' => [
'api' => [
// my new middleware group
'client_credentials' => [
Here you’ll notice we reference:
That is the %$%$@ middleware to check the client credentials that is no where to be found in the documentation.
With all that in place, I thought, yeah, this isn’t going to work but I’ll try it anyway. I fire up postman, try to hit an endpoint…
It worked! Yay! Hopefully if you’re banging your head against a keyboard right now trying to figure this out, like I was, this article will help.
I pulled ideas from this posts but the implementation was a bit awkward.