Last updated on May 1, 2018
In my last tutorial, we created an APIs for todo application without authentication. In this tutorial, I would like to show you building JWT based login system. Let’s start…
Create Project
Create a brand new Laravel 5.6 project with Composer create-project
command:
$ composer create-project laravel/laravel arjunphp-jwt-auth 5.6 --prefer-dist
Database connection settings
After creating project open .env
file and update your database credentials:
... DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=arjunphp_jwt_auth DB_USERNAME=root DB_PASSWORD=mysql ...
Next step, would be, go to the project root and open the terminal and type the following command. It will create the two tables, which is by default ships by Laravel 5.6
$ php artisan migrate Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table Migrating: 2014_10_12_100000_create_password_resets_table Migrated: 2014_10_12_100000_create_password_resets_table
You might get following error :
PDOException::("SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes")
to fix this, all you have to do is to edit your AppServiceProvider.php
file and add to the boot method a default string length:
... use Illuminate\Support\Facades\Schema; .... function boot() { Schema::defaultStringLength(191); } ...
We gonna use jwt-auth library to generate and handle the JWT tokens, so let got to root of the project and run following Composer command from your terminal:
composer require tymon/jwt-auth
Then add the service JWTAuthServceProvider to the providers’ array and the JWTAuth facade to the aliases array in config/app.php
... 'providers' => [ ... Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class, ] ... 'aliases' => [ ... 'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, ]
Now publish the configuration file
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\JWTAuthServiceProvider"
Now generate a key in the published configuration
php artisan jwt:generate
Note: if this error gives you an error checkout below link to fix it.
https://github.com/tymondesigns/jwt-auth/issues/1298
Edit app/Http/Kernel.php
adding jwt.auth
and jwt.refresh
to the application’s route middleware array.
protected $routeMiddleware = [ ... 'jwt.auth' => \Tymon\JWTAuth\Middleware\GetUserFromToken::class, 'jwt.refresh' => \Tymon\JWTAuth\Middleware\RefreshToken::class, ];
Now let’s create the AuthController by issuing below command from the root of your project:
$ php artisan make:controller AuthController Controller created successfully.
Going forward we gonna define register, login, logout, refresh and user methods in the AuthController.
signup
Let register a signup route.
Route::post('signup', 'AuthController@register');
Let us also create a FormRequest to handle validation for every registration request.
php artisan make:request RegisterFormRequest
Now edit our RegisterFormRequest class to reflect the code below.
class RegisterFormRequest extends FormRequest { public function authorize() { return true; } public function rules() { return [ 'name' => 'required|string|unique:users', 'email' => 'required|email|unique:users', 'password' => 'required|string|min:6|max:10', ]; } }
Final setup, create the register method that will handle user registrations
public function register(RegisterFormRequest $request) { $user = new User; $user->email = $request->email; $user->name = $request->name; $user->password = bcrypt($request->password); $user->save(); return response([ 'status' => 'success', 'data' => $user ], 200); }
Login
Let’s deinfe login route
Route::post('login', 'AuthController@login');
Create the login method in AuthController, it will handle the user logins
public function login(Request $request) { $credentials = $request->only('email', 'password'); if ( ! $token = JWTAuth::attempt($credentials)) { return response([ 'status' => 'error', 'error' => 'invalid.credentials', 'msg' => 'Invalid Credentials.' ], 400); } return response([ 'status' => 'success', 'token' => $token ]); }
Current User
Let us define user route, it will give you current user information
Route::group(['middleware' => 'jwt.auth'], function(){ Route::get('auth/user', 'AuthController@user'); });
Define user method in controller, which will return current user information
public function user(Request $request) { $user = User::find(Auth::user()->id); return response([ 'status' => 'success', 'data' => $user ]); }
Logout
Now define logout route in routes/api.php
.
Route::group(['middleware' => 'jwt.auth'], function(){ Route::post('auth/logout', 'AuthController@logout'); });
Here is the log-out method which will handle the logout requests.
public function logout() { JWTAuth::invalidate(); return response([ 'status' => 'success', 'msg' => 'Logged out Successfully.' ], 200); }
Refresh token
Define route to check the current token is valid or not and refresh the token if it is not invalidated.
Route::middleware('jwt.refresh')->get('/token/refresh', 'AuthController@refresh');
create refresh method with below code
public function refresh() { return response([ 'status' => 'success' ]); }