Sidenote: Skip to the Initial setup if you want to dive straight into tutorial. If you are interested only in e-mail authentication, part 2 of the tutorial can be found in the next post.

Passwords, pretty simple and effective system one would say… hundreds years ago. Nowadays, it’s a nightmare of the Internet users across the globe. We forget them, we lost them, people steal them, share and reuse. Passwords and rules associated with them became so annoying there are comic stories about them.

Password complexity

In the past we had to remember 1 code for you mobile phone, 1-2 codes for bank related access and e-mail password, maybe 1 or 2 more if you were part of a community which happened to use some kind of on-line forum. Today we don’t really use code for mobile phone, it’s on all the time, but we still have codes for bank things, e-mails (very often more than 3) and in addition to that there are social media (Twitter, Facebook, Instagram, YouTube, Reddit – that list can go on and on), games (fortunately centralized clients like Battle.net app are there) and educational accounts (mainly in high school and higher). Of course these are just the most popular, every website wants you to sign up and share with them your shiny e-mail address, of course account should be protected by STRONG password.

Amount of passwords to come up with and remember is pretty astonishing. This leads to many bad practices like:

  • one to rule them all – one password used everywhere, break one, get access to all of them
  • too simple – dictionary based, short, very often representing the common fact about us
  • written down – writing password on the device or it’s key is terrible idea

Of course, there are managers for passwords, they are even coming with your browsers, but is it comfortable? Maybe if you are using only one device, but nowadays when people constantly switch between PC, tablet, phone and public computers, it’s not too easy to carry your password library with you and not everyone can trust sync option,… when you forgot to log out in a classroom. It’s also worth mentioning that not everyone is a tech-guru and average (as not too much into technology) people don’t even bother setting up “this things”, but…

There is a common element between both groups and it’s e-mail. You may have no technology background, but you check you e-mail at least once a day and “once a day” is major understatement to new generations who are checking their various in-boxes constantly – you can assume push notifications are too slow for some people. You know your e-mail password, your inbox is probably open right now in another tab and near half of people open their e-mail via mobile devices.

Very often you have to confirm your e-mail, sometimes there is double-verification system which asks for password and e-mail authorization, but recently I saw couple lights at the end of different tunnels; services made e-mail based authentication (no need to post password, just e-mail to which authentication URL will be provided) their primary signing system and I love it – let’s make one, with Laravel.

Initial setup

Before you can log your user in with e-mail and URL, a few things need to be done. One of them is obviously user model and basic schema for database, based on which you will be able to verify your user; you can use materials from Cartalyst, if you decide to involve this package in your project, or just write them yourself. For purpose of this tutorial you just need an e-mail column, but to make things pretty I added nickname, self-incrementing id, password (for traditional log-in process) and dates. Something like this should do (put it in the UP section of your user tables migration):

Schema::create('users', function($table)
{
	$table->increments('id');
	$table->string('nick', 128);
	$table->string('email');
	$table->string('password', 255);
	$table->timestamps();
}

and a small User model:

/*app/models/User.php*/
class User extends Eloquent {

    protected $table = 'users';

    /*Optional, but worth keeping*/
    protected $hidden = array('password');
    protected $fillable = array('nick', 'email');
    protected $guarded = array('id', 'password');

}

When you are at creating, don’t hesitate and make authentication controller. You can do it manually, by making AuthController.php in your controllers folder (app/controllers) or letting Laravel do it for you and generate RESTful controller via command line:

php artisan controller:make AuthController

Command will fill controller with basic functions, but it’s not a big deal to remove them or add your own – no harm done, use the way you are comfortable with.

Finally it’s time to run a migration to let Laravel setup the table, after that you will be able to move to authenticating your users. Remember to add a test account, you can make it with seed option, which is relatively simple, very similar to migrating a schema – more info and example can be found in Laravel docs.

Traditional authentication

Now, with database, user model and test account, you can go ahead and start with simple, password-based authentication. You will need 3 things, a view for log-in form, functions to process posted requests and number of routes to connect these elements.

Sidenote: We will make password-based authentication first to be able to implement URL version as an alternative.

/*app/routes.php*/

	Route::get('login', array('uses' =>'AuthController@loginView'));
	Route::post('login', array('before' => 'csrf' ,'uses' =>'AuthController@loginTry'));

First route will call a view and present log-in form where users pass e-mail address and password. Second one will forward data from form to controller, in order to try authenticate user (csrf is a security check, more info can be found here. It will work out of the box if you are using Laravel’s engine for form generation – as in example below).

/*app/views/login.blade.php*/

@if(Auth::check())
	<p>You are already logged in. Enjoy it!</p>
@else				
	{{ Form::open( array('url' => 'login', 'role' => 'form') ) }}
	
	<div class="form-group">
		{{ Form::label('email', 'E-mail') }}
		{{ Form::email('email', '') }}
	</div>
	<div class="form-group">
		{{ Form::label('password', 'Password') }}
		{{ Form::password('password') }}
	</div>
		
	{{ Form::submit('Sign In') }}
	{{ Form::close() }}
@endif

This one is pretty simple. Blade will automatically build a form for you, which will send data to /login with POST flag. Of course, if user is already logged in, you don’t want to process authentication again, hence the Auth::check() which will prevent from showing the form at all.

/*controllers/AuthController.php*/

public function loginView()
{
	return View::make('auth.login', array('pageTitle' => 'Login'));	
}

public function loginTry()
{
	Input::only('email', 'password');
	// Set login credentials
	$credentials = array(
	'email'    => Input::get('email'),
	'password' => Input::get('password'),
	);
	
	// Try to authenticate the user
	$user = Auth::attempt($credentials);
	
	return Redirect::intended('/login');	
}

Final element of the puzzle, controller. loginView() is a response to /login (the “get” one) route and calls for log-in view from previous code chunk (login.blade.php), loginTry() is the function which processes the log in request. Input::only makes sure controller from will grab only inputs that we need (email and password), then it will be assign them to variables in array which will be used with Auth::attempt() after which user will be redirected back to /login.

Everything is rolling now, form gathers data which is forwarded by routes to proper controller’s functions and our test user should log in with no issues (with correct data). That’s it, but keep in mind that it would be a good idea to validate inputs, either during loginTry() or even before this step – your choice.

Homework External, solo task

This will close the first part of the tutorial and is a little task before you proceed to the next one.

As you are about to make e-mail-based, URL authentication, it’s pretty mandatory to have a functioning mechanism to send the message with URL. In order to do that, you are going to configure an SMTP for your Laravel installation. Head over to How-to: SMTP for mailing in Laravel and when you are ready, proceed to the next part.

How-to: No-pass authentication with URL & email #2 can be found in the next post.