create an Auth module with laravel using nwidart/laravel-modules package
Published: 2024-02-29 07:33:05

**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/"
    }
  }
}
```

-  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
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2n58su5t7gb3i7puqlvw.PNG)


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

```

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']);
});



```

8) add auth table in Migrations folder module

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/anxuxkg4cah3n3ysmxc9.PNG)


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,
        ],
```

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',
        ]);
    }
}

```
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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gv59j3re41kg23g9nmxj.PNG)
 

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',
        ]);
    }
}

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nll92fbee2d6v8teqexi.PNG)


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");
    }
}

```

-  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>
```

- 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!']);
    }
}

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l2ys0jnmfj1o9hmico3n.PNG)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qg95cm7fcyxoc0wka2wf.PNG)


- 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}"
```


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!']);
    }
}

```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pgx3119acfi7yvcs8pn9.PNG)


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.',
            ]);
        }
    }
}

```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sqn4q31bxczma0e1fp0f.PNG)