Laravel Idea for PhpStorm - Full-featured IDE for productive artisans!

9 Quick Tips for Auth in Laravel

Published on by

9 Quick Tips for Auth in Laravel image

Laravel has a great out-of-the-box Auth system, but surely we need to customize things here and there. For some of them, no need to look for external packages or write a lot of custom code, let’s explore what interesting abilities are hiding under the hood of Auth.

Tip 1. Auth::routes() Parameters

We all probably know the method Auth::routes() that comes from the Laravel UI package (before Laravel 7, it was included in the core).

But did you know it may accept an array of parameters to enable/disable certain Auth routes?

As of Laravel 7, here are possible parameters, with their default values:

Auth::routes([
'login' => true,
'logout' => true,
'register' => true,
'reset' => true, // for resetting passwords
'confirm' => false, // for additional password confirmations
'verify' => false, // for email verification
]);

Those parameters just enable or disable some routes.

To understand how they work, you can look at the file AuthRouteMethods in Laravel UI:

return function ($options = []) {
// Login Routes...
if ($options['login'] ?? true) {
$this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
$this->post('login', 'Auth\LoginController@login');
}
 
// Logout Routes...
if ($options['logout'] ?? true) {
$this->post('logout', 'Auth\LoginController@logout')->name('logout');
}
 
// Registration Routes...
if ($options['register'] ?? true) {
$this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
$this->post('register', 'Auth\RegisterController@register');
}
 
// Password Reset Routes...
if ($options['reset'] ?? true) {
$this->resetPassword();
}
 
// Password Confirmation Routes...
if ($options['confirm'] ??
class_exists($this->prependGroupNamespace('Auth\ConfirmPasswordController'))) {
$this->confirmPassword();
}
 
// Email Verification Routes...
if ($options['verify'] ?? false) {
$this->emailVerification();
}
};

Tip 2. Laravel UI: Generate Controllers Only

The official documentation specifies this main way of using Laravel UI:

php artisan ui vue --auth

But what if you don’t need the visual UI? What if you’re creating only an API-based project, and you don’t have any front-end on the Laravel side?

You can still use Laravel Auth and its Controllers. Install Laravel UI package and run this:

php artisan ui:controllers

It will generate only app/Http/Controllers/Auth contents, so you don’t need Blade/Vue files to use them.

See the implementation of this Artisan command in Github repository.


Tip 3. Re-Confirm Password for Important Settings

Have you ever maintained a Github repository, and tried to change its access settings? Then Github asks you to re-enter your password again, just to make sure it’s you.

Since Laravel 6.2, we also have that feature in the framework.

All you need to do is to add a Middleware called password.confirm to the route(s) that you want to protect.

Route::get('/secrets', 'SecretsController@show')->middleware('password.confirm');

Quoting Dries Vints from the official feature release article:

If you attempt to access the route, you will be prompted to confirm your password, similar to what you may have seen on other applications like GitHub.

Confirming the password will store a timestamp in the user’s session that lasts for three hours by default so users do not have to enter their password during that period again.

You may customize this duration using a new password_timeout configuration option in the auth configuration file._


Tip 4. Logout Other Devices

From Laravel 5.6, we have a separate method to automatically log out any other devices or browsers that are logged in with our account:

Auth::logoutOtherDevices($password);

Typical usage of this would be to log out other devices when the current device is successfully logged in. To do that, we override a method authenticated() from a Trait AuthenticatesUsers.php, and put this into app/Http/Controllers/Auth/LoginController.php:

protected function authenticated(Request $request, $user)
{
\Auth::logoutOtherDevices(request('password'));
}

Also, don’t forget to activate one middleware AuthenticateSession in app/Http/Kernel.php file, which is commented out by default:

protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],

Redirect after Login/Register: Custom Logic

By default, both Laravel LoginController and RegisterController have the same property:

class RegisterController extends Controller
{
protected $redirectTo = RouteServiceProvider::HOME;

So you can specify what URL to redirect to after successful login/registration. The default value is in app/Providers/RouteServiceProvider.php:

class RouteServiceProvider extends ServiceProvider
{
public const HOME = '/home';

How can you customize it?

First, you can change the value of that $redirectTo property, to some other constant, and maybe separately for Login and Registration.

But what if you have a more complex logic of dynamic redirect, that depends on a user role, for example?

You can create a method in those Auth Controllers, call it redirectTo(), and specify your conditions inside. That method will override any values of $redirectTo property.

See example:

class RegisterController extends Controller
{
protected $redirectTo = RouteServiceProvider::HOME;
 
protected function redirectTo()
{
if (auth()->user()->role_id == 1) {
return '/admin';
}
return '/home';
}

Tip 5. Quickly Create New Users

What if you need to create one new user, and you don’t have a registration form ready?

Just open Laravel Tinker in your Terminal:

php artisan tinker

If you’re not familiar with Tinker, it’s a command-line tool to execute any Laravel/PHP code. So, inside of that, you can easily create a user, typing this Eloquent command and hitting Enter:

\App\User::create(['name' => 'Admin', 'email' => 'admin@admin.com', 'password' => bcrypt('somesecurepassword')]);

But, what if you need to create many users for testing, Like, 10, or 100, or 1000? No problem, we can use a Factory class that comes by default with Laravel, in database/factories/UserFactory.php:

$factory->define(User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
];
});

These are default values for the “fake” user that we may create. To do that, we will generate a Seeder file:

php artisan make:seeder UsersSeeder

Then, we open that generated file database/seeds/UsersSeeder.php and fill run() method with this:

public function run()
{
// This will create 100 users
factory(App\User::class, 100)->create();
}

To launch that, we need to run this command:

php artisan db:seed --class=UsersSeeder

You can read more about database seeding in the official Laravel documentation.


Tip 6. Login with Email and/or Username

By default, Laravel users authenticate with email and password. But what if your identifier is not email? Some kind of username, for example.

You can change it easily by overriding one method from the AuthenticatesUsers.php trait.

Here’s the default value:

trait AuthenticatesUsers
{
// ... other methods
 
public function username()
{
return 'email';
}

You can copy that into your LoginController.php and just change the value:

class LoginController extends Controller
{
use AuthenticatesUsers;
 
// ... other methods
 
public function username()
{
return 'username';
}
}

Let’s take one step even further. What if your users can log in with email OR username? So there’s an input field called “Email/username” and they can put in one or another.

Let’s add a “trick” to the same username() method from above. We check if the entered string is an email, otherwise, we treat it as a username. That check is a PHP function, not even Laravel.

class LoginController extends Controller
{
// ...
 
public function username()
{
return filter_var(request('email'), FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
}
}

Notice: don’t forget that in your login form, you need to change input type="email" to type="text"


Tip 7. Too Many Login Attempts: Customize Parameters

If you try to log in with invalid credentials more than five times within the same minute, you will get blocked, with a message Too many login attempts. Please try again in X seconds.

That block will be active for 1 minute, and it is unique to the user’s username/e-mail and their IP address.

You can customize those parameters:

  • Amount of invalid attempts within a minute (default five attempts)
  • How many minutes to block logins (default 1 minute)

Those two parameters are inside of a Trait ThrottlesLogins:

trait ThrottlesLogins
{
// ... other methods
 
/**
* Get the maximum number of attempts to allow.
*
* @return int
*/
public function maxAttempts()
{
return property_exists($this, 'maxAttempts') ? $this->maxAttempts : 5;
}
 
/**
* Get the number of minutes to throttle for.
*
* @return int
*/
public function decayMinutes()
{
return property_exists($this, 'decayMinutes') ? $this->decayMinutes : 1;
}
}

So, to override those, you may specify properties inside of your LoginController:

class LoginController extends Controller
{
protected $maxAttempts = 3; // Default is 5
protected $decayMinutes = 2; // Default is 1
 
// ...
}

Tip 8. Registration: Disable Auto-Login

By default, a newly registered user is automatically logged in and redirected to the home page.

If you want to disable that and show some “success” page instead, without automatically creating a user’s session, here’s what you can do.

The original registration method is inside the Trait RegistersUsers:

trait RegistersUsers
{
public function register(Request $request)
{
$this->validator($request->all())->validate();
 
event(new Registered($user = $this->create($request->all())));
 
$this->guard()->login($user);
 
if ($response = $this->registered($request, $user)) {
return $response;
}
 
return $request->wantsJson()
? new Response('', 201)
: redirect($this->redirectPath());
}

So your goal is to override it in RegisterController and return a redirect to your new page, instead of logging in:

class RegisterController extends Controller
{
use RegistersUsers;
 
public function register(Request $request)
{
$this->validator($request->all())->validate();
 
event(new Registered($user = $this->create($request->all())));
 
return redirect()->route('your_success_page_route_name');
}

Tip 9. Login: Additional Check with Email/Password

What if you need some extra check, in addition to the default email and password? For example, you want to check if the user is active, or not banned.

You can add extra elements to credentials array, which is defined in the trait AuthenticatesUsers:

trait AuthenticatesUsers
{
// ...
 
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password');
}

You just override this in LoginController and add whatever you want:

class LoginController extends Controller
{
// ...
 
protected function credentials(Request $request)
{
return $request->only($this->username(), 'password') + ['is_active' => 1];
}

Notice: this is an interesting quick tip, but I would advise you to perform such extra check in a separate Middleware, then you could provide a more explicit error message to the user, instead of a default credentials error.


That’s it, these are the quick tips, but there’s much more to be extended with custom code and external packages. So, stay tuned for more articles to come on that topic!

PovilasKorop photo

Creator of Courses and Tutorials at Laravel Daily

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

Laravel Forge logo

Laravel Forge

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Forge
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
No Compromises logo

No Compromises

Joel and Aaron, the two seasoned devs from the No Compromises podcast, are now available to hire for your Laravel project. ⬧ Flat rate of $7500/mo. ⬧ No lengthy sales process. ⬧ No contracts. ⬧ 100% money back guarantee.

No Compromises
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $2500/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Lucky Media logo

Lucky Media

Get Lucky Now - the ideal choice for Laravel Development, with over a decade of experience!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
LaraJobs logo

LaraJobs

The official Laravel job board

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Multi-tenant Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit
Rector logo

Rector

Your partner for seamless Laravel upgrades, cutting costs, and accelerating innovation for successful companies

Rector
MongoDB logo

MongoDB

Enhance your PHP applications with the powerful integration of MongoDB and Laravel, empowering developers to build applications with ease and efficiency. Support transactional, search, analytics and mobile use cases while using the familiar Eloquent APIs. Discover how MongoDB's flexible, modern database can transform your Laravel applications.

MongoDB

The latest

View all →
The Inertia.js v2 Beta is Here image

The Inertia.js v2 Beta is Here

Read article
Mastering Laravel, No Compromises, and SourceDive with Joel Clermont image

Mastering Laravel, No Compromises, and SourceDive with Joel Clermont

Read article
Now you can install PHP and the Laravel installer with a single command image

Now you can install PHP and the Laravel installer with a single command

Read article
WireSpy is a Sleek New Debug Bar for Laravel Livewire image

WireSpy is a Sleek New Debug Bar for Laravel Livewire

Read article
The Laracon AU schedule is now live image

The Laracon AU schedule is now live

Read article
Supercharge PhpStorm with Laravel Idea image

Supercharge PhpStorm with Laravel Idea

Read article