How to use Passport with Laravel Modules (nwidart)

santhoshj

Santhosh

Posted on September 18, 2019

How to use Passport with Laravel Modules (nwidart)

Let me introduce these two packages for those who are new to it.

Laravel Passport:

Laravel makes API authentication a breeze using Laravel Passport, which provides a full OAuth2 server implementation for your Laravel application in a matter of minutes. Passport is built on top of the League OAuth2 server that is maintained by Andy Millington and Simon Hamp.

Note: I followed the Medium article to configure Passport - Here is the medium article for further reference.

Laravel Modules:

nwidart/laravel-modules is a Laravel package which was created to manage your large Laravel app using modules. A module is like a Laravel package, it has some views, controllers or models. This package is supported and tested in Laravel 5.

This package is a re-published, re-organised and maintained version of pingpong/modules, which isn't maintained anymore. This package is used in AsgardCMS.

When creating enterprise applications, it will be much useful to develop them as modular as possible to make it maintainable. I was going through a scenario where I have to implement a users module using Laravel Module and authentication is using Passport. Here is how I did it.

1.Start a new laravel project

composer create-project laravel/laravel my-app

For making it less clutter, I moved the default migrations out of this project. We will later be adding it back to the project under user module.

cd my-app

2. Install and configure Laravel Modules:

composer require nwidart/laravel-modules
php artisan vendor:publish --provider="Nwidart\Modules\LaravelModulesServiceProvider"

3. Add Modules folder to autoload array in composer.json:

"autoload": {
        "psr-4": {
            "App\\": "app/",
            "Modules\\": "Modules/"
        },
        "classmap": [
            "database/seeds",
            "database/factories"
        ]
    },

4. Run auto load

composer dumpautoload

5. Create Users module and model:

php artisan module:make Users
php artisan module:make-model User Users

6. Copy the migration under *my-app/Modules/Users/Database/Migrations*

We will set up the login and registration functionalities once we finish configuring the Passport.

7. Install and configure Passport:

composer require laravel/passport

8. Edit config/app.php to add Passport service provider

'providers' =>[
Laravel\Passport\PassportServiceProvider::class,
],

9. Run migrate and install - Install will create the token keys for security.

php artisan migrate
php artisan passport:install

10. Move the app/User.php to Modules/Users/Entities/User.php

11. app/Providers/AuthServiceProvider.php

<?php
namespace App\Providers;
use Laravel\Passport\Passport; 
use Illuminate\Support\Facades\Gate; 
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider 
{ 
    /** 
     * The policy mappings for the application. 
     * 
     * @var array 
     */ 
    protected $policies = [ 
        'App\Model' => 'App\Policies\ModelPolicy', 
    ];
/** 
     * Register any authentication / authorization services. 
     * 
     * @return void 
     */ 
    public function boot() 
    { 
        $this->registerPolicies(); 
        Passport::routes(); 
    } 
}

12. IMPORTANT: In config/auth.php, specify the api authentication driver to passport. Also, in providers, let laravel know that we have to use the User class inside Modules to be the model. NOT the default app/User::class.

<?php
return ['guards' => [   
    'web' => [   
        'driver' => 'session',   
        'provider' => 'users',   
    ],   
    'api' => [   
        'driver' => 'passport',   
        'provider' => 'users',   
    ],   
],
.
.
.
'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => Modules\Users\Entities\User::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

13. Add API Routes in Modules/Users/Routes/api.php

Route::post('login', 'UsersController@login');
Route::post('register', 'UsersController@register');

14. Create Users Controller - Laravel Module will create this on its own when we create the model.

<?php

namespace Modules\Users\Http\Controllers;

use Validator;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Modules\Users\Entities\User;
use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Auth; 

class UsersController extends Controller
{
    public $successStatus = 200;

    /**
    * Handles user logins
    *
    * @return void
    */
    public function login()
    {
        if(Auth::attempt(['email' => request('email'), 'password' => request('password')])){ 
            $user = Auth::user(); 
            $success['token'] =  $user->createToken('my-app')-> accessToken; 
            return response()->json(['success' => $success], $this-> successStatus); 
        } 
        else{ 
            return response()->json(['error'=>'Unauthorised'], 401); 
        } 
    }

    /** 
     * Register api 
     * 
     * @return \Illuminate\Http\Response 
     */ 
    public function register(Request $request) 
    { 
        $validator = Validator::make($request->all(), [ 
                'name' => 'required', 
                'email' => 'required|email', 
                'password' => 'required', 
                'c_password' => 'required|same:password', 
            ]);
            if ($validator->fails()) { 
                return response()->json(['error'=>$validator->errors()], 401);            
            }
            $input = $request->all(); 
            $input['password'] = bcrypt($input['password']); 
            $user = User::create($input); 
            $success['token'] =  $user->createToken('MyApp')-> accessToken; 
            $success['name'] =  $user->name;
            return response()->json(['success'=>$success], $this-> successStatus); 
        }

        /** 
        * details api 
        * 
        * @return \Illuminate\Http\Response 
        */ 
        public function details() 
        { 
            $user = Auth::user(); 
            return response()->json(['success' => $user], $this-> successStatus); 
        } 

    }

15. In command line, run the server and you will be able to test it using Postman or Insomnia.

php artisan serve

Please feel free to ask any questions on this article. I will be happy to help. Reach me - santhoshj at gmail dot com.

Written with StackEdit.

💖 💪 🙅 🚩
santhoshj
Santhosh

Posted on September 18, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related