Laravel custom login losses Session after redirect - laravel

i need a two way Login. First check database one if user exists and if not check database two.
So i build a custom Login Controller:
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Lang;
use Illuminate\Support\Facades\Redirect;
use App\Http\Controllers\Controller;
class CustomLoginController extends Controller
{
public function login(Request $request)
{
if($request->email) {
$credentials = $request->only('email', 'password');
if (Auth::attempt($credentials)) {
// Authentication passed...
return redirect()->intended('/');
} else {
DB::setDefaultConnection('otherdb');
if (Auth::attempt($credentials)) {
// The Login credentials will be found and user will be logged in
but after Redirect to home user isn't logged in anymore.
return redirect()->intended('/');
} else {
return redirect()->to('/login')
->withInput($request->only($credentials['email'], 'remember'))
->withErrors([
'email' => Lang::get('auth.failed'),
]);
}
}
} else {
return view('auth.login');
}
}
}
After i changed the database Connection with "DB::setDefaultConnection('otherdb');", the second login works but after Redirect to any page user isn't logged in anymore.
What am I doing wrong?
Any ideas?

Laravel trying to find a user in DB in every request. So after redirect there in no user in your default database. DB connection doesn't stored in session.
I think you need to create a custom auth guard with another user model like
class OtherUser extends Eloquent
{
protected $connection = 'otherdb';
}
and work with it.

Related

Admin Login in Laravel 8

How to set email and password to admin login using guards??
If I have to login for the 1st time in admin login portal what email and password is it going to verify with.
I tried adding record to database directly and logging in but that doesn't work.
when i try to login with email and password in the database, i get the following error
Argument 1 passed to Illuminate\Auth\EloquentUserProvider::validateCredentials() must be an instance of Illuminate\Contracts\Auth\Authenticatable, instance of App\Models\Admin given, called in C:\xampp\htdocs\Alumni datatable - Copy (2) - Copy\vendor\laravel\framework\src\Illuminate\Auth\SessionGuard.php on line 434
AdminAuthController
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Session;
class AdminAuthController extends Controller
{
public function getLogin(){
return view('admin.auth.login');
}
public function postLogin(Request $request)
{
$this->validate($request, [
'email' => 'required|email',
'password' => 'required',
]);
if(auth()->guard('admin')->attempt(['email' => $request->input('email'), 'password' => $request->input('password')])){
$user = auth()->guard('admin')->user();
if($user->is_admin == 1){
return redirect()->route('adminDashboard')->with('success','You are Logged in sucessfully.');
}
}else {
return back()->with('error','Whoops! invalid email and password.');
}
}
public function adminLogout(Request $request)
{
auth()->guard('admin')->logout();
Session::flush();
Session::put('success', 'You are logout sucessfully');
return redirect(route('adminLogin'));
}
}
you have to extends Authenticatable in your Admin Model
use Illuminate\Foundation\Auth\User as Authenticatable;
class Admin extends Authenticatable
{
}

Login and verify user - Call to a member function getKey() on null

I am trying to create a custom verification flow, where as soon as a user clicks the verification link, it logs him in and also verifies him, instead of first making him log in and only then the verification link works.
I built a custom notification URL in my CustomVerificationNotification, including the registered user_id, to login him later:
protected function verificationUrl($notifiable)
{
if (static::$createUrlCallback) {
return call_user_func(static::$createUrlCallback, $notifiable);
}
return URL::temporarySignedRoute(
'verification.custom-verify',
Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
[
'id' => $notifiable->getKey(),
'hash' => sha1($notifiable->getEmailForVerification()),
'user_id' => $this->user->id
]
);
}
Then in my web.php I added this route:
Route::get('/email/verify/{id}/{hash}/{user_id}','Auth\CustomVerifyController#login_and_verify')->name('verification.custom-verify');
Then in my CustomVerifyController:
public function login_and_verify(EmailVerificationRequest $request)
{
//..
}
But I get Call to a member function getKey() on null. And I can't edit EmailVerificationRequest, so what can I do? Is it possible to somehow call Auth::login($user); before calling the EmailVerificationRequest? (Because I have the user_id from the route)
I tried to follow the best answer from this post as well: How to Verify Email Without Asking the User to Login to Laravel
But I'm not sure then how to trigger the verify() method from the web.php and send the $request when I'm first calling the verify_and_login method
First you need verify that the URL is signed by adding the middleware signed
You don't want that anoyone having the url /email/verify/{id}/{hash}/{user_id} able to access this ressource without the signature.
web.php
Route::get('/email/verify/{id}/{hash}/{user_id}','Auth\CustomVerifyController#login_and_verify')
->middleware('signed')
->name('verification.custom-verify');
Then you need to verify that the hash correspond the user_id and for that you can use a Request or a Middleware. I think the Request fits better since Laravel already uses a Request for this.
CustomEmailVerificationRequest.php
<?php
namespace App\Http\Requests;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Http\FormRequest;
class EmailVerificationRequest extends FormRequest
{
public function authorize()
{
$user = User::findOrFail($this->route('id'));
if (! hash_equals((string) $this->route('hash'), sha1($user->getEmailForVerification()))) {
return false;
}
return true;
}
}
Finally you need to login with the user and set is email as verified
CustomVerifyController.php
public function login_and_verify(CustomEmailVerificationRequest $request)
{
$user = User::findOrFail($this->route('id'));
Auth::login($user);
$user->markEmailAsVerified();
event(new Verified($user));
...
}
[Edit to add addition feature from comments]
In order to have a middleware that verify the signed URL and resend automatically the verification email, you need to build a custom middleware.
ValidateSignatureAndResendEmailVerification.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Routing\Exceptions\InvalidSignatureException;
use URL;
class ValidateSignatureAndResendEmailVerification
{
public function handle($request, Closure $next, $relative = null)
{
if(! URL::hasCorrectSignature($request, $relative !== 'relative')( {
throw new InvalidSignatureException;
}
if (URL::signatureHasNotExpired()) {
return $next($request);
}
return redirect()->route('resend-email-confirmation');
}
}
Then you need to add the middleware to Kernel.php
Kernel.php
protected $routeMiddleware = [
...
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'signed.email' => \App\Http\Middleware\ValidateSignatureAndResendEmailVerification::class,
...
];
Then, don't forget to update your route with the new middleware
web.php
Route::get('/email/verify/{id}/{hash}/{user_id}','Auth\CustomVerifyController#login_and_verify')
->middleware('signed.email')
->name('verification.custom-verify');

laravel manually authenticate user

I want to manually login a user in laravel 8. The problem is that authentication succeeds, but the authenticated user is not stored in the session(or the session is not updated). I use the method given in de docs.
My loginController has two methods: 1) showing the login form and 2) performing the login
<?php
namespace App\Http\Controllers;
use App\Http\Requests\LoginRequest;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
public function login(){
return view('auth/login');
}
public function validateLogin(LoginRequest $request){
if (Auth::attempt(['email'=>$request->email, 'password'=>$request->password])) {
$request->session()->regenerate();
return redirect()->to('/');
}
return back()->withErrors(['credentials' => 'Deze gegevens zijn niet bekend!']);
}
}
The controller redirects indeed to / , so the user is authenticated but after the redirect the autenticated users is unavailable, so somehow it is not stored in the session.
Does anyone know how to solve this?
I removed the id from the User model as I wanted to use the e-mailadress as the primary key. This violated the Authenticable trait so the session was not updated.
The usermodel needed the following function to replace the id with the email:
public function getKeyName(){
return 'email';
}
The same can be accomplished with:
protected $primaryKey = 'email';
public $incrementing = false;

Laravel override Login controller, login(). How do i retrieve logged in user data if i overwrite the login controller. I tried to get auth() data

I used laravel like 4 years ago. Had to work on a project on laravel and tried using my own authentication methods but mybad forgot there was already inbuilt better security authentication. I understand if my question seem to be basic.
As you can see the commented line "$userID = Auth::user()->userID;" the auth() is null therefore, userID cannot get its id from null. I am unable to get user session data in any other controllers as well.
Any kind of help or suggestions is appreciated.
P.S. i have used the default login and registration inbuilt function only required function like login is override code. I am using laravel v 4.2.3. I tried passing the userid as url parameter but then discarded it as inbuilt session data makes it more secure and easier
the login function of my controller looks like this
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
use AuthenticatesUsers;
protected $redirectTo = RouteServiceProvider::HOME;
public function __construct()
{
$this->middleware('guest')->except('logout');
}
protected function login(Request $request){
$user = new User(); //my model User
$result=$user->login($request); //result has the id of the user
if ($result) {
//$userID = Auth::user()->userID;
return redirect()->route('homepage');
}else{
return redirect()->route('login');
}
}
}
model for user login()
//Auth user then let them login
public function login($request){
$email = $request->input('email');
$password = $request->input('password');
$result=DB::table('users')
->where('email', $email)
->where('password', $password)
->get();
return $result;
}
My Routes.. its default route of "Auth::routes();"
Route::get('/homepage/{userID?}', function($userID = null){
return view('index', ['userID' => $userID]);
})->name('homepage');
Route::get('/evaluate/{userID?}', function ($userID = null) {
return view('evaluate', ['userID' => $userID]);
})->name('evaluate');
I installed a fresh new laravel and tried my code again and somehow it worked. Must have made some errors when trying to override the codes. Thank you

Laravel - Attempting auth

I'm trying to manually auth my user like this :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use Auth;
use Log;
use Hash;
class UsersController extends Controller
{
public function authenticate(Request $request){
$email = $request->input('email');
$password = $request->input('password');
if (Auth::attempt(['email' => $email, 'password' => $password])) {
// Authentication passed...
return response()->json(User::find($email));
}
return response()->json(null);
}
}
I verify my request data, my database data, all is ok. I've also done a Hash::check with my user password and my request password, all is ok.
But the attempt always returning false.
Thanks !
Finally, I found it.
This was because I was attending a result but
return response()->json(User::find($email));
didn't find a user. So I change it for the following
return response()->json(User::where('email', $email)->first());
Thanks !

Resources