There are several similar questions but all of them seem incomplete as they are referring to not existing functions.
I am referring to:
Check for active user state with laravel
Login only if user is active using Laravel
extend laravel 5 built-in authentication to login only "if user == active"
In all of them there are presented solutions mostly to alter functions from AuthController, however those functions are not there.
I am using latest version of Laravel (5.2) so my default mentioned file looks like: https://github.com/laravel/laravel/blob/master/app/Http/Controllers/Auth/AuthController.php
Now, how do I implement this functionality? I have tried copying public function postLogin() (as suggested in those other mentioned posts) into that AuthController file. Nothing changed.
I am clearly missing something here.
Please someone help!
Edit:
The function that I have added is:
public function postLogin(Request $request)
{
$this->validate($request, [
'email' => 'required|email', 'password' => 'required',
]);
$credentials = $this->getCredentials($request);
// This section is the only change
if (Auth::validate($credentials)) {
$user = Auth::getLastAttempted();
if ($user->active) {
Auth::login($user, $request->has('remember'));
return redirect()->intended($this->redirectPath());
} else {
return redirect($this->loginPath()) // Change this to redirect elsewhere
->withInput($request->only('email', 'remember'))
->withErrors([
'active' => 'You must be active to login.'
]);
}
}
return redirect($this->loginPath())
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => $this->getFailedLoginMessage(),
]);
}
Most functionality in AuthController is added using traits. Note this line in the beginning of the class:
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
If you look at AuthenticatesAndRegistersUsers you can see that it does have a postLogin method.
As of why implementing this method doesn't work: I think you are missing the $request parameter in the method signature.
Add a larger code snippet to your question if this isn't the case.
EDIT: for future debugging: php artisan route:list gives you a list of which routes call which methods. This can give you a hint to which method to override.
So, for everyone facing the same problem on Laravel 5.2 with Authentication provided by php artisan make:auth.
First important thing is to understand that Route::auth(); points to login function and not postLogin(Thank you #lagbox!)
Then you will have to update AuthController:
Add on top of the file:
use Auth;
use Illuminate\Http\Request;
Add somewhere after use AuthenticatesAndRegistersUsers, ThrottlesLogins; :
/**
* Where to redirect users if login is unsuccessufull.
*
* #var string
*/
protected $loginPath = '/login';`
And the updated login function:
public function login(Request $request)
{
$this->validate($request, [
'email' => 'required|email', 'password' => 'required',
]);
$credentials = $this->getCredentials($request);
// This section is the only change
if (Auth::validate($credentials)) {
$user = Auth::getLastAttempted();
if ($user->active) {
Auth::login($user, $request->has('remember'));
return redirect()->intended($this->redirectPath());
} else {
return redirect($this->loginPath) // Change this to redirect elsewhere
->withInput($request->only('email', 'remember'))
->withErrors([
'active' => 'You must be active to login.'
]);
}
}
return redirect($this->loginPath)
->withInput($request->only('email', 'remember'))
->withErrors([
'email' => $this->getFailedLoginMessage(),
]);
}
Then login.blade.php should be updated to show the new error #if ($errors->has('active'))
Thank you guys for help!
Related
I have a login form on my welcome page that POSTs to the login route
If there are errors, I want them to show on the login page, not go back to the welcome page. The problem is that if there are errors, it is going back to the welcome page.
I looked through the code and it looks like back() is responsible for this, so I narrowed it down to the session previousUrl. I've tried using session()->setPreviousUrl(route('login')) in my welcome page controller, but did not resolve the issue.
How do I make it so it will show the errors on the login page even if the user is attempting to login from the welcome page?
Edit: This is a Laravel app which is using the built-in auth scaffolding for the login.
Thank you to #atymic for his help but I figured it out this way (which is very similar):
protected function validateLogin(Request $request)
{
$validator = Validator::make($request->all(), [
$this->username() => 'required|string',
'password' => 'required|string',
]);
if ($validator->fails()) {
throw (new ValidationException($validator))->redirectTo(route('login'));
}
}
protected function sendFailedLoginResponse(Request $request)
{
throw ValidationException::withMessages([
$this->username() => [trans('auth.failed')],
])->redirectTo(route('login'));
}
Need to throw an exception on validateLogin as just returning a redirect does nothing.
You can fix this by overriding the validateLogin and sendFailedLoginResponse functions on the controller.
protected function validateLogin(Request $request)
{
$validator = Validator::make($request->all(), [
$this->username() => 'required|string',
'password' => 'required|string',
]);
if ($validator->fails()) {
return redirect('login')
->withErrors($validator)
->withInput();
}
}
protected function sendFailedLoginResponse(Request $request)
{
throw new ValidationException::withMessages([
$this->username() => [trans('auth.failed')],
])->redirectTo(route('login'));
}
My expected result is to have the user redirected to my homepage after facebook login. I am using Socialite, Laravel 5.4, and Xampp. After being able to login through facebook, my url is now in callback in which the callback is calling the logincontroller that redirects to the homepage. So problem is after redirected to homepage, my url has now some hashed value. localhost/sampleProject/public/login/facebook/callback?code=AQBZpjdW... and when I reload page it shows error invalid state exception in abstractprovider.php. Am I missing something in my functions?
Inside my login controller
public function redirectToProvider()
{
return Socialite::driver('facebook')->redirect();
}
/**
* Obtain the user information from facebook.
*
* #return Response
*/
public function handleProviderCallback()
{
$user = Socialite::driver('facebook')->user();
return view('user-profile', compact('user',$user));
}
Inside my services.php file
'facebook' => [
'client_id' => 'insert_app_id_here',
'client_secret' => 'enter_app_secret_here',
'redirect' => 'http://localhost/sampleProject/public/login/facebook/callback',
],
Inside my routes/web.php
Route::get('login/facebook', 'Auth\LoginController#redirectToProvider');
Route::get('login/facebook/callback', 'Auth\LoginController#handleProviderCallback');
I also have included these in my config/app.php
Laravel\Socialite\SocialiteServiceProvider::class,
and
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
You could try this thing)
public function handleProviderCallback(Request $request)
{
session()->put('state', $request->input('state'));
$user = Socialite::driver('facebook')->user();
return view('user-profile', compact('user',$user));
}
First of all, run the following command:
composer require laravel/socialite
After that In app/config.php add the following line in providers.
Laravel\Socialite\SocialiteServiceProvider::class,
After that In app/config.php add the following line in aliases
'Socialite' => Laravel\Socialite\Facades\Socialite::class,
In config/services.php add:
//Socialite
'facebook' => [
'client_id' => '1234567890444',
'client_secret' => '1aa2af333336fffvvvffffvff',
'redirect' => 'http://laravel.dev/login/callback/facebook',
],
Now create two routes, mine are like these:
//Social Login
Route::get('/login/{provider?}',[
'uses' => 'AuthController#getSocialAuth',
'as' => 'auth.getSocialAuth'
]);
Route::get('/login/callback/{provider?}',[
'uses' => 'AuthController#getSocialAuthCallback',
'as' => 'auth.getSocialAuthCallback'
]);
You also need to create controller for the routes above like so:
<?php namespace App\Http\Controllers;
use Laravel\Socialite\Contracts\Factory as Socialite;
class AuthController extends Controller
{
public function __construct(Socialite $socialite){
$this->socialite = $socialite;
}
public function getSocialAuth($provider=null)
{
if(!config("services.$provider")) abort('404'); //just to handle providers that doesn't exist
return $this->socialite->with($provider)->redirect();
}
public function getSocialAuthCallback($provider=null)
{
if($user = $this->socialite->with($provider)->user()){
dd($user);
}else{
return 'something went wrong';
}
}
}
and finally, add Site URL to your Facebook App. I followed this article for the proposed solution above. https://www.cloudways.com/blog/social-login-in-laravel-using-socialite/
I'm building a Laravel 5.3 app and using the basic auth of laravel (artisan make:auth). Now, the "Forgot Password" functionality works fine, so if a user can't login because he doesn't know his password, he can get a mail to reset it. But now I want that logged in users can change their password as well. I found that, but this doesn't really help me. I also know that there's a ResetsPasswords trait but how do I use it? And is there already a view as well I can use?
Can somebody help me here?
You don't actually need to use the default password controller to achieve this, you can write your own function to get the same result, for example:
public function postUpdatePassword() {
$user = Auth::user();
$password = $this->request->only([
'current_password', 'new_password', 'new_password_confirmation'
]);
$validator = Validator::make($password, [
'current_password' => 'required|current_password_match',
'new_password' => 'required|min:6|confirmed',
]);
if ( $validator->fails() )
return back()
->withErrors($validator)
->withInput();
$updated = $user->update([ 'password' => bcrypt($password['new_password']) ]);
if($updated)
return back()->with('success', 1);
return back()->with('success', 0);
}
As you can see I registered a new custom validation rule to check if the new passowrd match the old one, to register the rule just go to "app/Providers/AppServiceProvider.php" and add to the boot function the next lines:
Validator::extend('current_password_match', function($attribute, $value, $parameters, $validator) {
return Hash::check($value, Auth::user()->password);
});
Now the validation rule works but you won't get the error message, to add an error message to the new rule you just created you will have to modify these lines in "resources/lang/en/validation.php":
'custom' => [
'current_password' => [
'current_password_match' => 'Current password is incorrect.',
],
],
That's it, now you can use this function to change your the current user password :)
If you want to keep your AppServiceProvider.php file clean of closures (for whatever reason; personally I like these small files neat and tidy) you can add perform the following two things:
1) Add the following to the boot() method of the AppServiceProvider.php
Validator::extend('current_password_match', 'App\Validators\PasswordMatch#check');
2) Add a new file 'app/Validators/PasswordMatch.php' in line with the closure mentioned above.
<?php
namespace App\Validators;
use Hash;
use Auth;
class PasswordMatch
{
public function check($attribute, $value, $parameters, $validator){
return Hash::check($value, Auth::user()->password);
}
}
You can then also add the validation rule messages to your extended FormRequest class messages() method like:
'current_password_match' => 'Current password is incorrect',
Pulling my hair out over what seems a simple task. I use the username instead of email in my AuthController using the following code:
/**
* Set the login system to use username instead of email address
* #var string
*/
protected $username = 'username';
This has worked fine for a long time (when I wasn't planning on users activating their accounts). However, now I need users to activate their accounts, I know I need to do additional checks on login before they can see their dashboard.
I have modified the postLogin() method below, to what I thought would be correct:
public function postLogin(Request $request)
{
$this->validate($request, [
'username' => 'required', 'password' => 'required',
]);
$credentials = $request->only('username', 'password');
$credentials = array_add($credentials, 'confirmed', '1');
if ($this->auth->attempt($credentials, $request->has('remember')))
{
return redirect()->intended($this->redirectPath());
}
return redirect($this->loginPath())
->withInput($request->only('username', 'remember'))
->withErrors([
'username' => $this->getFailedLoginMessage(),
]);
}
But all I get is the following error:
Undefined property: App\Http\Controllers\Auth\AuthController::$auth
What is it that i'm doing wrong?
Andy
Just one glitch that I see there.
if ($this->auth->attempt($credentials, $request->has('remember')))
should be
if (Auth::attempt($credentials, $request->has('remember')))
In Laravel 5.1, the $auth attribute does not exist in the AuthController class constructor, as explained in the 5.1 upgrade guide. So you're referencing a property which does not exist.
I use dsdevbe/ldap-connector for Laravel authentication. For this purpose I used the default AuthController and added the postLogin method from AuthenticatesAndRegistersUsers with following changes:
public function postLogin(Request $request)
{
$this->validate($request, [
'username' => 'required',
'password' => 'required',
]);
$credentials = $request->only('username', 'password');
if ($this->auth->attempt($credentials))
{
return redirect()->intended('/dashboard');
}
return redirect($this->loginPath())
->withInput($request->only('username'))
->withErrors([
'username' => 'Benutzername oder Passwort falsch.',
]);
}
The $this->auth->attempt() works fine, when I use incorrect credentials I'm getting redirected to auth/login with an error. When I use correct credentials I'm getting redirected to /dashboard, but the sessions doesn't seem to work properly, because I get a reredirect to auth/login. When I try to dd($this->auth->check()); the output is true before, and false after the redirect to dashboard.
Anybody know the issue and can help with that?
Sessions works well, tested with session(['test' => true]); under attempt() and with #if(session('test')) {{ "works" }} #endif in auth/login blade template.
Thanks.