I have this function for registering users which is pretty much the default one but i added a token to be sent to an email so the user can activate the account, otherwise the user cant log in. So i tried to add a resend function so if the first time the email is not send they can resend manually, but that causes the 419 error Page Expired.
Register function
protected function create(array $data)
{
$user = Account::create([
'login' => $data['login'],
'email' => $data['email'],
'password' => Hash::make($data['password']),
'verifyToken'=> Str::random(40),
'active' => (env('CONFIRM_EMAIL', true)) ? 0 : 1
]);
$thisUser = Account::findOrFail($user->id);
$this->sendEmail($thisUser);
return $user;
}
This is the function for resend
protected function resend(Request $request)
{
$user = Account::where('email', $request->input('email'))->first();
$user->verifyToken = Str::random(40);
$user->save();
$this->sendEmail($user);
return $user;
}
And i call it with this form
<form action=" {!! route('resendEmail') !!}" method="POST">
<fieldset class="youplay-input">
<input id="email" type="email" class="#error('email') is-invalid #enderror" placeholder="E-
mail" name="email" value="{{ old('email') }}" required autocomplete="email">
</fieldset>
<button class="btn btn-default db" type="submit" value="Submit">
Resend Verification Link
</button>
</form>
I have discussed this with a guy but we couldnt find a good solution: How to make resend email link function in Laravel
You are missing your csrf token in the form. After <form> tag add #csrf.
Example:
<form method="POST" action="/profile">
#csrf
</form>
https://laravel.com/docs/7.x/csrf
Related
I recently added livewire login component on a multi tenant website. Normal laravel login and registration works completely fine but when through livewire i click submit Login page Post request results in 302 found and redirects to a Login route GET request
<?php
namespace App\Http\Livewire;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
class Login extends Component
{
public $email;
public $password;
protected $rules = [
'email' => 'required|email',
'password' => 'required',
];
public function submit(){
$data = array(
'email' => $this->email,
'password' => $this->password
);
return $data;
$validatedData = $this->validate();
if (Auth::attempt($data)) {
return redirect('/');
} else{
return "error";
}
}
public function render()
{
return view('livewire.login');
}
}
Livewire form
<div>
<form wire:submit.prevent="submit">
<input type="email" class="form-control form-control-lg" wire:model="email">
#error('email') <span class="error">{{ $message }}</span> #enderror
#csrf
<input type="password" class="form-control form-control-lg" wire:model="password">
#error('password') <span class="error">{{ $message }}</span> #enderror
<button type="submit" class="btn btn-lg btn-primary btn-block">Login</button>
</form>
</div>
I have a temporary solution by entering 'livewire/message/login' in VerifyCsrfToken.php
I'm not sure why livewire isn't able to fetch the csrf token from head tag
<meta name="csrf-token" content="{{ csrf_token() }}">
what could be the reason
Your submit() method returns $data, which means no line of code will get executed after return statement.
public function submit(){
$data = array(
'email' => $this->email,
'password' => $this->password
);
return $data;
// Below code will never get executed
$validatedData = $this->validate();
if (Auth::attempt($data)) {
return redirect('/');
} else{
return "error";
}
}
You are not validating data at all.
I am using laravel 6. I am trying to implement forgot password for my laravel project for the first time. I have customize the default design for login, forgot password, reset password pages. I have integrated mailtrap for sending email. I have successfully implemented flow like -
click forgot password link
get page on which user enters email and click to send reset link
gets the email of resetting link and data like email, token , created_at stores in password_reset table
on click of reset link page with token and email url gets open in new tab(open the page of reset password having email, new password, confirm password)
Further when I type new password and confirm password and click on Reset Password, nothing happens.
my reset.blade.php
<form id="sign_in" name="sign_in" method="POST" action="{{ route('password.update') }}" data-parsley-validate >
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<h1>Reset Password</h1>
<div class="col-md-12 col-sm-12 form-group has-feedback">
{{-- <label for="login_id"><span style="color:red;">*</span>Login ID</label> --}}
<input id="email" type="email" class="form-control has-feedback-left #error('email') is-invalid #enderror" placeholder="Email" name="email" value="{{ $email ?? old('email') }}" required autocomplete="email" autofocus/>
<span class="fa fa-envelope form-control-feedback left" aria-hidden="true"></span>
#error('email')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
#enderror
</div>
<div class="col-md-12 col-sm-12 form-group has-feedback">
<input id="password" type="password" class="form-control has-feedback-left #error('password') is-invalid #enderror" placeholder="Password" name="password" required autocomplete="new-password" />
<span class="fa fa-pencil form-control-feedback left" aria-hidden="true"></span>
</div>
<div class="col-md-12 col-sm-12 form-group has-feedback">
<input id="password-confirm" type="password" class="form-control has-feedback-left" placeholder="Confirm Password" name="password_confirmation" required autocomplete="new-password" />
<span class="fa fa-pencil form-control-feedback left" aria-hidden="true"></span>
</div>
<button type="submit" class="btn btn-success">Reset Password</button>
</div>
<div class="clearfix"></div>
</form>
I have default controllers generated for auth like 'ConfirmPasswordController, ForgotPasswordController, ResetPasswordController, VerificationController'
ResetPasswordController
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
class ResetPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* #var string
*/
protected $redirectTo = '/dashboard';
}
I have used default route of auth like Auth::routes();
how the passwords reset in database in users table for email and token generated in password_reset table and how the message gets displayed that 'Password reset successfully? This is not working in my case.userstable not changing with new password and entry not gets removed frompassword_reset` table once the reset done successfully.
where and what changes I have to make to make this work? please guide. thanks in advance.
Password Reset in Laravel
Step 1 — Create a Route and a Controller
Create two routes, a controller, and methods through which the email address that requires a password reset will be submitted via the password reset form. The name of these routes, controllers, and methods is totally up to you.
Route::post('reset_password_without_token', 'AccountsController#validatePasswordRequest');
Route::post('reset_password_with_token', 'AccountsController#resetPassword');
Step 2— Change the action property on the default password reset form
<form method="POST" action="{{ url('/reset_password_without_token') }}">
The default password reset form can be found here:
resources/views/auth/passwords/email.blade.php
Step 3 — Create a token and Send Password Reset Link via email
Then add the validatePasswordRequest method in the AccountsController and use or modify the code below.
//You can add validation login here
$user = DB::table('users')->where('email', '=', $request->email)
->first();
//Check if the user exists
if (count($user) < 1) {
return redirect()->back()->withErrors(['email' => trans('User does not exist')]);
}
//Create Password Reset Token
DB::table('password_resets')->insert([
'email' => $request->email,
'token' => str_random(60),
'created_at' => Carbon::now()
]);
//Get the token just created above
$tokenData = DB::table('password_resets')
->where('email', $request->email)->first();
if ($this->sendResetEmail($request->email, $tokenData->token)) {
return redirect()->back()->with('status', trans('A reset link has been sent to your email address.'));
} else {
return redirect()->back()->withErrors(['error' => trans('A Network Error occurred. Please try again.')]);
}
The sendResetEmail method is a private method that sends an email with the reset link to the user. Here you can use whatever email app you choose to use. Maybe, you have a custom email service for your organization, you can use it here, not relying on the options Laravel has by default.
private function sendResetEmail($email, $token)
{
//Retrieve the user from the database
$user = DB::table('users')->where('email', $email)->select('firstname', 'email')->first();
//Generate, the password reset link. The token generated is embedded in the link
$link = config('base_url') . 'password/reset/' . $token . '?email=' . urlencode($user->email);
try {
//Here send the link with CURL with an external email API
return true;
} catch (\Exception $e) {
return false;
}
}
The link generated and sent to the user when clicked will direct the user to your domain.com/password/reset/token?email=’user#email.com’. You can find the view here: resources/views/auth/passwords/reset.blade.php
Step 4 - Reset the User's password
Add this method to the AccountsController. Go through the comments, they explain each step.
public function resetPassword(Request $request)
{
//Validate input
$validator = Validator::make($request->all(), [
'email' => 'required|email|exists:users,email',
'password' => 'required|confirmed'
'token' => 'required' ]);
//check if payload is valid before moving on
if ($validator->fails()) {
return redirect()->back()->withErrors(['email' => 'Please complete the form']);
}
$password = $request->password;
// Validate the token
$tokenData = DB::table('password_resets')
->where('token', $request->token)->first();
// Redirect the user back to the password reset request form if the token is invalid
if (!$tokenData) return view('auth.passwords.email');
$user = User::where('email', $tokenData->email)->first();
// Redirect the user back if the email is invalid
if (!$user) return redirect()->back()->withErrors(['email' => 'Email not found']);
//Hash and update the new password
$user->password = \Hash::make($password);
$user->update(); //or $user->save();
//login the user immediately they change password successfully
Auth::login($user);
//Delete the token
DB::table('password_resets')->where('email', $user->email)
->delete();
//Send Email Reset Success Email
if ($this->sendSuccessEmail($tokenData->email)) {
return view('index');
} else {
return redirect()->back()->withErrors(['email' => trans('A Network Error occurred. Please try again.')]);
}
}
There you have it. This should be enough to get things working.
I had the same problem, I was able to solve it this way,
first i add a route:
Route::get('password/reset/{token}', [App\Http\Controllers\Auth\ResetPasswordController::class, 'showResetForm'])->name('password.reset');
next i add in reset.blade.php
<input type="hidden" name="token" value="{{$token}}">
that's it, it works for me. Maybe someone will also need it
I'm new to laravel and have been going through this code for hours, yet I'm unable to figure out what's really wrong.
I have this form:
<form method="POST" action="{{ action('School1Controller#forgot_password') }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="text" class="form-control" name="matricule" placeholder="Matricule No. or name" >
<input type="email" class="form-control" name="inst_email" placeholder="Password">
<button type="submit" class="btn btn-primary">Submit</button>
</form>
which submits to this method..
public function forgot_password(Request $request){
$this->validate($request, [
'matricule' => 'required',
'inst_email' => 'required'
]);
$input = $request->all();
$student = User::where('matricule', $input['matricule'])->where('inst_email', $input['inst_email'])->get();
// dd($student);
if (empty($student)){
Session::flash('message', 'We have no such user in our records.');
return redirect()->back();
}else{
Session::flash('message', 'Student found. We will reset your password soon.');
return redirect()->back();
}
}
..through this route..
Route::post('/forgot_password', ['as' => 'forgot_password', 'uses' => 'School1Controller#forgot_password']);
When it queries the database, it returns the student properly and I can display it using dd($student). In cases when the student is unavailable, it also displays an empty array. Now the problem is, the message that keeps displaying is that which says student is found regardless whether the $student array holds any student or not. Is there a problem with my empty() function or what?
I am working on laravel 5 eCommerce web portal.
I am having an issue when the user updates the password using the ready made scripts.
The issue is that I can send the link to the customer perfectly without any issue and the customer can change his password also. But when logged out and re-logging in, I get the error as Invalid credentials.
In my routes.php, I have this:
Route::controllers([
'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]);
This is the login page:
<form class="form-horizontal" role="form" method="POST" action="{{ url('/login') }}">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="form-group">
<label class="col-md-4 control-label">E-Mail Address</label>
<div class="col-md-6">
<input type="email" class="form-control" name="email" value="{{ old('email') }}">
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">Password</label>
<div class="col-md-6">
<input type="password" class="form-control" name="password">
</div>
</div>
<div class="form-group">
<div class="col-md-4"></div>
<div class="col-md-4">
Forgot Password
</div>
</div>
<div class="form-group">
<div class="col-md-6 col-md-offset-4">
<button type="submit" class="btn btn-primary btn-block">Login</button>
</div>
</div>
</form>
I cannot login again after I am logged out once the password has been reset.
EDIT 1:
When the login button is clicked on the login form page, the postLogin method is called. Here's the code
public function postLogin( Request $request ) {
$this->validate( $request, [
'email' => ['required', 'exists:users,email,role,customer'],
'password' => 'required'
]);
$credentials = $request->only('email', 'password');
if ( \Auth::attempt($credentials) ) {
\Session::flash('logged_in', 'You have successfully logged in.');
return redirect('/');
}
return redirect('/login')->withInput($request->all())->withErrors(['email' => 'Invalid Email Address Or Password']);
}
EDIT 2:
I just realize that login is not checking for the hash and hence returning false, on doing dd(\Hash::check($request->password, $user->password)), after updating the password and re-logging in. What could be the issue with this ?
Where have I made mistake ? Kindly guide me.
Thanks in advance.
P.S.: I am using the defaults only to update the password, rest all, I have made the controllers and models which are all working fine without any issue.
I stumbled upon this as well and found the answer here, just adding this for future reference..
The reason is that as soon as you add the setPasswordAttribute method on your User model, the password is hashed twice when using the built-in password reset functionality of Laravel. As explained on the Laracast page, all it needs is a check for an already hashed password, eg:
// Add Hash facade
use Illuminate\Support\Facades\Hash;
class User extends Authenticatable
{
// ...
/**
* Automatically hash password
*
* #param String $value The password, maybe hashed already
*
* #return string|null
*/
public function setPasswordAttribute($value)
{
if ($value) {
$this->attributes['password'] = Hash::needsRehash($value) ? Hash::make($value) : $value;
}
}
}
If the new password does not work after changing then something goes wrong when changing the password.
Most likely suspect is the encryption. It can be possible that you are not using the Hash::make($password) and saving it in plaintext format.
You can doublecheck if the hash is saved correctly to DB with function Hash::check($password, $hash);
During the login you can check the password as
public function postLogin( Request $request ) {
$user=User::where('email', $request->email);
Log::debug("Testing $request->password $user->password ". Hash::check($request->password, $user->password));
}
If the Hash::check is false then something went wrong when saving new password. $user->password must be in hashed form.
I have 3 user types :
Admin
Distributor
Internal
I have a problem sign in as user type. ( Internal )
I can sign in when my user type is Admin.
I can sign in when my user type is Distributor.
BUT I can’t sign in when my user type is internal. Wired ????
I look through every single line of my code in my sign-in functions in my AccountController.php.
I didn’t notice any bug there. If you guys notice any bugs there -- please kindly let me know.
That will be a huge help for me.
Here is my Sign-In Functions
GET
public function getSignIn(){
return View::make('account.signin');
}
POST
public function postSignIn() {
$validator = Validator::make( Input::only('username','password'),
array(
'username' =>'required',
'password' =>'required'
)
);
if ($validator->fails()) {
return Redirect::route('account-sign-in-post')
->with('error','Username/Password Wrong or account has not been activated !')
->withErrors($validator);
}
// Remember Me
$remember = (Input::has('remember')) ? true : false ;
$auth = Auth::attempt(array(
'username' => strtolower(Input::get('username')),
'password' => Input::get('password'),
'active' => 1),
$remember);
// Keep track on log-in information of the user.
if(Auth::check()){
$user = Auth::user();
$user->last_logged_in = Input::get('created_at');
$user->logged_in_count = $user->logged_in_count + 1 ;
$user->is_online = '1';
$user->save();
}
if($auth) {
return Redirect::to('/')
->with('success','You have been successfully logged in.')
;
}
else {
return Redirect::route('account-sign-in')
->with('error','Username/Password Wrong or account has not been activated !')
->withInput(Input::except('password'))
->withErrors($validator);
}
}
VIEW
#extends ('layouts.form')
#section('content')
<style type="text/css">
.signin{
text-align: center;
}
#forgetpassword{
/*color:#5cb85c;*/
color:silver;
}
</style>
<form class="form-horizontal" role="form" action=" {{ URL::route('account-sign-in-post')}}" method="post" >
#if ($errors->has('username')){{ $errors->first('username')}} #endif
<div class="form-group">
<label for=""> Email </label>
<input placeholder="Email" type="text" class="form-control" required name="username" {{ ( Input::old('username')) ? 'value="'.e(Input::old('username')).'"' : '' }}>
</div><br>
#if ($errors->has('password')){{ $errors->first('password')}} #endif
<div class="form-group">
<label for=""> Password </label>
<input placeholder="Password" type="password" class="form-control" required name="password">
</div><br>
<br>
<button type="submit" class="btn btn-success btn-sm btn-block ">Sign In </button>
{{ Form::token() }}
</form><br>
<div class="col-lg-12 text-center">
<a id="forgetpassword" href="{{ URL::route('account-forgot-password') }}"> Forget Password </a> <br>
</div>
#stop
I am sure that I typed in the right username and password because I double check with my database.
It keep redirecting me back to my sign-in page.
with('error','Username/Password Wrong or account has not been activated !')
Can someone please tell me, if I did anything that I’m not suppose to ?
In your situation, you should check your auth variable in your Sign_In Function.
According to your code,
$auth = Auth::attempt(array(
'username' => strtolower(Input::get('username')),
'password' => Input::get('password'),
'active' => 1),
$remember);
Keep in mind that, these are things need to make sure
username must match the database
password must match the database
user active must be 1
If any of these fail, therefore, it STOP you from signing in.
Since, you're so sure about username and password, what about user active ?
Did you check to if it's 1 ?
If Not
on your set-password function or anywhere, where you normally set your user active.
just do this :
$user->active = '1';
$user->save();
Let me know if this work!!