I created auth module by php artisan make:auth
I Tried to convert registration success after email verifaction, but found all auth code is inside vendor folder.
for below routes
// Authentication Routes...
Route::get('login', 'Auth\AuthController#showLoginForm');
Route::post('login', 'Auth\AuthController#login');
Route::get('logout', 'Auth\AuthController#logout');
// Registration Routes...
Route::get('register', 'Auth\AuthController#showRegistrationForm');
Route::post('register', 'Auth\AuthController#register');
// Password Reset Routes...
Route::get('password/reset/{token?}', 'Auth\PasswordController#showResetForm');
Route::post('password/email', 'Auth\PasswordController#sendResetLinkEmail');
Route::post('password/reset', 'Auth\PasswordController#reset');
It creates user and login directly. but I want to verify users email by sending email with a token.
I know updating in vendor is not a good idea, Please suggest me to handle this, Or I should create my own auth module ?
Thanks for your time,
Cheers.
The registration process goes through the method register inside the trait:
/**
* Handle a registration request for the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function register(Request $request)
{
$validator = $this->validator($request->all());
if ($validator->fails()) {
$this->throwValidationException(
$request, $validator
);
}
Auth::guard($this->getGuard())->login($this->create($request->all()));
return redirect($this->redirectPath());
}
Then this method is calling two functions in the AuthController in the app directory, this you can edit as you wish:
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => 'required|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:6',
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'password' => bcrypt($data['password']),
//'token' => str_random(10)
]);
//Send email to $user here
return $user
}
}
In order to prevent users from logging in, change the Auth Middleware:
class Authenticate
{
/**
* 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)->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
if (!Auth::user()->validated())
{
return redirect()->route('error.message.route');
}
return $next($request);
}
}
Related
I am working with an inherited site based on the Laravel Framework which I upgraded from 5.6 to 8.0. I most aspects the site works great, but I occasionally sumble upon missing pieces. For example, I just discovered that the Reset Password feature does not work. Looking into it I find that there is a route for this:
Route::post('password/reset/{token}', ['as' => 'app.password.reset.post', 'uses' => 'App\Auth\ResetPasswordController#reset']);
Yet there is no 'reset()' method in the ResetPasswordController. Additionally, the ResetPasswordController uses the trait 'ResetsPassword', yet there is no such trait located under
Illuminate\Foundation\Auth\ResetsPasswords;
I tried checking the github repo for the Laravel framework, but these pieces were not there. I also looked under laravel-ui and didn't see them. According to the documentation,
"Laravel includes Auth\ForgotPasswordController and Auth\ResetPasswordController classes that contains the logic necessary to e-mail password reset links and reset user passwords. All of the routes needed to perform password resets may be generated using the laravel/ui Composer package"
I'm a little nervous about doing a general update as all other pieces are in place and working so I was looking for a way to obtain the individual pieces and have not found anything.
Here are my login routes:
Route::group(['prefix' => 'app'], function () {
//Auth::routes();
Route::get('login', ['as' => 'app.login', 'uses' => 'App\Auth\LoginController#showLoginForm']);
Route::post('login', ['as' => 'app.login.post', 'uses' => 'App\Auth\LoginController#login']);
Route::post('logout', ['as' => 'app.logout.post', 'uses' => 'App\Auth\LoginController#logout']);
Route::post('password/email', ['as' => 'app.password.email.post', 'uses' => 'App\Auth\ForgotPasswordController#sendResetLinkEmail']);
Route::get('password/reset', ['as' => 'app.password', 'uses' => 'App\Auth\ForgotPasswordController#showLinkRequestForm']);
Route::get('password/reset/{token}', ['as' => 'app.password.reset', 'uses' => 'App\Auth\ResetPasswordController#showResetForm']);
Route::post('password/reset/{token}', ['as' => 'app.password.reset.post', 'uses' => 'App\Auth\ResetPasswordController#reset']);
And this is what my ResetPasswordController looks like:
namespace App\Http\Controllers\App\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
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 password reset.
*
* #var string
*/
protected $redirectTo = '/';
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->redirectTo = route('app.dashboard');
$this->middleware('guest');
}
/**
* Display the password reset view for the given token.
*
* If no token is present, display the link request form.
*
* #param \Illuminate\Http\Request $request
* #param string|null $token
* #return \Illuminate\Http\Response
*/
public function showResetForm(Request $request, $token = null)
{
return view('app.auth.passwords.reset')->with(
['token' => $token, 'email' => $request->email]
);
}
}
Also, from what I've read there is possibly an updated reset.blade.php. My question is what is my best approach to fix the reset password bug?
This is the trait for reseting passwords, that I found in my project, I hope it can help you somehow.
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules;
use Illuminate\Validation\ValidationException;
trait ResetsPasswords
{
use RedirectsUsers;
/**
* Display the password reset view for the given token.
*
* If no token is present, display the link request form.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function showResetForm(Request $request)
{
$token = $request->route()->parameter('token');
return view('auth.passwords.reset')->with(
['token' => $token, 'email' => $request->email]
);
}
/**
* Reset the given user's password.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
public function reset(Request $request)
{
$request->validate($this->rules(), $this->validationErrorMessages());
// Here we will attempt to reset the user's password. If it is successful we
// will update the password on an actual user model and persist it to the
// database. Otherwise we will parse the error and return the response.
$response = $this->broker()->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
}
);
// If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
return $response == Password::PASSWORD_RESET
? $this->sendResetResponse($request, $response)
: $this->sendResetFailedResponse($request, $response);
}
/**
* Get the password reset validation rules.
*
* #return array
*/
protected function rules()
{
return [
'token' => 'required',
'email' => 'required|email',
'password' => ['required', 'confirmed', Rules\Password::defaults()],
];
}
/**
* Get the password reset validation error messages.
*
* #return array
*/
protected function validationErrorMessages()
{
return [];
}
/**
* Get the password reset credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(Request $request)
{
return $request->only(
'email', 'password', 'password_confirmation', 'token'
);
}
/**
* Reset the given user's password.
*
* #param \Illuminate\Contracts\Auth\CanResetPassword $user
* #param string $password
* #return void
*/
protected function resetPassword($user, $password)
{
$this->setUserPassword($user, $password);
$user->setRememberToken(Str::random(60));
$user->save();
event(new PasswordReset($user));
$this->guard()->login($user);
}
/**
* Set the user's password.
*
* #param \Illuminate\Contracts\Auth\CanResetPassword $user
* #param string $password
* #return void
*/
protected function setUserPassword($user, $password)
{
$user->password = Hash::make($password);
}
/**
* Get the response for a successful password reset.
*
* #param \Illuminate\Http\Request $request
* #param string $response
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
protected function sendResetResponse(Request $request, $response)
{
if ($request->wantsJson()) {
return new JsonResponse(['message' => trans($response)], 200);
}
return redirect($this->redirectPath())
->with('status', trans($response));
}
/**
* Get the response for a failed password reset.
*
* #param \Illuminate\Http\Request $request
* #param string $response
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse
*/
protected function sendResetFailedResponse(Request $request, $response)
{
if ($request->wantsJson()) {
throw ValidationException::withMessages([
'email' => [trans($response)],
]);
}
return redirect()->back()
->withInput($request->only('email'))
->withErrors(['email' => trans($response)]);
}
/**
* Get the broker to be used during password reset.
*
* #return \Illuminate\Contracts\Auth\PasswordBroker
*/
public function broker()
{
return Password::broker();
}
/**
* Get the guard to be used during password reset.
*
* #return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard();
}
}
I have a problem with laravel 8.55 and using Statamic 3. I just did fresh install on breeze and when I try to register, it saves the name, email and password in the users table, but doesnt save remember_token and doesnt log me in the system. When I try to login with the created user it gives me invalid credentials error. I tried to change the routes and their names in auth.php but without success.
routes/auth.php
Route::get('/user-register', [RegisteredUserController::class, 'create'])
->middleware('guest')
->name('user-register');
Route::post('/user-register', [RegisteredUserController::class, 'store'])
->middleware('guest');
Route::get('/user-login', [AuthenticatedSessionController::class, 'create'])
->middleware('guest')
->name('user-login');
Route::post('/user-login', [AuthenticatedSessionController::class, 'store'])
->middleware('guest');
class RegisteredUserController extends Controller
{
/**
* Display the registration view.
*
* #return \Illuminate\View\View
*/
public function create()
{
return view('auth.register');
}
/**
* Handle an incoming registration request.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse
*
* #throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request)
{
$request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
event(new Registered($user));
Auth::login($user);
return redirect(RouteServiceProvider::HOME);
}
}
class AuthenticatedSessionController extends Controller
{
/**
* Display the login view.
*
* #return \Illuminate\View\View
*/
public function create()
{
return view('auth.login');
}
/**
* Handle an incoming authentication request.
*
* #param \App\Http\Requests\Auth\LoginRequest $request
* #return \Illuminate\Http\RedirectResponse
*/
public function store(LoginRequest $request)
{
$request->authenticate();
$request->session()->regenerate();
return redirect()->intended(RouteServiceProvider::HOME);
}
/**
* Destroy an authenticated session.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse
*/
public function destroy(Request $request)
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}
I am trying to redirect users based on which role they enter in the registration page, however I keep getting the 'redirect too many times' error. I think its because I am using both the auth and guest mddlewares on the home page however I can not seem to fix it
Web.php:
Route::get('/', function () {
return view('auth.login');
});
Auth::routes();
// Using middleware guest (Redirect If Authenticated) to check role and redirect to right route.
Route::middleware(['guest'])->group(function(){
Route::get('/home', 'HomeController#index')->name('home');
});
Route::prefix('referrer')->group(function(){
/* need a more advanced middleware to give a notification when a brand user hits the
* referrer register/login page.
* e.g. logout and switch account, or simply make the referrer auth pages not accessible.
*/
Route::get('/login/{program_id?}', 'ReferrerController#showLoginForm')->name('referrer.login')->middleware('guest');
Route::post('/login/{program_id?}', 'Auth\LoginController#login')->name('referrer.login.user');
Route::get('/', 'ReferrerController#getHome')->name('referrer.home')->middleware('auth');
//program middieware
Route::middleware(['program.exist'])->group(function(){
Route::get('/register/{program_id?}', 'ReferrerController#showRegistrationForm')->name('referrer.register');
Route::post('/register/{program_id?}', 'ReferrerController#register')->name('referrer.register.user');
});
});
Register Controller:
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after registration.
*
* #var string
*/
// protected $redirectTo = RouteServiceProvider::HOME;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('guest');
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make($data, [
'name' => ['required', 'string', 'max:255'],
'role' => ['required', 'integer', 'between:1,3'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
]);
}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return \App\User
*/
protected function create(array $data)
{
$user = User::create([
'name' => $data['name'],
'role_id' => $data['role'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
]);
return $user;
}
protected function redirectTo() {
$role = auth()->user()->role_id;
switch ($role) {
case '3':
return RouteServiceProvider::REF_HOME;
break;
case '1':
//temp set as brand home
return RouteServiceProvider::ADMIN_HOME;
break;
default:
return RouteServiceProvider::HOME;
break;
}
}
}
Home Controller:
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
return view('home');
RedirectIfAuthenticated Middleware:
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()) {
// User role
$role = Auth::user()->role->name;
switch ($role) {
//role_id = 3
case 'referrer':
return redirect(RouteServiceProvider::REF_HOME);
break;
//role_id = 1
case 'admin':
//temp set as brand home
return redirect(RouteServiceProvider::ADMIN_HOME);
break;
default:
return redirect(RouteServiceProvider::HOME);
break;
}
}
return $next($request);
}
}
your index function in the HomeController has auth and guest middlewares, just use one of them only.
I'm trying to modify the default authentication to tailor my needs. I have this requirements like a user should be able to login using either user name or email but it always returns invalid credentials error even if the given credentials are correct, please refer to the code below:
<?php
namespace Illuminate\Foundation\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
trait AuthenticatesUsers
{
use RedirectsUsers, ThrottlesLogins;
/**
* Show the application's login form.
*
* #return \Illuminate\Http\Response
*/
public function showLoginForm()
{
return view('auth.login');
}
/**
* Handle a login request to the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
*/
public function login(Request $request)
{
$this->validateLogin($request);
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if ($this->attemptLogin($request)) {
return $this->sendLoginResponse($request);
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
/**
* Validate the user login request.
*
* #param \Illuminate\Http\Request $request
* #return void
*/
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|string',
'password' => 'required|string',
]);
}
/**
* Attempt to log the user into the application.
*
* #param \Illuminate\Http\Request $request
* #return bool
*/
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->has('remember')
);
}
/**
* Get the needed authorization credentials from the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
protected function credentials(Request $request)
{
// return $request->only($this->username(), 'password');
if(filter_var($request->username_email, FILTER_VALIDATE_EMAIL) ){
return $request->only('email', 'password');
}else{
return $request->only('username', 'password');
}
}
/**
* Send the response after the user was authenticated.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
protected function sendLoginResponse(Request $request)
{
$request->session()->regenerate();
$this->clearLoginAttempts($request);
return $this->authenticated($request, $this->guard()->user())
?: redirect()->intended($this->redirectPath());
}
/**
* The user has been authenticated.
*
* #param \Illuminate\Http\Request $request
* #param mixed $user
* #return mixed
*/
protected function authenticated(Request $request, $user)
{
//
return response()->json([ 'message' => 'authenticated']);
}
/**
* Get the failed login response instance.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\RedirectResponse
*/
protected function sendFailedLoginResponse(Request $request)
{
$errors = [$this->username() => trans('auth.failed')];
if ($request->expectsJson()) {
return response()->json($errors);
}
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors($errors);
}
/**
* Get the login username to be used by the controller.
*
* #return string
*/
public function username()
{
return 'username_email';
}
/**
* Log the user out of the application.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->flush();
$request->session()->regenerate();
return redirect('/');
}
/**
* Get the guard to be used during authentication.
*
* #return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return Auth::guard();
}
}
Inside credentials(), I check if its an username or email first and then return the corresponding database column, but it looks like it doesn't work at all. Any ideas, help please?
Your method:
protected function validateLogin(Request $request)
{
$this->validate($request, [
$this->username() => 'required|string',
'password' => 'required|string',
]);
}
With username() returning username_email seems incoherent. I think what you looking for is required_without_all:
protected function validateLogin(Request $request)
{
$this->validate($request, [
'username' => 'required_without_all:email|string',
'email' => 'required_without_all:username|string',
'password' => 'required|string',
]);
}
So username will be required when email is not present and vice versa.
Using the function below I was able to add active flag, so that only those users who are active can login.
Now I have another flag called role and I wish to allow only those users with role 1 or 2 to login.
public function credentials(Request $request)
{
return [
'email' => $request->email,
'password' => $request->password,
'active' => 1,
];
}
You may like to use middleware
<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
/**
* Handle the incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string $role
* #return mixed
*/
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
// Redirect...
}
return $next($request);
}
}