【Laravel7でユーザー認証_10】マルチ認証機能で作成した管理者のパスワード変更・リセット機能を追加する

#はじめに
Laravelのユーザー認証機能に、管理者権限を追加（マルチ認証機能）した後、管理者のパスワードを変更・リセットする機能を追加する手順をまとめます。

# 環境

XAMPP環境でLaravelが使えるように設定してあります。

- Windows10 Pro 64bit
- PHP 7.3.18
- Laravel 7.12.0
- MariaDB 10.1.32

また、Laravelプロジェクトは以下の手順で作業を進めており、管理者はすでに作成されている状態です。

- [【Laravel7でユーザー認証_1】基本のき](https://qiita.com/crosawassant/items/bf3982666b6333bcb8c8)
- [【Laravel7でユーザー認証_2】ユーザー認証を日本語化](https://qiita.com/crosawassant/items/d1f4c5c93f30afa9eb65)
- [【Laravel7でユーザー認証_3】ユーザー認証をメールアドレスからユーザー名に変更する](https://qiita.com/crosawassant/items/2464db8a0fe1c603401a)
- [【Laravel7でユーザー認証_4】パスワード変更フォームを作成する](https://qiita.com/crosawassant/items/04242c8d7a12346dcc20)
- [【Laravel7でユーザー認証_5】ユーザーを倫理削除（SoftDelete）する](https://qiita.com/crosawassant/items/a6e3e9b1aedf566b2d27)
- [【Laravel7でユーザー認証_6】ユーザーの情報を表示・変更する設定画面を作成する](https://qiita.com/crosawassant/items/d8b434f0bc98455165b4)
- [【Laravel7でユーザー認証_7】会員登録時にメール認証を行う](https://qiita.com/crosawassant/items/eed947b1e516d864fc6c)
- [【Laravel7でユーザー認証_8】メールアドレス変更時にメール認証を行う](https://qiita.com/crosawassant/items/018b29ab770c0a373bc9)
- [【Laravel7でユーザー認証_9】マルチ認証機能を使って管理者を作成する](https://qiita.com/drafts/549e7ea9615fcd9ad68e/edit)

#パスワード変更 実装手順

##コントローラの作成
パスワード変更用のコントローラを作成します。
今回は、ユーザー用に作成した `Auth/ChangePasswordController` を `Admin/Auth` ディレクトリの中にコピーして利用します。

namespaceをAdmin用に書き換えます。
また、パスワード変更の処理はadminログインを必須としたいので、コンストラクトでチェックするように指定します。

```diff:app/Http/Controllers/Admin/Auth/ChangePasswordController.php
  <?php
  
- namespace App\Http\Controllers\Auth;
+ namespace App\Http\Controllers\Admin\Auth;

  use App\Http\Controllers\Controller;
  use App\Http\Requests\ChangePasswordRequest;
  use Illuminate\Support\Facades\Auth;

  class ChangePasswordController extends Controller
  {
      public function __construct()
      {
-         $this->middleware('auth');
+         $this->middleware('auth:admin');
          $this->middleware('verified');
      }

      public function showChangePasswordForm()
      {
          return view('auth\passwords\change');
      }

      public function changePassword(ChangePasswordRequest $request)
      {
          //ValidationはChangePasswordRequestで処理
          //パスワード変更処理
          $user = Auth::user();
          $user->password = bcrypt($request->get('password'));
          $user->save();

          //homeにリダイレクト
          return redirect()->route('home')->with('status', __('Your password has been changed.'));
    }
  }
```

##ルーティングの設定
以下の仕様で、ルーティングを設定します。

通常のアクセス（GET）の場合は、「Admin/Auth/ChangePasswordController」コントローラの「showChangePasswordForm」メソッドを実行。
パスワードを変更の処理（POST）の場合は、「Admin/Auth/ChangePasswordController」コントローラの「changePassword」メソッドを実行。
それぞれのルーティングには、「admin.password.form」、「admin.password.change」という名前を付けました。

```diff:/routes/web.php
  Route::namespace('Admin')->prefix('admin')->name('admin.')->group(function() {
      Route::get('home', 'HomeController@index')->name('home');

      Route::get('login', 'Auth\LoginController@showLoginForm')->name('login');
      Route::post('login', 'Auth\LoginController@login');

      Route::post('logout', 'Auth\LoginController@logout')->name('logout');
+
+     Route::get('/setting/password', 'Auth\ChangePasswordController@showChangePasswordForm')->name('password.form');
+     Route::post('/setting/password', 'Auth\ChangePasswordController@changePassword')->name('password.change');
  });
```

##viewの作成

viewは、`auth/passwords/change.blade.php` をコピーして利用します。
formのアクション先は、ルーティングで付けた「admin.password.change」という名前を使います。

```php:resources/views/admin/auth/passwords/change.blade.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Change Password') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('admin.password.change') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="current_password" class="col-md-4 col-form-label text-md-right">{{ __('Current Password') }}</label>

                            <div class="col-md-6">
                                <input id="current_password" type="password" class="form-control @error('current_password') is-invalid @enderror" name="current_password" required autocomplete="new_password">

                                @error('current_password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('New Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">

                                @error('password')
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $message }}</strong>
                                    </span>
                                @enderror
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm New Password') }}</label>

                            <div class="col-md-6">
                                <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new_password">
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Change Password') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
```

###viewを指定

コントローラの `showChangePasswordForm` メソッドで、作成したviewを指定します。

```diff:app/Http/Controllers/Admin/Auth/ChangePasswordController.php
      public function showChangePasswordForm()
      {
-         return view('auth\passwords\change');
+         return view('admin\auth\passwords\change');
      }
```

##パスワード変更の処理
###バリデーションチェック
####FormRequest の設定
ユーザーのFormRequest　`app/Http/Requests/ChangePasswordRequest.php` を`app/Http/Requests/Admin/ChangePasswordRequest.php` に複製します。

```diff:app/Http/Request/Admin/ChangePasswordRequest.php
  <?php

- namespace App\Http\Requests;
+ namespace App\Http\Requests\Admin;

  use Illuminate\Foundation\Http\FormRequest;
  use Illuminate\Contracts\Validation\Validator;
  use Illuminate\Http\Exceptions\HttpResponseException;
  use Illuminate\Support\Facades\Auth;
  use Illuminate\Support\Facades\Hash;

  class ChangePasswordRequest extends FormRequest
  {
      /**
       * Determine if the user is authorized to make this request.
       *
       * @return bool
       */
      public function authorize()
      {
          return true;
      }

      /**
       * Get the validation rules that apply to the request.
       *
       * @return array
       */
      public function rules()
      {
          return [
              'current_password' => ['required', 'string', 'min:8'],
              'password' => ['required', 'string', 'min:8', 'confirmed']
          ];
      }

      public function withValidator(Validator $validator) {
           $validator->after(function ($validator) {
               $auth = Auth::user();
             
               //現在のパスワードと新しいパスワードが合わなければエラー
               if (!(Hash::check($this->input('current_password'), $auth->password))) {
                   $validator->errors()->add('current_password', __('The current password is incorrect.'));
               }
           });
       }
  }
```

###コントローラに読み込み
FormRequest をコントローラから読み込むように修正します。
また、パスワード変更時のリダイレクト先が管理者のhomeになるよう変更します。

```diff:app/Http/Controllers/Admin/Auth/ChangePasswordController.php
  <?php
  
  namespace App\Http\Controllers\Admin\Auth;

  use App\Http\Controllers\Controller;
- use App\Http\Requests\ChangePasswordRequest;
+ use App\Http\Requests\Admin\ChangePasswordRequest;
  use Illuminate\Support\Facades\Auth;

===（中略）===

      public function changePassword(ChangePasswordRequest $request)
      {
          //ValidationはChangePasswordRequestで処理
          //パスワード変更処理
          $user = Auth::user();
          $user->password = bcrypt($request->get('password'));
          $user->save();

          //homeにリダイレクト
-         return redirect()->route('home')->with('status', __('Your password has been changed.'));
+         return redirect()->route('admin.home')->with('status', __('Your password has been changed.'));
    }
  }
```

##ヘッダからリンクする

ログインした後、右上に表示されるメニューの中に、パスワード変更のリンクを張っておきます。

```diff:resource/views/layouts/app.blade.php
                                  <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
                                      <a class="dropdown-item" href="{{ route('admin.logout') }}"
                                         onclick="event.preventDefault();
                                                       document.getElementById('logout-form').submit();">
                                          {{ __('Logout') }}
                                      </a>

                                      <form id="logout-form" action="{{ route('admin.logout') }}" method="POST" style="display: none;">
                                          @csrf
                                      </form>
+
+                                     <a class="dropdown-item" href="{{ route('admin.password.form') }}">
+                                         {{ __('Change Password') }}
+                                     </a>
                                  </div>
```

##動作確認
管理者のパスワード変更画面にアクセスして、希望の動作になるか確認します。
前回、secretという8桁以下のパスワードで設定したため、バリデーションがとおらなくなってしまいました。
tinkerを使ってDBを操作して、まずは直接パスワードを変更することにします。

```
$ php artisan tinker
$ \DB::table('admins')->where('id', 1)->update(['password' => \Hash::make('secretpassword')]);
```

これでパスワードが「secretpassword」に変更されました。
現在のパスワード欄に「secretpassword」、新しいパスワード欄に任意の文字列を入力して動作を確認します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262236/72d6186a-9f27-37dc-9515-fa45241b31c7.png" width="600">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262236/9889d4a5-bba6-2a54-8ea9-dd02145c6b07.png" width="600">

#パスワードリセット 実装手順

##ルーティングの定義

管理者のパスワードリセットについて、`Auth::routes()` を使うと、認証系に必要な定義を自動で追加してくれます。
管理者用は登録部分は利用しないことにするので、オプションで以下のように指定します。

```diff:routes/web.php
  Route::namespace('Admin')->prefix('admin')->name('admin.')->group(function() {
      Route::get('home', 'HomeController@index')->name('home');

      Route::get('login', 'Auth\LoginController@showLoginForm')->name('login');
      Route::post('login', 'Auth\LoginController@login');

      Route::post('logout', 'Auth\LoginController@logout')->name('logout');

      Route::get('/setting/password', 'Auth\ChangePasswordController@showChangePasswordForm')->name('password.form');
      Route::post('/setting/password', 'Auth\ChangePasswordController@changePassword')->name('password.change');
+
+     Auth::routes([
+         'register' => false,
+         'reset'    => true,
+         'verify'   => false
+     ]);
  });
```

`php artisan route:list` をしてみると、admin.password.email や admin.password.update といったパスワードに関するルーティングが追加されているのが分かります。
![Laravel-admin-resetpassword-01.fw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262236/1e334bcd-73ce-99f9-e1d2-677ac30529c6.png)

このルーティングに沿って、コントローラを作成していきます。

##コントローラの作成

ユーザー用のパスワードリセット用のコントローラ `app/Http/Controllers/Auth/ForgotPasswordController.php` と `app/Http/Controllers/Auth/ResetPasswordController.php` を、管理者用として `app/Http/Controllers/Admin/Auth/` 以下にコピーします。

コピー後、namespaceやリダイレクト先を管理者向けに変更します。

```diff:app/Http/Controllers/Admin/Auth/ForgotPasswordController.php
  <?php
  
- namespace App\Http\Controllers\Auth;
+ namespace App\Http\Controllers\Admin\Auth;

  use App\Http\Controllers\Controller;
  use Illuminate\Foundation\Auth\SendsPasswordResetEmails;

  class ForgotPasswordController extends Controller
  {
      /*
      |--------------------------------------------------------------------------
      | Password Reset Controller
      |--------------------------------------------------------------------------
      |
      | This controller is responsible for handling password reset emails and
      | includes a trait which assists in sending these notifications from
      | your application to your users. Feel free to explore this trait.
      |
      */

      use SendsPasswordResetEmails;
  }
```

```diff:app/Http/Controllers/Admin/Auth/ResetPasswordController.php
  <?php

- namespace App\Http\Controllers\Auth;
+ namespace App\Http\Controllers\Admin\Auth;

  use App\Http\Controllers\Controller;
  use App\Providers\RouteServiceProvider;
  use Illuminate\Foundation\Auth\ResetsPasswords;

  class ResetPasswordController extends Controller
  {
      /*
      |--------------------------------------------------------------------------
      | Password Reset Controller
      |--------------------------------------------------------------------------
      |
      | This controller is responsible for handling password reset requests
      | and uses a simple trait to include this behavior. You're free to
      | explore this trait and override any methods you wish to tweak.
      |
      */

      use ResetsPasswords;

      /**
       * Where to redirect users after resetting their password.
       *
       * @var string
       */
-     protected $redirectTo = RouteServiceProvider::HOME;
+     protected $redirectTo = RouteServiceProvider::ADMIN_HOME;
  }
```

##viewの作成

ユーザー用のパスワードリセット用のview `resources/views/auth/passwords/reset.blade.php` と `resources/views/auth/passwords/email.blade.php` を、管理者用として `app/Http/Controllers/Admin/Auth/` 以下にコピーします。
コピー後、レイアウトやformの送信先を変更します。

```diff:resources/views/auth/passwords/reset.blade.php
- @extends('layouts.app')
+ @extends('layouts.admin.app')

  @section('content')
  <div class="container">
      <div class="row justify-content-center">
          <div class="col-md-8">
              <div class="card">
                  <div class="card-header">{{ __('Reset Password') }}</div>

                  <div class="card-body">
-                     <form method="POST" action="{{ route('password.update') }}">
+                     <form method="POST" action="{{ route('admin.password.update') }}">
                          @csrf

                          <input type="hidden" name="token" value="{{ $token }}">

                          <div class="form-group row">
                              <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>

                               <div class="col-md-6">
                                  <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus>

                                  @error('email')
                                      <span class="invalid-feedback" role="alert">
                                          <strong>{{ $message }}</strong>
                                      </span>
                                  @enderror
                              </div>
                          </div>

                          <div class="form-group row">
                              <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>

                              <div class="col-md-6">
                                  <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="new-password">

                                  @error('password')
                                      <span class="invalid-feedback" role="alert">
                                          <strong>{{ $message }}</strong>
                                      </span>
                                  @enderror
                              </div>
                          </div>

                          <div class="form-group row">
                              <label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>

                              <div class="col-md-6">
                                  <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required autocomplete="new-password">
                              </div>
                          </div>

                          <div class="form-group row mb-0">
                              <div class="col-md-6 offset-md-4">
                                  <button type="submit" class="btn btn-primary">
                                      {{ __('Reset Password') }}
                                  </button>
                              </div>
                          </div>
                      </form>
                  </div>
              </div>
          </div>
      </div>
  </div>
  @endsection
```

```diff:resources/views/auth/passwords/email.blade.php
- @extends('layouts.app')
+ @extends('layouts.admin.app')

  @section('content')
  <div class="container">
      <div class="row justify-content-center">
          <div class="col-md-8">
              <div class="card">
                  <div class="card-header">{{ __('Reset Password') }}</div>
  
                  <div class="card-body">
                      @if (session('status'))
                          <div class="alert alert-success" role="alert">
                              {{ session('status') }}
                          </div>
                      @endif
+
-                     <form method="POST" action="{{ route('password.email') }}">
+                     <form method="POST" action="{{ route('admin.password.email') }}">
                          @csrf
  
                          <div class="form-group row">
                              <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>

                              <div class="col-md-6">
                                  <input id="email" type="email" class="form-control @error('email') is-invalid @enderror" name="email" value="{{ old('email') }}" required autocomplete="email" autofocus>

                                  @error('email')
                                      <span class="invalid-feedback" role="alert">
                                          <strong>{{ $message }}</strong>
                                      </span>
                                  @enderror
                              </div>
                          </div>

                          <div class="form-group row mb-0">
                              <div class="col-md-6 offset-md-4">
                                  <button type="submit" class="btn btn-primary">
                                      {{ __('Send Password Reset Link') }}
                                  </button>
                              </div>
                          </div>
                      </form>
                  </div>
              </div>
          </div>
      </div>
  </div>
  @endsection
```

##管理者用パスワードリセットトークン保存テーブル作成

ユーザー用のパスワードリセットトークン保存テーブル `password_resets` と、管理者用のものを分けるため、`admin_password_resets` というテーブルを新たに作成します。

```
php artisan make:migration create_admin_password_resets_table 
```

`日付_create_admin_password_resets_table.php` の中身は、 `日付_create_password_resets_table.php` を参考にします。

```database/migrations/日付_create_admin_password_resets_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateAdminPasswordResetsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('admin_password_resets', function (Blueprint $table) {
            $table->string('email')->index();
            $table->string('token');
            $table->timestamp('created_at')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('admin_password_resets');
    }
}
```

```
php artisan migrate
```

##パスワードブローカーの設定

管理者がパスワードリセット時に `admin_password_resets` テーブルを使用するため、`config/auth.php` で、管理者用のパスワードブローカーを設定します。

```diff:config/auth.php
      'passwords' => [
          'users' => [
              'provider' => 'users',
              'table' => 'password_resets',
              'expire' => 60,
              'throttle' => 60,
        'admins' => [
            'provider' => 'admins',
            'table' => 'admin_password_resets',
            'expire' => 60,
            'throttle' => 60,
        ],
          ],
      ],
```

configファイルを変更したので、キャッシュをクリアします。
```
php artisan config:cache
```

##コントローラの修正

パスワードリセットのボタンを押すと、`ForgotPasswordController` の `showLinkRequestForm()` が実行されます。現状だと、`SendsPasswordResetEmails`（`vendor/laravel/ui/auth-backend/SendsPasswordResetEmails.php`） に処理がまとめられているため、このままだと管理者もユーザーと同じ挙動になってしまいます。
管理者は管理者向けの処理になるよう、`ForgotPasswordController` 内で各メソッドをオーバーライドします。

```diff:app\Http\Controllers\Admin\Auth\ForgotPasswordController.php
  <?php

  namespace App\Http\Controllers\Admin\Auth;

  use App\Http\Controllers\Controller;
  use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
+ use Illuminate\Support\Facades\Password;

  class ForgotPasswordController extends Controller
  {
      /*
      |--------------------------------------------------------------------------
      | Password Reset Controller
      |--------------------------------------------------------------------------
      |
      | This controller is responsible for handling password reset emails and
      | includes a trait which assists in sending these notifications from
      | your application to your users. Feel free to explore this trait.
      |
      */

      use SendsPasswordResetEmails;
+
+     public function showLinkRequestForm()
+     {
+         return view('admin.auth.passwords.email');
+     }
+
+     public function broker()
+     {
+         return Password::broker('admins');
+     }
}
```

```diff:app\Http\Controllers\Admin\Auth\ResetPasswordController.php
  <?php
  
  namespace App\Http\Controllers\Admin\Auth;

  use App\Http\Controllers\Controller;
  use App\Providers\RouteServiceProvider;
  use Illuminate\Foundation\Auth\ResetsPasswords;
+ use Illuminate\Http\Request;
+ use Illuminate\Support\Facades\Password;

  class ResetPasswordController extends Controller
  {

  ==（中略）==

      protected $redirectTo = RouteServiceProvider::ADMIN_HOME;
+
+     public function showResetForm(Request $request, $token = null)
+     {
+         return view('admin.auth.passwords.reset')->with(
+             ['token' => $token, 'email' => $request->email]
+         );
+     }
+
+     public function broker()
+     {
+         return Password::broker('admins');
+     }
}

```

##リセットメールの変更

ここまでで一旦動作確認してみると、パスワードリセットメールは届きますが、本文中のURLがユーザー用のURLのままです。
管理者用の通知メールを作成し、そちらを利用するようにします。

###Notificationの作成

`php artisan make:notification` コマンドを実行します。

```
php artisan make:notification AdminResetPasswordNotification
```
`app/Notifications/AdminResetPasswordNotification.php` が作成されるので、内容を修正します。
メールの送信は、 `vendor/laravel/framework/src/Illuminate/Auth/Notifications/ResetPassword.php` の中の `toMail()` を使っているので、このメソッドをコピーしてURL部分だけ管理者用に変更しました。

```diff:app/Notifications/AdminResetPasswordNotification.php
  <?php

  namespace App\Notifications;

  use Illuminate\Bus\Queueable;
  use Illuminate\Contracts\Queue\ShouldQueue;
  use Illuminate\Notifications\Messages\MailMessage;
  use Illuminate\Notifications\Notification;
+ use Illuminate\Support\Facades\Lang;

  class AdminResetPasswordNotification extends Notification
  {
      use Queueable;
+     public static $toMailCallback;
+     public static $createUrlCallback;

      /**
       * Create a new notification instance.
       *
       * @return void
       */
-     public function __construct()
+     public function __construct($token)
      {
+         $this->token = $token;
      }

  ===（中略）===

      public function toMail($notifiable)
      {
          return (new MailMessage)
-                     ->line('The introduction to the notification.')
-                     ->action('Notification Action', url('/'))
-                     ->line('Thank you for using our application!');
+         if (static::$toMailCallback) {
+             return call_user_func(static::$toMailCallback, $notifiable, $this->token);
+         }
+ 
+         if (static::$createUrlCallback) {
+             $url = call_user_func(static::$createUrlCallback, $notifiable, $this->token);
+         } else {
+             $url = url(route('password.reset', [
+                 'token' => $this->token,
+                 'email' => $notifiable->getEmailForPasswordReset(),
+             ], false));
+         }
+ 
+         return (new MailMessage)
+             ->subject(Lang::get('Reset Password Notification'))
+             ->line(Lang::get('You are receiving this email because we received a password reset request for your account.'))
+             ->action(Lang::get('Reset Password'), $url)
+             ->line(Lang::get('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.'.config('auth.defaults.passwords').'.expire')]))
+             ->line(Lang::get('If you did not request a password reset, no further action is required.'));
        }
```

###Adminモデルの修正

管理者は `AdminResetPasswordNotification` を使うように、Adminモデルを修正します。

```diff:app/Admin.php
  <?php

  namespace App;

  use Illuminate\Contracts\Auth\MustVerifyEmail;
  use Illuminate\Foundation\Auth\User as Authenticatable;
  use Illuminate\Notifications\Notifiable;
  use Illuminate\Database\Eloquent\Model;
  use Illuminate\Database\Eloquent\SoftDeletes;
+ use App\Notifications\AdminResetPasswordNotification;

  class Admin extends Authenticatable implements MustVerifyEmail
  {

  ===（中略）===
+
+     public function AdminResetPasswordNotification($token)
+     {
+             $this->notify(new AdminResetPasswordNotification($token));
+     }
  }
```

#おわりに
ここまでで、管理者のログイン・パスワード変更・パスワードリセットができるようになりました。
今回、管理者の登録・削除は作成しませんでしたが、同じようにして作成できそうです。
ユーザー認証についてのまとめは、ここまでで一旦完了としたいと思います。

#参考サイト
- [【Laravel】パスワードなどハッシュ化した文字列を生成したい場合 | ハトらぼ](https://hatolabo.com/programming/%E3%80%90laravel%E3%80%91%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%81%AA%E3%81%A9%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E5%8C%96%E3%81%97%E3%81%9F%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E7%94%9F)
- [Laravel・データベースのデータ操作（追加／変更／削除）する全実例 &#8211; console dot log](https://blog.capilano-fw.com/?p=699)
- [Laravel 7.xでマルチ認証機能を作成してみた 2 〜ユーザ登録・パスワード再設定〜 - arms inc. Engineers&#39; Blog](https://tech.arms-soft.co.jp/entry/2020/05/27/090000)
- [通知 7.x Laravel](https://readouble.com/laravel/7.x/ja/notifications.html)
- [Laravel5.7のMulti Auth環境で正しくパスワードリセットを動作させる - Qiita](https://qiita.com/zaburo/items/ef284d3d2f52dcc0c678#resetpasswordcontrollerphp)