Let’s Kill the Password! Magic Login Links to the Rescue!

Let’s Kill the Password! Magic Login Links to the Rescue!

Authentication is something that has evolved over the years. We have seen it change from email – password combination to social authentication, and finally password-less authentication. Actually, more like an “email only” authentication. In the case of a password-less login, the app assumes that you will get the login link from your inbox if the email provided is indeed yours.

Vector illustration of an open padlock on yellow background

The general flow in a password-less login system is as follows:

  • Users visit the login page
  • They type in their email address and confirm
  • A link is sent to their email
  • Upon clicking the link, they are redirected back to the app and logged in
  • The link is disabled

This comes in handy when you can’t remember your password for an app, but you do remember the email you signed up with. Even Slack employs this technique.

In this tutorial, we are going to implement such a system in a Laravel app. The complete code can be found here.

Creating the App

Let’s start by generating a new Laravel app. I am using Laravel 5.2 in this tutorial:

composer create-project laravel/laravel passwordless-laravel 5.2.*

If you have an existing Laravel project with users and passwords, worry not – we won’t be interfering with the normal auth flow, just creating a layer on top of what is already there. Users will still have the option of logging in with passwords.

Database setup

Next, we have to set up our MySQL database before running any migrations.

Open your .env file in the root directory and pass in the hostname, username, and database name:

[...]
DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=passwordless-app
DB_USERNAME=username
DB_PASSWORD=
[...]

If you’re using our Homestead Improved box, the database / username / password combination is homestead, homestead, secret.

Scaffolding Auth

One great thing that Laravel introduced in version 5.2 is the ability to add a pre-made authentication layer with just a single command. Let’s do that:

php artisan make:auth

This command scaffolds everything we need for authentication i.e the Views, Controllers, and Routes.

Migrations

If we look inside database/migrations, we notice that the generated Laravel app came with migrations for creating the users table and password_resets table.

We won’t alter anything since we still want our app to have the normal auth flow.

To create the tables, run:

php artisan migrate

We can now serve the app and users should be able to sign up and log in using the links in the nav.

Changing the Login Link

Next, we want to change the login link to redirect users to a custom login view where users will be submitting their email addresses without a password.

Navigate to resources/views/layouts/app.blade.php. That’s where we find the nav partial. Change the line with the login link (right below the conditional to check if the user is logged out) to this:

resources/views/layouts/app.blade.php

[...]
@if (Auth::guest())
<li><a href="{{ url('/login/magiclink') }}">Login</a></li>
<li><a href="{{ url('/register') }}">Register</a></li>
[...]

When a user tries to access a protected route when not logged in, they should be taken to our new custom login view instead of the normal one. This behavior is specified in the authenticate middleware. We’ll have to tweak that:

app/Http/Middleware/Authenticate.php

class Authenticate
{
[...]
public function handle($request, Closure $next, $guard = null)
{
    if (Auth::guard($guard)->guest()) {
        if ($request->ajax() || $request->wantsJson()) {
            return response('Unauthorized.', 401);
        } else {
            return redirect()->guest('login/magiclink');
        }
    }

    return $next($request);
}
[...]

Notice inside the else block we’ve changed the redirect to point to login/magiclink instead of the normal login.

Creating the Magic Login Controller, View, and Routes

Our next step is to create the MagicLoginController inside our Auth folder:

php artisan make:controller Auth\MagicLoginController

Continue reading %Let’s Kill the Password! Magic Login Links to the Rescue!%