DEV Community

Cover image for create an Auth module with laravel using nwidart/laravel-modules package
ashrakt
ashrakt

Posted on • Edited on

create an Auth module with laravel using nwidart/laravel-modules package

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.

1) create project and install nwidart/laravel-modules package

  • create Laravel project
    composer create-project laravel/laravel module

  • install nwidart through Composer, by run the following command:
    composer require nwidart/laravel-modules

  • The package will automatically register a service provider and alias.
    Optionally, publish the package's configuration file by running:
    php artisan vendor:publish --provider="Nwidart\Modules\LaravelModulesServiceProvider"

2) Autoloading

  • By default the module classes are not loaded automatically. You can autoload your modules using psr-4. For example :


{
  "autoload": {
    "psr-4": {
      "App\\": "app/",
      "Modules\\": "Modules/"
    }
  }
}


Enter fullscreen mode Exit fullscreen mode
  • run composer dump-autoload

3) Generate a new module using the Nwidart package
php artisan module:make <module-name>
php artisan module:make Auth



app/
bootstrap/
vendor/
Modules/
  ├── Auth/
      ├── Assets/
      ├── Config/
      ├── Console/
      ├── Database/
          ├── Migrations/
          ├── Seeders/
      ├── Entities/
      ├── Http/
          ├── Controllers/
          ├── Middleware/
          ├── Requests/
          ├── routes.php
      ├── Providers/
          ├── BlogServiceProvider.php
      ├── Resources/
          ├── lang/
          ├── views/
      ├── Repositories/
      ├── Tests/
      ├── composer.json
      ├── module.json
      ├── start.php


Enter fullscreen mode Exit fullscreen mode

Image description

4) install sanctun
composer require laravel/sanctum

5) Publish the Laravel Sanctum configuration file.
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

6) Create the authentication controllers within the Auth module.



php artisan module:controller LogoutController Auth
php artisan module:controller RegisterControl Auth
php artisan module:controller LoginController Auth
php artisan module:controller ForgotPasswordController Auth
php artisan module:controller ResetPasswordController Auth



Enter fullscreen mode Exit fullscreen mode

7) Define the routes for authentication within the Auth module.
Create a file named routes/api.php within the Modules/Auth directory and add the following code:




Route::prefix('user')->group(function () {
    Route::post('register', [RegisterController::class,'register']);
    Route::post('login', [LoginController::class,'login']);
    Route::post('password/forgot ', [ForgotPasswordController::class, 'sendForgotLinkEmail']);
    Route::post('password/forgot/submit', [ForgotPasswordController::class, 'submitForgotPassword']);
    Route::post('password/reset', [ResetPasswordController::class, 'resetPassword'])->middleware(['auth:sanctum']);
    Route::post('logout', [LogoutController::class, 'logout'])->middleware(['auth:sanctum']);
});





Enter fullscreen mode Exit fullscreen mode

8) add auth table in Migrations folder module

Image description

9)

  • php artisan migrate
  • php artisan key:generate

10) Move the User model to the Auth module's model directory
mv app/Models/User.php Modules/Auth/Models/User.php

11)Update the namespace of the User model. Open Modules/Auth/Models/User.php and modify the namespace to:

12) Update the config/auth.php file to use the Auth module's User model. In the config/auth.php file, locate the 'providers' configuration and modify it as follows:



 'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => Modules\Auth\Models\User::class,
        ],


Enter fullscreen mode Exit fullscreen mode

13) Open the RegisterController and add the code below in it to create the method to register a user:



use Illuminate\Support\Facades\Hash;

class RegisterController extends Controller
{

    public function register(Request $request)
    {
        $validatedData = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:8',
        ]);

        $user = User::create([
            'name' => $validatedData['name'],
            'email' => $validatedData['email'],
            'password' => Hash::make($validatedData['password']),
        ]);

        $token = $user->createToken('auth_token')->plainTextToken;

        return response()->json([
            'access_token' => $token,
            'token_type' => 'Bearer',
        ]);
    }
}



Enter fullscreen mode Exit fullscreen mode

First, we validate the incoming request to make sure all required variables are present. Once a user has been created, we create a new personal access token using the createToken() method and give the token a name of auth_token, we call the plainTextToken on the instance to access the plain-text value of the token. Finally, we return a JSON response containing the generated token as well as the type of the token.

Image description

14) Then add the login() method inside of the LoginController:



use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{

    public function login(Request $request)
    {
        if (!Auth::attempt($request->only('email', 'password'))) {
            return response()->json([
                'message' => 'Invalid login details'
            ], 401);
        }

        $user = User::where('email', $request['email'])->firstOrFail();
        $token = $user->createToken('auth_token')->plainTextToken;

        return response()->json([
            'user'         => $user,
            'access_token' => $token,
            'token_type'   => 'Bearer',
        ]);
    }
}



Enter fullscreen mode Exit fullscreen mode

Image description

15) forgot password

  • make mail

php artisan module:make-mail ResetPassword Auth



<?php

namespace Modules\Auth\App\Emails;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class ResetPassword extends Mailable
{
    use Queueable, SerializesModels;

    public $data;

    public function __construct($data)
    {
        $this->data = $data;
    }

    public function build()
    {
        return $this->subject('Mail from ashrakt')->view("auth::mails.resetPassword");
    }
}



Enter fullscreen mode Exit fullscreen mode
  • make view


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Authentication</title>
</head>

<body>
    <h3>code : {{ $data }}</h3>
</body>

</html>


Enter fullscreen mode Exit fullscreen mode
  • Forgot Password Controller


<?php

namespace Modules\Auth\App\Http\Controllers;

use Carbon\Carbon;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Modules\Auth\Models\User;
use Illuminate\Support\Facades\DB;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use Modules\Auth\App\Emails\ResetPassword;


class ForgotPasswordController extends Controller
{

    public function sendResetLinkEmail(Request $request)
    {
        $request->validate([
            'email' => 'required|email|exists:users',
        ]);

        $token = Str::random(64);
        DB::table('password_reset_tokens')->insert([
            'email' => $request->email,
            'token' => $token,
            'created_at' => Carbon::now()
        ]);

        Mail::to($request->email)->send(new ResetPassword($token));


        return response()->json(['message' => 'We have e-mailed your password reset link!']);
    }



    public function submitResetPasswordForm(Request $request)
    {
        $request->validate([
            'email' => 'required|email|exists:users',
            'token' => 'required',
            'password' => 'required|string|min:6|confirmed',
            'password_confirmation' => 'required'
        ]);

        $updatePassword = DB::table('password_reset_tokens')
            ->where([
                'email' => $request->email,
                'token' => $request->token
            ])->first();

        if (!$updatePassword) {
            return response()->json(['message' => 'Invalid token!']);
        }

        User::where('email', $request->email)
            ->update(['password' => Hash::make($request->password)]);


        DB::table('password_reset_tokens')->where(['email' => $request->email])->delete();

        return response()->json(['message' => 'Your password has been changed!']);
    }
}



Enter fullscreen mode Exit fullscreen mode

Image description

Image description

  • env file


MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME=####
MAIL_PASSWORD=####
MAIL_ENCRYPTION=tls
MAIL_MAILER=smtp
MAIL_FROM_ADDRESS=####
MAIL_FROM_NAME="${APP_NAME}"


Enter fullscreen mode Exit fullscreen mode

16) Reset password



<?php

namespace Modules\Auth\App\Http\Controllers;

use Illuminate\Http\Request;
use Modules\Auth\Models\User;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;


class ResetPasswordController extends Controller
{

    public function resetPassword(Request $request)
    {
        $request->validate([
            'email' => 'required|email|exists:users',
            'password' => 'required|string|min:6|confirmed',
            'password_confirmation' => 'required'
        ]);

        User::where('email', $request->email)
            ->update(['password' => Hash::make($request->password)]);

        return response()->json(['message' => 'Your password has been changed!']);
    }
}



Enter fullscreen mode Exit fullscreen mode

Image description

17) logout



<?php

namespace Modules\Auth\App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Laravel\Sanctum\PersonalAccessToken;

class LogoutController extends Controller
{

    public function logout(Request $request)
    {
        $logout = PersonalAccessToken::findToken($request->bearerToken())->delete();

        if ($logout) {
            return response()->json([
                'message' => 'Successfully logged out.',
            ]);
        } else {
            return response()->json([
                'message' => 'Error occurred while logging out.',
            ]);
        }
    }
}



Enter fullscreen mode Exit fullscreen mode

Image description

Top comments (0)