How to add conditions in laravel auth - laravel

I am using Laravel 5.8.
I want to add email_verified_at != null OR phone_number_verified_at != null in auth.
How do I do that?

Use this in web.php route Auth::routes(['verify' => true]);
Read this link https://laravel.com/docs/5.8/verification#verification-routing
if you are using this its check email verified or not Auth::routes(['verify' => true]);
If you want to more about go to this path in laravel project \vendor\laravel\framework\src\Illuminate\Auth and see trait MustVerifyEmail
public function hasVerifiedEmail()
{
return ! is_null($this->email_verified_at);
}
You are trying to check both
overite one method
public function hasVerifiedEmail()
{
if (!is_null($this->phone_verified_at) && !is_null($this->email_verified_at)) {
return 1;
}
}
2.step go to VerificationController
/**
* Show the email verification notice.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function show(Request $request)
{
$user = Auth::user();
if (is_null($user->email_verified_at)) {
return view('auth.verify');
}elseif (is_null($user->phone_verified_at)) {
return redirect("phone_verify");
}else{
return redirect($this->redirectPath());
}
}
go to web.php create route for phone verify
Route::get('phone_verify',function(){
dd("not verify");
});

Add attemptLogin function in LoginController, this function is called by laravel to authenticate
protected function attemptLogin(Request $request)
{
$valid = $this->guard()->attempt(
$this->credentials($request), $request->filled('remember')
);
if($valid){
$user = $this->guard()->user();
if($user->email_verified_at == null && $user->phone_number_verified_at == null ){
$this->guard()->logout();
$request->session()->invalidate();
return false;
}
}
return true;
}

Related

Restrict page if Auth::user()->id != user_id using middleware

i use middleware to restrict the admin page from non-admins, and i can restrict pages with a list of "patients" from other users by using a policy, but if i use a policy. I have to repeat the code can() method in every function. If i use middleware to check if the user_id in the url == Auth::user()->id. I do not need to repeat this, but how do i get the user_id from the url in my middleware?
the route
Route::get('/patients/{patient}', 'PatientController#edit')
What i have now
PatientPolicy
public function view(User $user, Patient $patient)
{
// does this patient belong to user
return $user->id == $patient->user_id;
}
PatientController
public function edit(Patient $patient)
{
// authenticate logged in user
$user = auth()->user();
// can the loged in user do this?(policy)
if($user->can('update', $patient)){
return view('patient.edit-patient', compact('patient', 'user'));
}
return view('403');
}
what i should have in a middleware
UserMiddleware
/**
* #param $request
* #param Closure $next
* #return mixed
*/
public static function handle($request, Closure $next)
{
if (Auth::check() && Auth::user()->id == User::patients()->user_id) {
return $next($request);
} else {
return redirect()->route('login');
}
}
Does somebody know how to check if the {patient} in the routes user_id == the logged in user()->id?
Since you have Illuminate\Http\Request object injected into handle function in middleware this is pretty straight forward to get patient id from url:
/**
* #param $request
* #param Closure $next
* #return mixed
*/
public static function handle($request, Closure $next)
{
$patientId = $request->patient; // patient id from url!
$patient = Patient::find($patientId);
if (!$patient) {
return redirect()->back()->with(['message' => 'Patient not found!']);
}
if (Auth::check() && (int) Auth::user()->id === (int) $patient->id) {
return $next($request);
} else {
return redirect()->route('login');
}
}
Thank you #Leorent,
Your answer helped me alot and this is how it got fixed
Route
Route::get('/patients/{patient}', 'PatientController#show')->middleware('user');
UserMiddeware
public static function handle($request, Closure $next)
{
$patientId = $request->patient->user_id; // user_id from patient in url!
if (Auth::check() && (int) Auth::user()->id == $patientId) {
return $next($request);
} else {
return redirect()->route('403');
}
}
Thanks again!

Socialite is not working in Laravel Middleware, How can i resolve this issue?

I am using Socialite for Google Authentication, i have an middleware for check that if user exist in my local database by their google_id, it can redirect to /home page otherwise it will redirect back to Google Authentication page, while doing this i am facing issue in middle and the error is:
Client error: POST https://www.googleapis.com/oauth2/v4/token resulted in a 400 Bad Request response: { "error": "invalid_request", "error_description": "Missing required parameter: code" }
Middleware
<?php
namespace App\Http\Middleware;
//use Socialite;
use App\GmailAccount;
use Closure;
use Laravel\Socialite\Facades\Socialite;
use Illuminate\Support\Facades\Auth;
class GoogleAuth
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$user = Socialite::driver('google')->stateless()->user();
$finduser = GmailAccount::where('google_id', $user->id)->first();
if($finduser){
return $next($request);
}
else{
return route('/logingoogle');
}
}
}
Routes
Route::group(['middleware' => 'App\Http\Middleware\GoogleAuth'], function()
{
Route::get('/home', 'HomeController#index')->name('home');
});
Route::get('/logingoogle', 'GoogleController#google_login');
Route::get('auth/google', 'GoogleController#redirectToGoogle');
Route::get('auth/google/callback', 'GoogleController#handleGoogleCallback');
HomeController
class HomeController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('googleauth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Contracts\Support\Renderable
*/
public function index()
{
$user_id=Auth::user()->id;
$user_messages=DB::table('user_message')
->join('messages', 'user_message.message_id', '=', 'messages.id')
->where([
'user_message.user_id' => $user_id,
'user_message.placeholder' => 'inbox'
])
->select('messages.*', 'user_message.message_id', 'user_message.user_id','user_message.is_read')
->orderBy('messages.id', 'DESC')
->paginate(10);
return view('website_pages.home',compact('user_messages'));
}
}
GoogleController
class GoogleController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
public function google_login(){
return view('website_pages.login_google');
}
public function redirectToGoogle()
{
return Socialite::driver('google')->stateless()->redirect();
}
/**
* Create a new controller instance.
*
* #return void
*/
public function handleGoogleCallback()
{
$login_user_id = Auth::user()->id;
try {
$user = Socialite::driver('google')->stateless()->user();
$finduser = GmailAccount::where('google_id', $user->id)->first();
if($finduser){
return redirect('/home');
}
else{
$newUser = DB::table('gmail_accounts')->updateOrInsert(
[
'email' => $user->email,
],
[
'user_id' => $login_user_id,
'email' => $user->email,
'google_id'=> $user->id,
'remember_token'=> $user->token
]
);
if ($newUser){
return redirect('/home');
}
else{
return redirect()->back();
}
Auth::login($newUser, true);
}
} catch (Exception $e) {
dd($e->getMessage());
}
}
}
GmailAccount Model
class GmailAccount extends Model
{
protected $table = 'gmail_accounts';
protected $fillable = [
'email', 'password', 'google_id', 'user_id', 'remember_token'
];
public function user()
{
return $this->belongsTo('App\User');
}
}
Can you try this?
if($finduser) {
auth()->login($finduser), true);
}
else {
return redirect('/logingoogle');
}
And include these:
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Socialite;
Follow this which is a working example:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Socialite;
use App\User;
class LoginController extends Controller
{
use AuthenticatesUsers;
public function redirectToProvider()
{
return Socialite::driver('google')->redirect();
}
public function handleProviderCallback()
{
try {
$user = Socialite::driver('google')->user();
} catch (\Exception $e) {
return redirect('/login');
}
// check if they're an existing user
$existingUser = User::where('email', $user->email)->first();
if ($existingUser) {
// log them in
auth()->login($existingUser, true);
} else {
// create a new user
$newUser = new User;
$newUser->name = $user->name;
$newUser->email = $user->email;
$newUser->google_id = $user->id;
$newUser->avatar = $user->avatar;
$newUser->avatar_original = $user->avatar_original;
$newUser->lastlogin_at = \Carbon\Carbon::now();
$newUser->save();
auth()->login($newUser, true);
}
session(['user_name' => $user->name]);
session(['user_email' => $user->email]);
session(['user_avatar' => $user->avatar]);
return redirect()->to('/home');
}
}
Route::get('/redirect', 'Auth\LoginController#redirectToProvider');
Route::get('/callback', 'Auth\LoginController#handleProviderCallback');

Argument 1 passed to Illuminate\Auth\SessionGuard::attempt() must be of the type array, object given, called in

I have the controllers below to allow the user login with laravel auth system but when the user clicks in the button "Login" I get the following error:
Argument 1 passed to Illuminate\Auth\SessionGuard::attempt() must be of the type array, object given, called in C:\laragon\www\AGRIAPP\projet investisseur\AgriApp_Investor\AgriAppInvestor\vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers.php on line 82
When I refresh the page I log in so I wanted to solve this problem
According to the documentation, the attempt function takes an array and a bool
LoginController.php
public function __construct()
{
$this->middleware('guest')->except('logout');
}
public function showLoginForm()
{
return view('auth.login');
}
protected function credentials(Request $request)
{
$credentials = array(
'slug' => $request->slug,
'password' => $request->password,
'statut' => 1,
);
if(Auth::attempt( $credentials,false ))
{
return Redirect::to( '/admin/home' );
}
}
public function username()
{
return 'slug';
}
protected function authenticated()
{
$user = auth()->user();
$user->online = true;
$user->save();
if ($user->rule->pluck( 'name' )->contains( 'abonne' )) {
return Redirect::to( '/admin-dashboard' );
}
return Redirect::to( '/admin/home' );
}
public function logout()
{
$user = Auth::user();
$user->online=false;
$user->save();
Auth::logout();
return redirect('/');
}}
AuthController.php
protected function attemptLogin(Request $request)
{
return $this->guard()->attempt(
$this->credentials($request), $request->filled('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');
}
You have overridden the credentials() method but you're not returning anything from it.
Change your credentials method to:
protected function credentials(Request $request)
{
return [
'slug' => $request->slug,
'password' => $request->password,
'statut' => 1,
];
}
I realise that you were trying to authenticate the user inside the credentials method but you don't need to as, in this case, the method calling it is doing the same.
The reason your redirect didn't work either is because the calling method wasn't returning it, so your user was getting logged in but you were actually passing the redirect response to the attempt method which is what caused your error.
Also, I'm not sure if statut is a typo or not?
If you're using laravel 8+ all you have to do is to modify your credential function
protected function credentials(Request $request)
{
if(Auth::attempt($request->all())) {
return Redirect::to( '/admin/home' );
}
}

Laravel Form Request issue with validation

I am trying to use form request in my REST API built using laravel 5.2. My controller is
public function save(SbcEntityFormRequest $request)
{
$requestData = Input::all();
try {
list($success, $message) = $this->sbcService->saveSbcEntity($requestData);
if ($success) {
return $this->successJsonResponse($request, ['id' => $message]);
}
return $this->errorJsonResponse($request, Response::HTTP_BAD_REQUEST, [$message]);
} catch (Exception $e) {
AppLog::write($e);
$message = [config('messages.save_failed')];
return $this->errorJsonResponse($request, Response::HTTP_BAD_REQUEST, $message);
}
}
My form request is
namespace App\Http\Requests;
use Illuminate\Http\Request;
class SbcEntityFormRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'logo' => 'Required',
'bio' => 'Required|Max:150'
];
}
}
My validation rules are never called. I put a die statement in authorize() function and it is neither called. When I printed $request->all() in the controller it shows empty array. Any Idea on what is wrong here?

Laravel 5 middleware auth always fails and redirects to login

I am authenticating my user and redirecting him to dashboard if credentials are correct. I want to secure the dashboard route and added middleware auth, but now it always redirects to login page.
Routes.php
Route::get('login', array('uses' => 'HomeController#showLogin'));
Route::post('login', array('uses' => 'HomeController#doLogin'));
Route::get('logout', array('uses' => 'HomeController#doLogout'));
Route::group(['middleware' => 'auth'], function() {
Route::get('/', function () {
return view('dashboard');
});
Route::get('dashboard', function () {
return view('dashboard');
});
});
HomeController.php
public function showLogin(){
return View::make('login');
}
public function doLogin(Request $request){
$rules = array(
'email' => 'required|email',
'password' => 'required|alphaNum|min:3'
);
$validator = Validator::make($request::all(), $rules);
if ($validator->fails()) {
return Redirect::to('login')
->withErrors($validator)
->withRequest($request::except('password'));
}
else {
$userdata = array(
'email' => $request::get('email'),
'password' => $request::get('password')
/*'password' => Hash::make($request::get('password'))*/
);
if (Auth::attempt($userdata)) {
$userid = Auth::id();
return redirect()->intended('/');
} else {
return Redirect::to('login');
}
}
}
public function doLogout()
{
Auth::logout();
return Redirect::to('login');
}
Middleware Authenticate.php
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');
}
}
return $next($request);
}
Middleware RedirectIfAuthenticated.php
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/');
}
return $next($request);
}
I am not sure why your code is not working, but you can try replace:
if (Auth::attempt($userdata)) {
$userid = Auth::id();
return redirect()->intended('/');
}
with:
if (Auth::attempt($userdata)) {
$userid = Auth::id();
return redirect('dashboard');
}
From the API Docs of intended method:
Create a new redirect response to the previously intended location.
is giving some error to you as it is going back to the previous location and not to the next location.
UPDATE 1:
I would have gone with the following approach.
Make your own middleware called UserAlreadyLoggedIn
php artisan make:middleware UserAlreadyLoggedIn
Open UserAlreadyLoggedIn.php and update handle method with the below code:
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(auth()->check()) {
return $next($request);
}
return redirect('login');
}
Register it in app/Http/Kernel.php file inside $routeMiddleware array:
$routeMiddleware = [
'user_already_logged_in' => \App\Http\Middleware\UserAlreadyLoggedIn::class,
];
Separate the already logged in user in controller by making UserSessionsController
php artisan make:controller UserSessionsController --plain
Inside UserSessionsController place the __constructor method:
/**
* Check if the user is already logged in.
*
* #return void
*/
public function __construct()
{
$this->middleware('user_already_logged_in');
}
routes.php
Route::get('login', 'HomeController#showLogin');
Route::post('login', 'HomeController#doLogin');
Route::get('logout', 'HomeController#doLogout');
// Replace the dashboard code inside the dashboard method..
Route::get('dashboard', 'UserSessionsController#dashboard');
Again I would have created a middleware called UserIsAGuest and would have replaced the if block inside the handle method:
if(auth()->guest()) {
return $next($request);
}
return redirect('dashboard');
And then inside the HomeController's __construct method:
/**
* Check if the user is already logged in.
*
* #return void
*/
public function __construct()
{
// Register the middleware in Kernel.php file
$this->middleware('user_is_guest');
}
Hope this helps you out. Happy Coding. Cheers.
Sorry for being late to the party, but after a long search for me, I had to change my middleware from ['middleware' => 'auth] to ['middleware' => 'auth:web']
I hope this helps out

Resources