├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── LaravelCollectiveAuth-banner.png ├── composer.json ├── phpunit.xml.dist ├── readme.md └── src ├── AuthCommand.php ├── AuthRouteMethods.php ├── CollectiveAuthServiceProvider.php ├── ControllersCommand.php ├── Facades └── CollectiveAuth.php ├── Foundation ├── AuthenticatesUsers.php ├── ConfirmsPasswords.php ├── RedirectsUsers.php ├── RegistersUsers.php ├── ResetsPasswords.php ├── SendsPasswordResetEmails.php ├── ThrottlesLogins.php └── VerifiesEmails.php └── stubs ├── auth-controllers ├── ConfirmPasswordController.stub ├── ForgotPasswordController.stub ├── LoginController.stub ├── RegisterController.stub ├── ResetPasswordController.stub └── VerificationController.stub ├── controllers └── HomeController.stub ├── migrations └── 2014_10_12_100000_create_password_resets_table.php ├── routes.stub └── views ├── auth ├── login.stub ├── passwords │ ├── confirm.stub │ ├── email.stub │ └── reset.stub ├── register.stub └── verify.stub ├── home.stub └── layouts └── app.stub /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log - LarvelCollective Auth 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | ---- 5 | 6 | ## [v1.2.0] - 2023-03-07 7 | 8 | ### Added 9 | - Laravel 10 compatibility 10 | 11 | ## [v1.1.2] - 2022-03-22 12 | 13 | ### Fixed 14 | - Issue with missing password validate rule 15 | 16 | ## [v1.1.1] - 2022-02-15 17 | 18 | ### Fixed 19 | - Issue with namespaces 20 | 21 | ## [v1.1.0] - 2022-02-09 22 | 23 | ### Added 24 | - Tests from UI package 25 | 26 | ### Changed 27 | - Minor updates from the UI package updates 28 | 29 | ## [v1.0.0] - 2020-09-18 30 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Laravel Contribution Guide 2 | 3 | Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](http://laravel.com/docs/contributions). Please review the entire guide before sending a pull request. 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Matt Lantz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | The MIT License (MIT) 24 | 25 | Copyright (c) Taylor Otwell 26 | 27 | Permission is hereby granted, free of charge, to any person obtaining a copy 28 | of this software and associated documentation files (the "Software"), to deal 29 | in the Software without restriction, including without limitation the rights 30 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 31 | copies of the Software, and to permit persons to whom the Software is 32 | furnished to do so, subject to the following conditions: 33 | 34 | The above copyright notice and this permission notice shall be included in 35 | all copies or substantial portions of the Software. 36 | 37 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 38 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 39 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 40 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 41 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 42 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 43 | THE SOFTWARE. -------------------------------------------------------------------------------- /LaravelCollectiveAuth-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LaravelCollective/auth/3c6806ee8ca8ba914bccb33a4293b42aa1dcf157/LaravelCollectiveAuth-banner.png -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravelcollective/auth", 3 | "description": "Auth backend and Controller stubs for the Laravel Framework from Laravel UI", 4 | "license": "MIT", 5 | "homepage": "https://laravelcollective.com", 6 | "support": { 7 | "issues": "https://github.com/LaravelCollective/auth/issues", 8 | "source": "https://github.com/LaravelCollective/auth" 9 | }, 10 | "authors": [ 11 | { 12 | "name": "Matt Lantz", 13 | "email": "matt@laravelcollective.com" 14 | }, 15 | { 16 | "name": "Taylor Otwell", 17 | "email": "taylor@laravel.com" 18 | } 19 | ], 20 | "require": { 21 | "php": "^7.2.5|^8.0", 22 | "illuminate/support": "^7.0|^8.0|^9.0|^10.0", 23 | "illuminate/console": "^7.0|^8.0|^9.0|^10.0", 24 | "illuminate/filesystem": "^7.0|^8.0|^9.0|^10.0" 25 | }, 26 | "require-dev": { 27 | "phpunit/phpunit": "^9.5.10", 28 | "orchestra/testbench": "^6.23|^7.0|^8.0" 29 | }, 30 | "autoload": { 31 | "psr-4": { 32 | "Collective\\Auth\\": "src/" 33 | } 34 | }, 35 | "extra": { 36 | "branch-alias": { 37 | "dev-master": "1.x-dev" 38 | }, 39 | "laravel": { 40 | "providers": [ 41 | "Collective\\Auth\\CollectiveAuthServiceProvider" 42 | ] 43 | } 44 | }, 45 | "minimum-stability": "dev", 46 | "abandoned": "laravel/ui", 47 | "prefer-stable": true 48 | } 49 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 17 | ./tests 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ![LaravelCollective Auth](LaravelCollectiveAuth-banner.png) 2 | 3 | [![Total Downloads](https://poser.pugx.org/LaravelCollective/auth/downloads)](https://packagist.org/packages/laravelcollective/auth) 4 | [![License](https://poser.pugx.org/LaravelCollective/auth/license.svg)](https://packagist.org/packages/laravelcollective/auth) 5 | 6 | Official documentation for Collective Auth for The Laravel Framework can be found at the [LaravelCollective](https://laravelcollective.com/docs) website. 7 | 8 | > This code was derrived from the [Laravel/UI](https://github.com/laravel/ui) package. It's initial MIT licence attributed to Taylor Otwell is included in this packages licence as he is the original creator of the bulk of this code. This package was created for those who opt to not use Jetstream/Fortify. 9 | -------------------------------------------------------------------------------- /src/AuthCommand.php: -------------------------------------------------------------------------------- 1 | 'auth/login.blade.php', 31 | 'auth/passwords/confirm.stub' => 'auth/passwords/confirm.blade.php', 32 | 'auth/passwords/email.stub' => 'auth/passwords/email.blade.php', 33 | 'auth/passwords/reset.stub' => 'auth/passwords/reset.blade.php', 34 | 'auth/register.stub' => 'auth/register.blade.php', 35 | 'auth/verify.stub' => 'auth/verify.blade.php', 36 | 'home.stub' => 'home.blade.php', 37 | 'layouts/app.stub' => 'layouts/app.blade.php', 38 | ]; 39 | 40 | /** 41 | * Execute the console command. 42 | * 43 | * @return void 44 | * 45 | * @throws \InvalidArgumentException 46 | */ 47 | public function handle() 48 | { 49 | $this->ensureDirectoriesExist(); 50 | $this->exportViews(); 51 | $this->exportBackend(); 52 | 53 | $this->info('Authentication scaffolding generated successfully.'); 54 | } 55 | 56 | /** 57 | * Create the directories for the files. 58 | * 59 | * @return void 60 | */ 61 | protected function ensureDirectoriesExist() 62 | { 63 | if (! is_dir($directory = $this->getViewPath('layouts'))) { 64 | mkdir($directory, 0755, true); 65 | } 66 | 67 | if (! is_dir($directory = $this->getViewPath('auth/passwords'))) { 68 | mkdir($directory, 0755, true); 69 | } 70 | } 71 | 72 | /** 73 | * Export the views 74 | * 75 | * @return void 76 | */ 77 | public function exportViews() 78 | { 79 | foreach ($this->views as $key => $value) { 80 | if (file_exists($view = $this->getViewPath($value)) && ! $this->option('force')) { 81 | if (! $this->confirm("The [{$value}] view already exists. Do you want to replace it?")) { 82 | continue; 83 | } 84 | } 85 | 86 | copy( 87 | __DIR__.'/stubs/views/'.$key, 88 | $view 89 | ); 90 | } 91 | } 92 | 93 | /** 94 | * Export the authentication backend. 95 | * 96 | * @return void 97 | */ 98 | protected function exportBackend() 99 | { 100 | $this->callSilent('auth:controllers'); 101 | 102 | $controller = app_path('Http/Controllers/HomeController.php'); 103 | 104 | if (file_exists($controller) && ! $this->option('force')) { 105 | if ($this->confirm("The [HomeController.php] file already exists. Do you want to replace it?")) { 106 | file_put_contents($controller, $this->compileControllerStub()); 107 | } 108 | } else { 109 | file_put_contents($controller, $this->compileControllerStub()); 110 | } 111 | 112 | file_put_contents( 113 | base_path('routes/web.php'), 114 | file_get_contents(__DIR__.'/stubs/routes.stub'), 115 | FILE_APPEND 116 | ); 117 | 118 | copy( 119 | __DIR__.'/stubs/migrations/2014_10_12_100000_create_password_resets_table.php', 120 | base_path('database/migrations/2014_10_12_100000_create_password_resets_table.php') 121 | ); 122 | } 123 | 124 | /** 125 | * Compiles the "HomeController" stub. 126 | * 127 | * @return string 128 | */ 129 | protected function compileControllerStub() 130 | { 131 | return str_replace( 132 | '{{namespace}}', 133 | $this->laravel->getNamespace(), 134 | file_get_contents(__DIR__.'/stubs/controllers/HomeController.stub') 135 | ); 136 | } 137 | 138 | /** 139 | * Get full view path relative to the application's configured view path. 140 | * 141 | * @param string $path 142 | * @return string 143 | */ 144 | protected function getViewPath($path) 145 | { 146 | return implode(DIRECTORY_SEPARATOR, [ 147 | config('view.paths')[0] ?? resource_path('views'), $path, 148 | ]); 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /src/AuthRouteMethods.php: -------------------------------------------------------------------------------- 1 | prependGroupNamespace('Auth\LoginController')) ? null : 'App\Http\Controllers'; 17 | 18 | $this->group(['namespace' => $namespace], function() use($options) { 19 | // Login Routes... 20 | if ($options['login'] ?? true) { 21 | $this->get('login', 'Auth\LoginController@showLoginForm')->name('login'); 22 | $this->post('login', 'Auth\LoginController@login'); 23 | } 24 | 25 | // Logout Routes... 26 | if ($options['logout'] ?? true) { 27 | $this->post('logout', 'Auth\LoginController@logout')->name('logout'); 28 | } 29 | 30 | // Registration Routes... 31 | if ($options['register'] ?? true) { 32 | $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register'); 33 | $this->post('register', 'Auth\RegisterController@register'); 34 | } 35 | 36 | // Password Reset Routes... 37 | if ($options['reset'] ?? true) { 38 | $this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request'); 39 | $this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email'); 40 | $this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset'); 41 | $this->post('password/reset', 'Auth\ResetPasswordController@reset')->name('password.update'); 42 | } 43 | 44 | // Password Confirmation Routes... 45 | if ($options['confirm'] ?? class_exists($this->prependGroupNamespace('Auth\ConfirmPasswordController'))) { 46 | $this->get('password/confirm', 'Auth\ConfirmPasswordController@showConfirmForm')->name('password.confirm'); 47 | $this->post('password/confirm', 'Auth\ConfirmPasswordController@confirm'); 48 | } 49 | 50 | // Email Verification Routes... 51 | if ($options['verify'] ?? false) { 52 | $this->get('email/verify', 'Auth\VerificationController@show')->name('verification.notice'); 53 | $this->get('email/verify/{id}/{hash}', 'Auth\VerificationController@verify')->name('verification.verify'); 54 | $this->post('email/resend', 'Auth\VerificationController@resend')->name('verification.resend'); 55 | } 56 | }); 57 | }; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/CollectiveAuthServiceProvider.php: -------------------------------------------------------------------------------- 1 | app->runningInConsole()) { 21 | $this->commands([ 22 | AuthCommand::class, 23 | ControllersCommand::class, 24 | ]); 25 | } 26 | } 27 | 28 | /** 29 | * Bootstrap any application services. 30 | * 31 | * @return void 32 | */ 33 | public function boot() 34 | { 35 | Route::mixin(new AuthRouteMethods); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/ControllersCommand.php: -------------------------------------------------------------------------------- 1 | allFiles(__DIR__.'/stubs/auth-controllers')) 40 | ->each(function (SplFileInfo $file) use ($filesystem) { 41 | $filesystem->copy( 42 | $file->getPathname(), 43 | app_path('Http/Controllers/Auth/'.Str::replaceLast('.stub', '.php', $file->getFilename())) 44 | ); 45 | }); 46 | 47 | $this->info('Authentication scaffolding generated successfully.'); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Facades/CollectiveAuth.php: -------------------------------------------------------------------------------- 1 | make('router')->auth($options); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Foundation/AuthenticatesUsers.php: -------------------------------------------------------------------------------- 1 | validateLogin($request); 37 | 38 | // If the class is using the ThrottlesLogins trait, we can automatically throttle 39 | // the login attempts for this application. We'll key this by the username and 40 | // the IP address of the client making these requests into this application. 41 | if (method_exists($this, 'hasTooManyLoginAttempts') && 42 | $this->hasTooManyLoginAttempts($request)) { 43 | $this->fireLockoutEvent($request); 44 | 45 | return $this->sendLockoutResponse($request); 46 | } 47 | 48 | if ($this->attemptLogin($request)) { 49 | if ($request->hasSession()) { 50 | $request->session()->put('auth.password_confirmed_at', time()); 51 | } 52 | 53 | return $this->sendLoginResponse($request); 54 | } 55 | 56 | // If the login attempt was unsuccessful we will increment the number of attempts 57 | // to login and redirect the user back to the login form. Of course, when this 58 | // user surpasses their maximum number of attempts they will get locked out. 59 | $this->incrementLoginAttempts($request); 60 | 61 | return $this->sendFailedLoginResponse($request); 62 | } 63 | 64 | /** 65 | * Validate the user login request. 66 | * 67 | * @param \Illuminate\Http\Request $request 68 | * @return void 69 | * 70 | * @throws \Illuminate\Validation\ValidationException 71 | */ 72 | protected function validateLogin(Request $request) 73 | { 74 | $request->validate([ 75 | $this->username() => 'required|string', 76 | 'password' => 'required|string', 77 | ]); 78 | } 79 | 80 | /** 81 | * Attempt to log the user into the application. 82 | * 83 | * @param \Illuminate\Http\Request $request 84 | * @return bool 85 | */ 86 | protected function attemptLogin(Request $request) 87 | { 88 | return $this->guard()->attempt( 89 | $this->credentials($request), 90 | $request->filled('remember') 91 | ); 92 | } 93 | 94 | /** 95 | * Get the needed authorization credentials from the request. 96 | * 97 | * @param \Illuminate\Http\Request $request 98 | * @return array 99 | */ 100 | protected function credentials(Request $request) 101 | { 102 | return $request->only($this->username(), 'password'); 103 | } 104 | 105 | /** 106 | * Send the response after the user was authenticated. 107 | * 108 | * @param \Illuminate\Http\Request $request 109 | * @return \Illuminate\Http\Response 110 | */ 111 | protected function sendLoginResponse(Request $request) 112 | { 113 | $request->session()->regenerate(); 114 | 115 | $this->clearLoginAttempts($request); 116 | 117 | if ($response = $this->authenticated($request, $this->guard()->user())) { 118 | return $response; 119 | } 120 | 121 | return $request->wantsJson() 122 | ? new JsonResponse([], 204) 123 | : redirect()->intended($this->redirectPath()); 124 | } 125 | 126 | /** 127 | * The user has been authenticated. 128 | * 129 | * @param \Illuminate\Http\Request $request 130 | * @param mixed $user 131 | * @return mixed 132 | */ 133 | protected function authenticated(Request $request, $user) 134 | { 135 | // 136 | } 137 | 138 | /** 139 | * Get the failed login response instance. 140 | * 141 | * @param \Illuminate\Http\Request $request 142 | * @return \Symfony\Component\HttpFoundation\Response 143 | * 144 | * @throws \Illuminate\Validation\ValidationException 145 | */ 146 | protected function sendFailedLoginResponse(Request $request) 147 | { 148 | throw ValidationException::withMessages([ 149 | $this->username() => [trans('auth.failed')], 150 | ]); 151 | } 152 | 153 | /** 154 | * Get the login username to be used by the controller. 155 | * 156 | * @return string 157 | */ 158 | public function username() 159 | { 160 | return 'email'; 161 | } 162 | 163 | /** 164 | * Log the user out of the application. 165 | * 166 | * @param \Illuminate\Http\Request $request 167 | * @return \Illuminate\Http\Response 168 | */ 169 | public function logout(Request $request) 170 | { 171 | $this->guard()->logout(); 172 | 173 | $request->session()->invalidate(); 174 | 175 | $request->session()->regenerateToken(); 176 | 177 | if ($response = $this->loggedOut($request)) { 178 | return $response; 179 | } 180 | 181 | return $request->wantsJson() 182 | ? new JsonResponse([], 204) 183 | : redirect('/'); 184 | } 185 | 186 | /** 187 | * The user has logged out of the application. 188 | * 189 | * @param \Illuminate\Http\Request $request 190 | * @return mixed 191 | */ 192 | protected function loggedOut(Request $request) 193 | { 194 | // 195 | } 196 | 197 | /** 198 | * Get the guard to be used during authentication. 199 | * 200 | * @return \Illuminate\Contracts\Auth\StatefulGuard 201 | */ 202 | protected function guard() 203 | { 204 | return Auth::guard(); 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /src/Foundation/ConfirmsPasswords.php: -------------------------------------------------------------------------------- 1 | validate($this->rules(), $this->validationErrorMessages()); 31 | 32 | $this->resetPasswordConfirmationTimeout($request); 33 | 34 | return $request->wantsJson() 35 | ? new JsonResponse([], 204) 36 | : redirect()->intended($this->redirectPath()); 37 | } 38 | 39 | /** 40 | * Reset the password confirmation timeout. 41 | * 42 | * @param \Illuminate\Http\Request $request 43 | * @return void 44 | */ 45 | protected function resetPasswordConfirmationTimeout(Request $request) 46 | { 47 | $request->session()->put('auth.password_confirmed_at', time()); 48 | } 49 | 50 | /** 51 | * Get the password confirmation validation rules. 52 | * 53 | * @return array 54 | */ 55 | protected function rules() 56 | { 57 | return [ 58 | 'password' => 'required|current_password:web', 59 | ]; 60 | } 61 | 62 | /** 63 | * Get the password confirmation validation error messages. 64 | * 65 | * @return array 66 | */ 67 | protected function validationErrorMessages() 68 | { 69 | return []; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Foundation/RedirectsUsers.php: -------------------------------------------------------------------------------- 1 | redirectTo(); 16 | } 17 | 18 | return property_exists($this, 'redirectTo') ? $this->redirectTo : RouteServiceProvider::HOME; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Foundation/RegistersUsers.php: -------------------------------------------------------------------------------- 1 | validator($request->all())->validate(); 33 | 34 | event(new Registered($user = $this->create($request->all()))); 35 | 36 | $this->guard()->login($user); 37 | 38 | if ($response = $this->registered($request, $user)) { 39 | return $response; 40 | } 41 | 42 | return $request->wantsJson() 43 | ? new JsonResponse([], 201) 44 | : redirect($this->redirectPath()); 45 | } 46 | 47 | /** 48 | * Get the guard to be used during registration. 49 | * 50 | * @return \Illuminate\Contracts\Auth\StatefulGuard 51 | */ 52 | protected function guard() 53 | { 54 | return Auth::guard(); 55 | } 56 | 57 | /** 58 | * The user has been registered. 59 | * 60 | * @param \Illuminate\Http\Request $request 61 | * @param mixed $user 62 | * @return mixed 63 | */ 64 | protected function registered(Request $request, $user) 65 | { 66 | // 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/Foundation/ResetsPasswords.php: -------------------------------------------------------------------------------- 1 | with( 31 | ['token' => $token, 'email' => $request->email] 32 | ); 33 | } 34 | 35 | /** 36 | * Reset the given user's password. 37 | * 38 | * @param \Illuminate\Http\Request $request 39 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 40 | */ 41 | public function reset(Request $request) 42 | { 43 | $request->validate($this->rules(), $this->validationErrorMessages()); 44 | 45 | // Here we will attempt to reset the user's password. If it is successful we 46 | // will update the password on an actual user model and persist it to the 47 | // database. Otherwise we will parse the error and return the response. 48 | $response = $this->broker()->reset( 49 | $this->credentials($request), 50 | function ($user, $password) { 51 | $this->resetPassword($user, $password); 52 | } 53 | ); 54 | 55 | // If the password was successfully reset, we will redirect the user back to 56 | // the application's home authenticated view. If there is an error we can 57 | // redirect them back to where they came from with their error message. 58 | return $response == Password::PASSWORD_RESET 59 | ? $this->sendResetResponse($request, $response) 60 | : $this->sendResetFailedResponse($request, $response); 61 | } 62 | 63 | /** 64 | * Get the password reset validation rules. 65 | * 66 | * @return array 67 | */ 68 | protected function rules() 69 | { 70 | return [ 71 | 'token' => 'required', 72 | 'email' => 'required|email', 73 | 'password' => ['required', 'confirmed', Rules\Password::defaults()], 74 | ]; 75 | } 76 | 77 | /** 78 | * Get the password reset validation error messages. 79 | * 80 | * @return array 81 | */ 82 | protected function validationErrorMessages() 83 | { 84 | return []; 85 | } 86 | 87 | /** 88 | * Get the password reset credentials from the request. 89 | * 90 | * @param \Illuminate\Http\Request $request 91 | * @return array 92 | */ 93 | protected function credentials(Request $request) 94 | { 95 | return $request->only( 96 | 'email', 97 | 'password', 98 | 'password_confirmation', 99 | 'token' 100 | ); 101 | } 102 | 103 | /** 104 | * Reset the given user's password. 105 | * 106 | * @param \Illuminate\Contracts\Auth\CanResetPassword $user 107 | * @param string $password 108 | * @return void 109 | */ 110 | protected function resetPassword($user, $password) 111 | { 112 | $this->setUserPassword($user, $password); 113 | 114 | $user->setRememberToken(Str::random(60)); 115 | 116 | $user->save(); 117 | 118 | event(new PasswordReset($user)); 119 | 120 | $this->guard()->login($user); 121 | } 122 | 123 | /** 124 | * Set the user's password. 125 | * 126 | * @param \Illuminate\Contracts\Auth\CanResetPassword $user 127 | * @param string $password 128 | * @return void 129 | */ 130 | protected function setUserPassword($user, $password) 131 | { 132 | $user->password = Hash::make($password); 133 | } 134 | 135 | /** 136 | * Get the response for a successful password reset. 137 | * 138 | * @param \Illuminate\Http\Request $request 139 | * @param string $response 140 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 141 | */ 142 | protected function sendResetResponse(Request $request, $response) 143 | { 144 | if ($request->wantsJson()) { 145 | return new JsonResponse(['message' => trans($response)], 200); 146 | } 147 | 148 | return redirect($this->redirectPath()) 149 | ->with('status', trans($response)); 150 | } 151 | 152 | /** 153 | * Get the response for a failed password reset. 154 | * 155 | * @param \Illuminate\Http\Request $request 156 | * @param string $response 157 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 158 | */ 159 | protected function sendResetFailedResponse(Request $request, $response) 160 | { 161 | if ($request->wantsJson()) { 162 | throw ValidationException::withMessages([ 163 | 'email' => [trans($response)], 164 | ]); 165 | } 166 | 167 | return redirect()->back() 168 | ->withInput($request->only('email')) 169 | ->withErrors(['email' => trans($response)]); 170 | } 171 | 172 | /** 173 | * Get the broker to be used during password reset. 174 | * 175 | * @return \Illuminate\Contracts\Auth\PasswordBroker 176 | */ 177 | public function broker() 178 | { 179 | return Password::broker(); 180 | } 181 | 182 | /** 183 | * Get the guard to be used during password reset. 184 | * 185 | * @return \Illuminate\Contracts\Auth\StatefulGuard 186 | */ 187 | protected function guard() 188 | { 189 | return Auth::guard(); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /src/Foundation/SendsPasswordResetEmails.php: -------------------------------------------------------------------------------- 1 | validateEmail($request); 31 | 32 | // We will send the password reset link to this user. Once we have attempted 33 | // to send the link, we will examine the response then see the message we 34 | // need to show to the user. Finally, we'll send out a proper response. 35 | $response = $this->broker()->sendResetLink( 36 | $this->credentials($request) 37 | ); 38 | 39 | return $response == Password::RESET_LINK_SENT 40 | ? $this->sendResetLinkResponse($request, $response) 41 | : $this->sendResetLinkFailedResponse($request, $response); 42 | } 43 | 44 | /** 45 | * Validate the email for the given request. 46 | * 47 | * @param \Illuminate\Http\Request $request 48 | * @return void 49 | */ 50 | protected function validateEmail(Request $request) 51 | { 52 | $request->validate(['email' => 'required|email']); 53 | } 54 | 55 | /** 56 | * Get the needed authentication credentials from the request. 57 | * 58 | * @param \Illuminate\Http\Request $request 59 | * @return array 60 | */ 61 | protected function credentials(Request $request) 62 | { 63 | return $request->only('email'); 64 | } 65 | 66 | /** 67 | * Get the response for a successful password reset link. 68 | * 69 | * @param \Illuminate\Http\Request $request 70 | * @param string $response 71 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 72 | */ 73 | protected function sendResetLinkResponse(Request $request, $response) 74 | { 75 | return $request->wantsJson() 76 | ? new JsonResponse(['message' => trans($response)], 200) 77 | : back()->with('status', trans($response)); 78 | } 79 | 80 | /** 81 | * Get the response for a failed password reset link. 82 | * 83 | * @param \Illuminate\Http\Request $request 84 | * @param string $response 85 | * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse 86 | */ 87 | protected function sendResetLinkFailedResponse(Request $request, $response) 88 | { 89 | if ($request->wantsJson()) { 90 | throw ValidationException::withMessages([ 91 | 'email' => [trans($response)], 92 | ]); 93 | } 94 | 95 | return back() 96 | ->withInput($request->only('email')) 97 | ->withErrors(['email' => trans($response)]); 98 | } 99 | 100 | /** 101 | * Get the broker to be used during password reset. 102 | * 103 | * @return \Illuminate\Contracts\Auth\PasswordBroker 104 | */ 105 | public function broker() 106 | { 107 | return Password::broker(); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Foundation/ThrottlesLogins.php: -------------------------------------------------------------------------------- 1 | limiter()->tooManyAttempts( 23 | $this->throttleKey($request), 24 | $this->maxAttempts() 25 | ); 26 | } 27 | 28 | /** 29 | * Increment the login attempts for the user. 30 | * 31 | * @param \Illuminate\Http\Request $request 32 | * @return void 33 | */ 34 | protected function incrementLoginAttempts(Request $request) 35 | { 36 | $this->limiter()->hit( 37 | $this->throttleKey($request), 38 | $this->decayMinutes() * 60 39 | ); 40 | } 41 | 42 | /** 43 | * Redirect the user after determining they are locked out. 44 | * 45 | * @param \Illuminate\Http\Request $request 46 | * @return \Symfony\Component\HttpFoundation\Response 47 | * 48 | * @throws \Illuminate\Validation\ValidationException 49 | */ 50 | protected function sendLockoutResponse(Request $request) 51 | { 52 | $seconds = $this->limiter()->availableIn( 53 | $this->throttleKey($request) 54 | ); 55 | 56 | throw ValidationException::withMessages([ 57 | $this->username() => [trans('auth.throttle', [ 58 | 'seconds' => $seconds, 59 | 'minutes' => ceil($seconds / 60), 60 | ])], 61 | ])->status(Response::HTTP_TOO_MANY_REQUESTS); 62 | } 63 | 64 | /** 65 | * Clear the login locks for the given user credentials. 66 | * 67 | * @param \Illuminate\Http\Request $request 68 | * @return void 69 | */ 70 | protected function clearLoginAttempts(Request $request) 71 | { 72 | $this->limiter()->clear($this->throttleKey($request)); 73 | } 74 | 75 | /** 76 | * Fire an event when a lockout occurs. 77 | * 78 | * @param \Illuminate\Http\Request $request 79 | * @return void 80 | */ 81 | protected function fireLockoutEvent(Request $request) 82 | { 83 | event(new Lockout($request)); 84 | } 85 | 86 | /** 87 | * Get the throttle key for the given request. 88 | * 89 | * @param \Illuminate\Http\Request $request 90 | * @return string 91 | */ 92 | protected function throttleKey(Request $request) 93 | { 94 | return Str::transliterate(Str::lower($request->input($this->username())).'|'.$request->ip()); 95 | } 96 | 97 | /** 98 | * Get the rate limiter instance. 99 | * 100 | * @return \Illuminate\Cache\RateLimiter 101 | */ 102 | protected function limiter() 103 | { 104 | return app(RateLimiter::class); 105 | } 106 | 107 | /** 108 | * Get the maximum number of attempts to allow. 109 | * 110 | * @return int 111 | */ 112 | public function maxAttempts() 113 | { 114 | return property_exists($this, 'maxAttempts') ? $this->maxAttempts : 5; 115 | } 116 | 117 | /** 118 | * Get the number of minutes to throttle for. 119 | * 120 | * @return int 121 | */ 122 | public function decayMinutes() 123 | { 124 | return property_exists($this, 'decayMinutes') ? $this->decayMinutes : 1; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/Foundation/VerifiesEmails.php: -------------------------------------------------------------------------------- 1 | user()->hasVerifiedEmail() 23 | ? redirect($this->redirectPath()) 24 | : view('auth.verify'); 25 | } 26 | 27 | /** 28 | * Mark the authenticated user's email address as verified. 29 | * 30 | * @param \Illuminate\Http\Request $request 31 | * @return \Illuminate\Http\Response 32 | * 33 | * @throws \Illuminate\Auth\Access\AuthorizationException 34 | */ 35 | public function verify(Request $request) 36 | { 37 | if (! hash_equals((string) $request->route('id'), (string) $request->user()->getKey())) { 38 | throw new AuthorizationException; 39 | } 40 | 41 | if (! hash_equals((string) $request->route('hash'), sha1($request->user()->getEmailForVerification()))) { 42 | throw new AuthorizationException; 43 | } 44 | 45 | if ($request->user()->hasVerifiedEmail()) { 46 | return $request->wantsJson() 47 | ? new Response('', 204) 48 | : redirect($this->redirectPath()); 49 | } 50 | 51 | if ($request->user()->markEmailAsVerified()) { 52 | event(new Verified($request->user())); 53 | } 54 | 55 | if ($response = $this->verified($request)) { 56 | return $response; 57 | } 58 | 59 | return $request->wantsJson() 60 | ? new Response('', 204) 61 | : redirect($this->redirectPath())->with('verified', true); 62 | } 63 | 64 | /** 65 | * The user has been verified. 66 | * 67 | * @param \Illuminate\Http\Request $request 68 | * @return mixed 69 | */ 70 | protected function verified(Request $request) 71 | { 72 | // 73 | } 74 | 75 | /** 76 | * Resend the email verification notification. 77 | * 78 | * @param \Illuminate\Http\Request $request 79 | * @return \Illuminate\Http\Response 80 | */ 81 | public function resend(Request $request) 82 | { 83 | if ($request->user()->hasVerifiedEmail()) { 84 | return $request->wantsJson() 85 | ? new Response('', 204) 86 | : redirect($this->redirectPath()); 87 | } 88 | 89 | $request->user()->sendEmailVerificationNotification(); 90 | 91 | return $request->wantsJson() 92 | ? new Response('', 202) 93 | : back()->with('resent', true); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/stubs/auth-controllers/ConfirmPasswordController.stub: -------------------------------------------------------------------------------- 1 | middleware('auth'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/stubs/auth-controllers/ForgotPasswordController.stub: -------------------------------------------------------------------------------- 1 | middleware('guest')->except('logout'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/stubs/auth-controllers/RegisterController.stub: -------------------------------------------------------------------------------- 1 | middleware('guest'); 42 | } 43 | 44 | /** 45 | * Get a validator for an incoming registration request. 46 | * 47 | * @param array $data 48 | * @return \Illuminate\Contracts\Validation\Validator 49 | */ 50 | protected function validator(array $data) 51 | { 52 | return Validator::make($data, [ 53 | 'name' => ['required', 'string', 'max:255'], 54 | 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 55 | 'password' => ['required', 'string', 'min:8', 'confirmed'], 56 | ]); 57 | } 58 | 59 | /** 60 | * Create a new user instance after a valid registration. 61 | * 62 | * @param array $data 63 | * @return \App\User 64 | */ 65 | protected function create(array $data) 66 | { 67 | return User::create([ 68 | 'name' => $data['name'], 69 | 'email' => $data['email'], 70 | 'password' => Hash::make($data['password']), 71 | ]); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/stubs/auth-controllers/ResetPasswordController.stub: -------------------------------------------------------------------------------- 1 | middleware('auth'); 39 | $this->middleware('signed')->only('verify'); 40 | $this->middleware('throttle:6,1')->only('verify', 'resend'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/stubs/controllers/HomeController.stub: -------------------------------------------------------------------------------- 1 | middleware('auth'); 17 | } 18 | 19 | /** 20 | * Show the application dashboard. 21 | * 22 | * @return \Illuminate\Contracts\Support\Renderable 23 | */ 24 | public function index() 25 | { 26 | return view('home'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/stubs/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/stubs/routes.stub: -------------------------------------------------------------------------------- 1 | 2 | CollectiveAuth::routes([ 3 | 'login' => true, 4 | 'logout' => true, 5 | 'register' => true, 6 | 'reset' => true, 7 | 'confirm' => true, 8 | 'verify' => true, 9 | ]); 10 | 11 | Route::get('/home', 'HomeController@index')->name('home'); 12 | -------------------------------------------------------------------------------- /src/stubs/views/auth/login.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |

{{ __('Login') }}

5 | 6 |
7 |
8 | @csrf 9 | 10 |
11 | 12 | 13 |
14 | 15 | 16 | @error('email') 17 | 18 | {{ $message }} 19 | 20 | @enderror 21 |
22 |
23 | 24 |
25 | 26 | 27 |
28 | 29 | 30 | @error('password') 31 | 32 | {{ $message }} 33 | 34 | @enderror 35 |
36 |
37 | 38 |
39 |
40 |
41 | 42 | 43 | 46 |
47 |
48 |
49 | 50 |
51 |
52 | 55 | 56 | @if (Route::has('password.request')) 57 | 58 | {{ __('Forgot Your Password?') }} 59 | 60 | @endif 61 |
62 |
63 |
64 |
65 | @endsection 66 | -------------------------------------------------------------------------------- /src/stubs/views/auth/passwords/confirm.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 | 5 |

{{ __('Confirm Password') }}

6 |

{{ __('Please confirm your password before continuing.') }}

7 | 8 |
9 | @csrf 10 | 11 |
12 | 13 | 14 | @error('password') 15 | 16 | {{ $message }} 17 | 18 | @enderror 19 |
20 | 21 | 22 |
23 |
24 | 27 | 28 | @if (Route::has('password.request')) 29 | 30 | {{ __('Forgot Your Password?') }} 31 | 32 | @endif 33 |
34 |
35 |
36 | 37 | @endsection 38 | -------------------------------------------------------------------------------- /src/stubs/views/auth/passwords/email.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |

{{ __('Reset Password') }}

5 | 6 | @if (session('status')) 7 |
8 | {{ session('status') }} 9 |
10 | @endif 11 | 12 |
13 | @csrf 14 | 15 |
16 | 17 |
18 | 19 | 20 | @error('email') 21 | 22 | {{ $message }} 23 | 24 | @enderror 25 |
26 |
27 | 28 |
29 |
30 | 33 |
34 |
35 |
36 | 37 | @endsection 38 | -------------------------------------------------------------------------------- /src/stubs/views/auth/passwords/reset.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |

{{ __('Reset Password') }}

5 | 6 |
7 |
8 | @csrf 9 | 10 | 11 | 12 |
13 | 14 | 15 |
16 | 17 | 18 | @error('email') 19 | 20 | {{ $message }} 21 | 22 | @enderror 23 |
24 |
25 | 26 |
27 | 28 | 29 |
30 | 31 | 32 | @error('password') 33 | 34 | {{ $message }} 35 | 36 | @enderror 37 |
38 |
39 | 40 |
41 | 42 | 43 |
44 | 45 |
46 |
47 | 48 |
49 |
50 | 53 |
54 |
55 |
56 |
57 | @endsection 58 | -------------------------------------------------------------------------------- /src/stubs/views/auth/register.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |

{{ __('Register') }}

5 | 6 |
7 |
8 | @csrf 9 | 10 |
11 | 12 | 13 |
14 | 15 | 16 | @error('name') 17 | 18 | {{ $message }} 19 | 20 | @enderror 21 |
22 |
23 | 24 |
25 | 26 | 27 |
28 | 29 | 30 | @error('email') 31 | 32 | {{ $message }} 33 | 34 | @enderror 35 |
36 |
37 | 38 |
39 | 40 | 41 |
42 | 43 | 44 | @error('password') 45 | 46 | {{ $message }} 47 | 48 | @enderror 49 |
50 |
51 | 52 |
53 | 54 | 55 |
56 | 57 |
58 |
59 | 60 |
61 |
62 | 65 |
66 |
67 |
68 |
69 | @endsection 70 | -------------------------------------------------------------------------------- /src/stubs/views/auth/verify.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |

{{ __('Verify Your Email Address') }}

5 | 6 |
7 | @if (session('resent')) 8 |
9 | {{ __('A fresh verification link has been sent to your email address.') }} 10 |
11 | @endif 12 | 13 | {{ __('Before proceeding, please check your email for a verification link.') }} 14 | {{ __('If you did not receive the email') }}, 15 |
16 | @csrf 17 | . 18 |
19 |
20 | @endsection 21 | -------------------------------------------------------------------------------- /src/stubs/views/home.stub: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |

{{ __('Dashboard') }}

5 | 6 |
7 | @if (session('status')) 8 |
9 | {{ session('status') }} 10 |
11 | @endif 12 | 13 | {{ __('You are logged in!') }} 14 |
15 | @endsection 16 | -------------------------------------------------------------------------------- /src/stubs/views/layouts/app.stub: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {{ config('app.name', 'Laravel') }} 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 37 | 38 |
39 | @yield('content') 40 |
41 |
42 | 43 | 44 | --------------------------------------------------------------------------------