Laravel6でマルチ認証(管理者/ユーザー)の基本設定


(コントローラー構成イメージ)

```
app\Http\Controllers
|   (一般ページ〜)
├── HomeController.php
├── CompanyController.php
└── Admin(管理者ダッシュボード〜)
|   ├ Auth
|   |  ├ LoginController.php
|   |  └ RegisterController.php
|   ├ DashboardController.php
|   └ ...
└── User(会員ページ〜)
    ├ Auth
    |  ├ LoginController.php
    |  └ RegisterController.php
    ├ DashboardController.php
    └ ...
```


## Controllerのディレクトリ準備

■Admin/Usreディレクトリの作成

```
$ mkdir ./app/Http/Controllers/{User,Admin}
```

■元のAuthディレクトリをUser以下に移動

```
$ mv ./app/Http/Controllers/Auth ./app/Http/Controllers/User/Auth
```

■AuthディレクトリをコピーしてAdmin以下にも配置

```
$ cp -r ./app/Http/Controllers/User/Auth  ./app/Http/Controllers/Admin/Auth
```

■namespaceの変更: User側のController

```
namespace App\Http\Controllers\User\Auth;
```

■namespaceの変更: Admin側のController

```
namespace App\Http\Controllers\Admin\Auth;
```




## Migrationの作成

```
$ php artisan make:model Admin -m
```

(database/migrations以下にMigrationファイルが生成されます)

```
database/migrations
├── 2014_10_12_000000_create_users_table.php
├── 2014_10_12_100000_create_password_resets_table.php
├── 2019_08_19_000000_create_failed_jobs_table.php
└── 2020_11_29_015635_create_admins_table.php
```

AdminテーブルのMigrationファイルの編集  
Schema::create部分をUserモデル参考に変更します。

```2020_11_29_015635_create_admins_table.php
        Schema::create('admins', function (Blueprint $table) {
	        $table->bigIncrements('id');
	        $table->string('name');
	        $table->string('email')->unique();
	        $table->timestamp('email_verified_at')->nullable();
	        $table->string('password');
	        $table->rememberToken();
	        $table->timestamps();
        });
```

migrationを実行します。(tableが作成されます)

```
$ php artisan migrate
```



## Seederの準備

■テストユーザー作成のためのシーダーを準備

```
$ php artisan make:seeder UsersTableSeeder
$ php artisan make:seeder AdminTableSeeder
```

■シーダーで作成する、ユーザー/管理者のデータを設定します。

```database/seeds/UsersTableSeeder.php
<?php
use Illuminate\Database\Seeder;
class UsersTableSeeder extends Seeder
{
	public function run()
	{
		DB::table('users')->insert([
			'name' => 'member',
			'email' => 'member@example.com',
			'password' => Hash::make('pass'),
			'remember_token' => Str::random(10),
		]);
	}
}
```

```database/seeds/AdminsTableSeeder.php
<?php
use Illuminate\Database\Seeder;

class AdminTableSeeder extends Seeder
{
    public function run()
    {
	    DB::table('admins')->insert([
		    'name' => 'kanri',
		    'email' => 'admin@example.com',
		    'password' => Hash::make('word'),
		    'remember_token' => Str::random(10),
	    ]);
    }
}
```


```database/seeds/DatabaseSeeder.php
<?php
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
	public function run()
	{
		$this->call([
			UsersTableSeeder::class,
			AdminsTableSeeder::class,
		]);
	}
}
```

準備ができたところでSeedを実行します。(データがはいります)

```
$ php artisan db:seed
```



## Modelの準備

User.phpを参考にAdmin.phpを編集します。(Class名以外はUserと一緒)

```app/Admin.php
<?php

namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class Admin extends Authenticatable
{
	use Notifiable;
	
	/**
	 * The attributes that are mass assignable.
	 *
	 * @var array
	 */
	protected $fillable = [
		'name', 'email', 'password',
	];
	
	/**
	 * The attributes that should be hidden for arrays.
	 *
	 * @var array
	 */
	protected $hidden = [
		'password', 'remember_token',
	];
	
	/**
	 * The attributes that should be cast to native types.
	 *
	 * @var array
	 */
	protected $casts = [
		'email_verified_at' => 'datetime',
	];
}
```



## 管理者(Admin)認証設定:config/auth.php

■デフォルトのguardをwebからusersに変更

```
    'defaults' => [
        'guard' => 'user',
        'passwords' => 'users',
    ],
```

■guardsのwebをuserに変更/adminを追加

```
    'guards' => [
        'user' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
    ],
```

■providersにadminsを追加

```
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Admin::class,
        ],
    ],
```

■passwordsにadminを追加

```
    'passwords' => [
	    'users' => [
		    'provider' => 'users',
		    'table' => 'password_resets',
		    'expire' => 60,
		    'throttle' => 60,
	    ],
	    'admins' => [
		    'provider' => 'admins',
		    'table' => 'password_resets',
		    'expire' => 60,
		    'throttle' => 60,
	    ],
    ],
```


# 〜(長いので一旦)User側の認証をまず作ります〜

## ログイン後のコントローラーの準備

ログイン後のダッシュボードのコントローラーを作成。

```
$ php artisan make:controller User/DashboardController
```

```User/DashboardController.php
<?php
namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class DashboardController extends Controller
{
	public function index()
	{
		return view('user.index');
	}
}
```


## ルーティング設定

以下のルーティングの設定を行います。

- トップページのviewの変更
- Userのプリフィックスの設定
- ルーティングにAuthの制限

```routes/web.php
<?php
Route::get('/', function () {
    return view('index');
});
Route::namespace('User')->prefix('user')->name('user.')->group(function () {
	Auth::routes();
	Route::middleware('auth:user')->group(function () {
		Route::get('/', 'DashboardController@index')->name('index');
	});
});
```


## ログイン前後のリダイレクト先の設定

以下の3ケースについて設定していきます。

1. ログイン未:制限ページへのアクセス
2. ログイン済:ログインページへのアクセス
3. ログイン後:リダイレクト先ページ


### 1.ログイン未:制限ページへのアクセス

ルートのnameがuser/adminの場合で分岐しています。

```app/Http/Middleware/Authenticate.php
<?php
namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Support\Facades\Route;

class Authenticate extends Middleware
{
    /**
     * Get the path the user should be redirected to when they are not authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string|null
     */
    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {
        	if(Route::is('user.*')){
		        return route('user.login');	
	        }else if(Route::is('admin.*')){
		        return route('admin.login');
	        }else{
		        abort(403, 'Unauthorized action.');
	        }
        }
    }
}
```

### 2.ログイン済:ログインページへのアクセス

guardのタイプでリダイレクト先を変更

```app/Http/Middleware/RedirectIfAuthenticated.php
<?php

namespace App\Http\Middleware;

use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */

    public function handle($request, Closure $next, $guard = null)
    {
	
	    if (Auth::guard($guard)->check()) {
		    $home = '';
	    	switch($guard){
			    case 'user':
				    $home = RouteServiceProvider::HOME;
				    break;
			    case 'admin':
				    $home = RouteServiceProvider::HOME_ADMIN;
				    break;
			    default:
				    $home = RouteServiceProvider::HOME;
		    }
		    return redirect($home);
	    }
        return $next($request);
    }
}
```


### 3. ログイン後:リダイレクト先ページ

User用のHOMEを変更しています。  
Admin用のHOME_ADMINを追記しています。

```app/Providers/RouteServiceProvider.php
    public const HOME = '/user';
    public const HOME_ADMIN = '/admin';
```




## LoginControllerの設定

パスの変更などがあるため以下をOverrideして微調整します。

- showLoginForm()をOverride
- loggedOut()をOverride

```app/Http/Controllers/User/Auth/LoginController.php
<?php

namespace App\Http\Controllers\User\Auth;

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

class LoginController extends Controller
{
 
    use AuthenticatesUsers;

    protected $redirectTo = RouteServiceProvider::HOME;

    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
    
	public function showLoginForm()
	{
		return view('user.auth.login');
	}
	protected function loggedOut(Request $request)
	{
		return redirect(route('user.login'));
	}
}

```


## RegisterControllerの設定



- ネームスペースを変更
- showRegistrationForm()をOverride


```app/Http/Controllers/User/Auth/RegisterController.php
<?php

namespace App\Http\Controllers\User\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use App\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class RegisterController extends Controller
{

    use RegistersUsers;
    
    protected $redirectTo = RouteServiceProvider::HOME;
    
    public function __construct()
    {
        $this->middleware('guest');
    }

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }
	
    public function showRegistrationForm()
    {
        return view('user.auth.register');
    }
}

```


## パスワードリセットURLの設定

パスワードリセットのURLを  ``` http://example.com/user/password/reset/{token} ``` のように/user/以下に配置したいためメールを生成しているクラスを変更します。

■リセットメール送信Notification作成

```
$ php artisan make:notification PasswordResetUserNotification
```

■app/Notifications/PasswordResetUserNotification.php  
※ResetPasswordを継承してtoMailのみをオーバーライドしています。

```app/Notifications/PasswordResetUserNotification.php 
<?php

namespace App\Notifications;

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

class PasswordResetUserNotification extends ResetPassword
{
	
	public function toMail($notifiable)
	{
		if (static::$toMailCallback) {
			return call_user_func(static::$toMailCallback, $notifiable, $this->token);
		}
		
		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(route('user.password.reset', ['token' => $this->token, 'email' => $notifiable->getEmailForPasswordReset()], false)))
			->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.'));
	}
}
```

■app/User.phpでsendPasswordResetNotification(Illuminate\Auth\Passwords\CanResetPassword)のオーバーライド

```app/User.php
	public function sendPasswordResetNotification($token)
	{
		$this->notify(new PasswordResetUserNotification($token));
	}
```



## パスワードリセットフォームの表示設定

- showLinkRequestForm()のオーバーライド

```app/Http/Controllers/User/Auth/ForgotPasswordController.php 
<?php

namespace App\Http\Controllers\User\Auth;

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

class ForgotPasswordController extends Controller
{
    
    use SendsPasswordResetEmails;
	
	public function showLinkRequestForm()
	{
		return view('user.auth.passwords.email');
	}
}
```


## パスワードリセットフォームの設定

- showResetFormメソッドのオーバーライド

```app/Http/Controllers/User/Auth/ResetPasswordController.php
<?php

namespace App\Http\Controllers\User\Auth;

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

class ResetPasswordController extends Controller
{
	
    use ResetsPasswords;

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

```



## viewの設定

user側のviewを以下の通り構成していきます。
実用的ではないのですが、極力マルチ認証をシンプルに一旦完成できるようにしてみました。

```
resources/views
|
├── index.blade.php
├── layouts
|   └ default.blade.php
└── user
     ├ index.blade.php
     └ auth
        ├  login.blade.php
        ├  register.blade.php  
        ├  verify.blade.php  
        └  passwords
            ├  reset.blade.php
            └  email.blade.php
```

ファイル/ディレクトリ作成

```
$ mv resources/views/welcome.blade.php resources/views/index.blade.php 
$ mkdir resources/views/{user,layouts}
$ touch resources/views/layouts/default.blade.php
$ touch resources/views/user/index.blade.php
$ mkdir resources/views/user/auth  
$ mkdir resources/views/user/auth/passwords
$ touch resources/views/user/auth/{login.blade.php,register.blade.php,verify.blade.php}
$ touch resources/views/user/auth/passwords/{reset.blade.php,email.blade.php}
```

```php:resources/views/layouts/default.blade.php
<!doctype html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<meta name="csrf-token" content="{{ csrf_token() }}">
	<title>マルチ認証テスト</title>
	<script src="{{ asset('js/app.js') }}" defer></script>
	<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>

<h2>ユーザー関連</h2>
<ul>
	<li><a href="{{ route('user.login') }}">ユーザーログイン</a></li>
	<li><a href="{{ route('user.register') }}">ユーザー登録</a></li>
	<li><a href="{{ route('user.index') }}">ユーザーダッシュボード</a></li>
</ul>
@auth('user')
	<p>ようこそ{{ Auth::user()->name }}</p>
	<form method="POST" action="{{ route('user.logout') }}">
		@csrf
		<button type="submit">ログアウト</button>
	</form>
@else
	<p>ユーザー未ログイン</p>
@endauth

<hr>

<h2>管理者関連</h2>
<ul>
	<li><a href="{{ route('admin.login') }}">管理者ログイン</a></li>
	<li><a href="{{ route('admin.register') }}">管理者登録</a></li>
	<li><a href="{{ route('admin.index') }}">管理者ダッシュボード</a></li>
</ul>
@auth('admin')
	<p>ようこそ{{ auth('admin')->user()->name }}</p>
	<form method="POST" action="{{ route('admin.logout') }}">
		@csrf
		<button type="submit">ログアウト</button>
	</form>
@else
	<p>管理者未ログイン</p>
@endauth

<hr>

<main>
	@yield('content')
</main>
</body>
</html>
```

```php:resources/views/index.blade.php
@extends('layouts.default')
@section('content')
<h1>トップページ</h1>
@endsection
```

```php:resources/views/user/index.blade.php

@extends('layouts.default')
@section('content')
<h1>ユーザーダッシュボード</h1>
@endsection
```

```php:resources/views/user/auth/login.blade.php
@extends('layouts.default')
@section('content')
	<form method="POST" action="{{ route('user.login') }}">
		@csrf
		<div>
			<input type="email" name="email" value="{{ old('email') }}">
			@error('email')<p>{{ $message }}</p>@enderror
		</div>
		<div>
			<input type="password" name="password">
			@error('password')<p>{{ $message }}</p>@enderror
		</div>
		<div>
			<button type="submit">ログイン</button>
		</div>
	</form>
	<a href="{{ route('user.password.request') }}">パスワードを忘れた方</a>
@endsection
```

```php:resources/views/user/auth/register.blade.php
@extends('layouts.default')
@section('content')
	<form method="POST" action="{{ route('user.register') }}">
		@csrf
		<div>
			<input type="text" name="name" value="{{ old('name') }}" placeholder="name">
			@error('name')<p>{{ $message }}</p>@enderror
		</div>
		<div>
			<input type="email" name="email" value="{{ old('email') }}" placeholder="email">
			@error('email')<p>{{ $message }}</p>@enderror
		</div>
		<div>
			<input type="password" name="password" placeholder="password"><br>
			<input type="password" name="password_confirmation" placeholder="password_confirmation">
			@error('password')<p>{{ $message }}</p>@enderror
		</div>
		<button type="submit">登録</button>
	</form>	
@endsection
```

```php:resources/views/user/auth/passwords/email.blade.php
@extends('layouts.default')
@section('content')
	@if (session('status'))
		<p>{{ session('status') }}</p>
	@endif
	<form method="post" action="{{ route('user.password.email') }}">
		@csrf
		<input type="email" name="email" value="{{ old('email') }}">
		@error('email')
		<p>リンクの送信に失敗しました。</p>
		@enderror
		<button type="submit">パスワードリセットリンクを送信</button>
	</form>
@endsection
```

```php:resources/views/user/auth/passwords/reset.blade.php
@extends('layouts.default')

@section('content')
	<form method="POST" action="{{ route('user.password.update') }}">
		@csrf
		<input type="hidden" name="token" value="{{ $token }}">
		<div>
			<input type="email" name="email" value="{{ $email ?? old('email') }}" placeholder="email">
			@error('email')<p>{{ $message }}</p>@enderror
		</div>
		<div>
			<input type="password" name="password" placeholder="password"><br>
			<input type="password" name="password_confirmation" placeholder="password_confirmation">
			@error('password')<p>{{ $message }}</p>@enderror
		</div>
		<button type="submit">パスワードのリセット</button>
	</form>
@endsection
```


# 〜ユーザー側ができたのでやっと管理者側〜

User側を参考にAdmin側を作っていきます。


## ログイン後のコントローラーの準備

```
$ php artisan make:controller Admin/DashboardController
```

```php:app/Http/Controllers/Admin/DashboardController.php
<?php
namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class DashboardController extends Controller
{
	public function index()
	{
		return view('admin.index');
	}
}
```


## ルーティング設定

- Adminのプリフィックスの設定を追加

```php:routes/web.php
<?php
Route::get('/', function () {
    return view('index');
});

Route::namespace('User')->prefix('user')->name('user.')->group(function () {
	Auth::routes();
	Route::middleware('auth:user')->group(function () {
		Route::get('/', 'DashboardController@index')->name('index');
	});
});

Route::namespace('Admin')->prefix('admin')->name('admin.')->group(function () {
	Auth::routes();
	Route::middleware('auth:admin')->group(function () {
		Route::get('/', 'DashboardController@index')->name('index');
	});
});
```


## LoginControllerの設定

- showLoginForm()をOverride
- guard()をOverride
- logout()をOverride
- loggedOut()をOverride

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

namespace App\Http\Controllers\Admin\Auth;

use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class LoginController extends Controller
{
	
    use AuthenticatesUsers;

    protected $redirectTo = RouteServiceProvider::HOME_ADMIN;

    public function __construct()
    {
	    $this->middleware('guest')->except('logout');
    }
	
	public function showLoginForm()
	{
		return view('admin.auth.login');
	}
	
	protected function guard()
	{
		return Auth::guard('admin');
	}
	
	public function logout(Request $request)
	{
		Auth::guard('admin')->logout();
		return $this->loggedOut($request);
	}
	
	protected function loggedOut(Request $request)
	{
		return redirect(route('admin.login'));
	}
	
}
```

## RegisterControllerの設定

- ネームスペースを変更
- guard()をOverride
- showRegistrationForm()をOverride

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

use App\Admin;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;

class RegisterController extends Controller
{
	
    use RegistersUsers;

    protected $redirectTo = RouteServiceProvider::HOME;

    public function __construct()
    {
        $this->middleware('guest');
    }

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => ['required', 'string', 'max:255'],
            'email' => ['required', 'string', 'email', 'max:255', 'unique:admins'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }
	
	protected function guard()
	{
		return Auth::guard('admin');
	}

    protected function create(array $data)
    {
        return Admin::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }
	
	public function showRegistrationForm()
	{
		return view('admin.auth.register');
	}
}
```

## パスワードリセットURLの設定

パスワードリセットのURLを  ``` http://example.com/admin/password/reset/{token} ``` のように/admin/以下に配置したいためメールを生成しているクラスを変更します。

■リセットメール送信Notification作成

```
$ php artisan make:notification PasswordResetAdminNotification
```

※ResetPasswordを継承してtoMailのみをオーバーライドしています。

```php:app/Notifications/PasswordResetAdminNotification.php
<?php

namespace App\Notifications;

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

class PasswordResetAdminNotification extends ResetPassword
{
	
	public function toMail($notifiable)
	{
		if (static::$toMailCallback) {
			return call_user_func(static::$toMailCallback, $notifiable, $this->token);
		}
		
		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(route('admin.password.reset', ['token' => $this->token, 'email' => $notifiable->getEmailForPasswordReset()], false)))
			->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.'));
	}
}
```

- Illuminate\Auth\Passwords\CanResetPasswordのオーバーライド

```php:app/Admin.phpでsendPasswordResetNotification.php
	public function sendPasswordResetNotification($token)
	{
		$this->notify(new PasswordResetAdminNotification($token));
	}
```



## パスワードリセットフォームの設定

- showLinkRequestForm()のオーバーライド
- sendResetLinkEmail()のオーバーライド

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

namespace App\Http\Controllers\Admin\Auth;

use App\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Password;
use UnexpectedValueException;

class ForgotPasswordController extends Controller
{

    use SendsPasswordResetEmails;
	
	public function showLinkRequestForm()
	{
		return view('admin.auth.passwords.email');
	}
	
	public function sendResetLinkEmail(Request $request)
	{
		$this->validateEmail($request);
		$broker = Password::broker('admins');
		$response = $broker->sendResetLink(
			$this->credentials($request)
		);
		return $response == Password::RESET_LINK_SENT
			? $this->sendResetLinkResponse($request, $response)
			: $this->sendResetLinkFailedResponse($request, $response);
	}
}
```


## パスワードリセットフォームの設定

- redirectToの変更
- showResetFormメソッドのオーバーライド

```php: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;

class ResetPasswordController extends Controller
{
    
    use ResetsPasswords;

    /**
     * Where to redirect users after resetting their password.
     *
     * @var string
     */
    protected $redirectTo = RouteServiceProvider::HOME_ADMIN;
    
	public function showResetForm(Request $request, $token = null)
	{
		return view('admin.auth.passwords.reset')->with(
			['token' => $token, 'email' => $request->email]
		);
	}
    
}
```


## viewの設定

Admin側のviewを以下の通り構成していきます。

```
resources/views(に追加)
└── admin
     ├ index.blade.php
     └ auth
        ├  login.blade.php
        ├  register.blade.php  
        ├  verify.blade.php  
        └  passwords
            ├  reset.blade.php
            └  email.blade.php
```

ファイル/ディレクトリ作成

```
$ mkdir resources/views/admin
$ touch resources/views/admin/index.blade.php
$ mkdir resources/views/admin/auth  
$ mkdir resources/views/admin/auth/passwords
$ touch resources/views/admin/auth/{login.blade.php,register.blade.php,verify.blade.php}
$ touch resources/views/admin/auth/passwords/{reset.blade.php,email.blade.php}
```

```php:resources/views/admin/index.blade.php
@extends('layouts.default')
@section('content')
<h1>管理者ダッシュボード</h1>
@endsection
```

```php:resources/views/admin/auth/login.blade.php
@extends('layouts.default')
@section('content')
	<form method="POST" action="{{ route('admin.login') }}">
		@csrf
		<div>
			<input type="email" name="email" value="{{ old('email') }}">
			@error('email')<p>{{ $message }}</p>@enderror
		</div>
		<div>
			<input type="password" name="password">
			@error('password')<p>{{ $message }}</p>@enderror
		</div>
		<div>
			<button type="submit">ログイン</button>
		</div>
	</form>
	<a href="{{ route('admin.password.request') }}">パスワードを忘れた方</a>
@endsection
```

```php:resources/views/admin/auth/register.blade.php
@extends('layouts.default')
@section('content')

	<form method="POST" action="{{ route('admin.register') }}">
		@csrf
		<div>
			<input type="text" name="name" value="{{ old('name') }}" placeholder="name">
			@error('name')<p>{{ $message }}</p>@enderror
		</div>
		<div>
			<input type="email" name="email" value="{{ old('email') }}" placeholder="email">
			@error('email')<p>{{ $message }}</p>@enderror
		</div>
		<div>
			<input type="password" name="password" placeholder="password"><br>
			<input type="password" name="password_confirmation" placeholder="password_confirmation">
			@error('password')<p>{{ $message }}</p>@enderror
		</div>
		<button type="submit">登録</button>
	</form>

@endsection
```

```php:resources/views/admin/auth/passwords/email.blade.php
@extends('layouts.default')
@section('content')
	@if (session('status'))
		<p>{{ session('status') }}</p>
	@endif
	<form method="post" action="{{ route('user.password.email') }}">
		@csrf
		<input type="email" name="email" value="{{ old('email') }}">
		@error('email')
		<p>リンクの送信に失敗しました。</p>
		@enderror
		<button type="submit">パスワードリセットリンクを送信</button>
	</form>
@endsection
```


```php:user/auth/passwords/reset.blade.php
@extends('layouts.default')

@section('content')
	<form method="POST" action="{{ route('user.password.update') }}">
		@csrf
		<input type="hidden" name="token" value="{{ $token }}">
		<div>
			<input type="email" name="email" value="{{ $email ?? old('email') }}" placeholder="email">
			@error('email')<p>{{ $message }}</p>@enderror
		</div>
		<div>
			<input type="password" name="password" placeholder="password"><br>
			<input type="password" name="password_confirmation" placeholder="password_confirmation">
			@error('password')<p>{{ $message }}</p>@enderror
		</div>
		<button type="submit">パスワードのリセット</button>
	</form>
@endsection
```


## 参考にさせて頂いたページ。
Laravel6でマルチ認証を実装する（UserとAdminの階層を分ける）
https://qiita.com/namizatork/items/5d56d96d4c255a0e3a87