Laravel: The Power of Authentication [Part 3]

Laravel: The Power of Authentication [Part 3]Forget about using your controller to manually login your users, learn the REAL way!.

Italo BaezaBlockedUnblockFollowFollowingMay 13Photo by Cytonn Photography on UnsplashAs a kind of follow up of my article about how the Authentication works in Laravel, here I will write about the moving parts of the authentication mechanism, like the Authentication middleware, the Guard, the Driver, the User Provider and Authenticatable.

We understand all the moving parts, but we need to glue them together.

In this third and final part we are gonna see how to do that by registering them inside the application and using the configuration.

This gluing is done silently by the AuthManager, a Service in charge of registering and instancing Authentication Guards, like the ones that come out of the box, and it uses the configuration file to know what the hell is doing otherwise it will run around in circles.

Understanding the ConfigurationThe configuration works in a simple way: You register a Guard name, like “web”, and you set the Guard Driver and the Provider (not User Provider) you’re gonna use with that guard, which by default are “session” and “users”, respectively.

config/auth.

phpThen in your code you can check if an User is authenticated into a particular Guard by its name: Auth::guard('web')->check().

The config needs a default, however, which will be used when you don’t issue the guard name in your code.

Thankfully, this is set in the very first key, which is nice for simple applications.

config/auth.

phpGoing back to the Guard configuration, the Providers are registered in this configuration file.

One of the purposes of this Providers key is to encapsulate the real User Provider, and pass the configuration array to it.

For example, the users provider uses eloquent as the User Provider, and this receives the whole key configuration, which contains the model key that will be used to know which model to retrieve from the database.

There is no need to create another authentication mechanism or provider for your other models; you can just change this here and you’re set.

Registering a Custom Authentication Guard Driver and User ProviderLet’s say we have created a way to authenticate users by an special header in the Request and to pull them out from an external API.

Let’s call them HeaderGuard, which is in reality the Guard Driver, and ApiUserProvider which will pull the Users from an external API.

Now that we have them somewhere in our code, we need to register them into the application, or it will never know when to use it.

The documentation is pretty straightforward about adding new Guard Drivers and registering custom User Providers.

Registering the Header GuardIn our AuthServiceProvider we will register our HeaderGuard using the Service Container instead of instancing it manually — you could but I consider this way more convenient.

This will ease our job of injecting any Service our Guard Driver could use, like for example, the Request and the respective User Provider.

If someday or the next minute we want to add a Service into our Guard, like the Cache Manager, we just simply change the _construct method parameters in our Guard and call it a day.

Auth::extend('header', function ($app, $name, array $config) { return $app->make(AppAuthHeaderGuard::class, [ 'name' => $name, 'config' => $config, 'provider' => $app['auth']->createUserProvider( $config['provider'] ?? null ) ]);});Note here that we are manually telling the Service Container to resolve the $provider in our HeaderGuard using the createUserProvider of the AuthManager.

This method creates the Users Providers by the name given, and if none is set, it will use the default.

Now that we have our Guard Driver, we can use it by writing header as our “driver” in our configuration file, but it will still take users from the Database since it uses the users provider, and this uses eloquent User Provider to pull Users from the database.

We don’t want that!Registering the User ProviderNow we need to register our ApiUserProvider.

That can be accomplished by just adding this:Auth::provider('external-api', function ($app, $config) { return $app->make(AppAuthApiUserProvider::class, [ 'config' => $config, ]);});This code will attach the external-api User Provider to a Closure that will return the ApiUserProvider, also resolved by the Service Container.

By the way, these Closures will be registered inside an array called customCreators and customProviderCreators in the AuthManager class.

Personally, I like a less straightforward way of registering Service (unless necessary).

In this example, I “optimized” the registration of the new Guard Driver and User Provider by pushing these registrations just before the service is resolved:Instead of resolving the AuthManager service every time my application is booting, I use the register() method of the Service Provider.

Here I tell the Service Container to only add our Driver and User Provider when we need to use authentication mechanisms.

With this there is no need to call the Authenticate Middleware, like inside a public route; we can just skip instancing the Auth Manager and every class that uses it.

Cool, möar performance!Using both as a GuardNow these are set, we only need to add both in the configuration.

We can just change the Driver and Provider for an existing Guard, or name our own.

I’ll go for the latter, and not set if as a default since I will use this Guard for other set of routes.

'guards' => [ // .

'remote' => [ 'driver' => 'header', 'provider' => 'external-provider', ], 'providers' => [ // .

'external-provider' => [ 'driver' => 'external-api', ], ],],Then, everything is ready to use your Guard like this:Route::prefix('external') ->middleware('auth:remote') ->group(function() { Route::get('/'->uses(function () { // .

}); Route::get('dashboard')->uses(function () { // .

});});And that’s pretty much it.

Again, trying to reinvent the wheel and create your own authentication logic inside a controller is just the bad way of doing it.

Use these moving cogs and you won’t need to change anything more in your code.

It will just work.

Hopefully, you have learned something to use in your future projects.

See ya next time.

.. More details

Leave a Reply