How to customize auth controller in laravel 5.3? - php

I am facing a problem in the auth controller. I have almost made a project in Laravel 5.3. And the database is Clusterpoint. I have made a login function and its working fine. But now I try to implement the auth controller in laravel. It have already its own login and register controller and view. From one of the solution I update the login controller and custom middleware with postSignIn function. As per the solution it will override the auth login function. But when I try to do so it is not working. I am give below the already working code with out auth controller.
public function doLogin(Request $request)
{
$db_name='test_db';
$email=$_POST['email'];
$password=$_POST['password'];
$email_md5=md5($email);
$pass_md5=md5($password);
$cp = new Client();
$collection = $cp->database($db_name.".users");
$response = $collection->select('_id, email')->where('_id', '==' ,$email_md5)->where('password', '==', $pass_md5)->get();
$rawResponse = $response->rawResponse();
$data_array=json_decode($rawResponse, true);
$array_all=$data_array['results'];
//echo '<pre>'; print_r($array_all); die;
$count=$data_array['hits'];
if($count==1){
$value='on';
Session::set('s_val', $value);
Session::set('user_id', $email_md5);
Session::set('user_name', $email);
return redirect()->action('CampaignController#getIndex');
} else {
return redirect()->action('HomeController#showLogin');
}
}
Please guide me how to do the custom login function like above. Thanks in advance for the help.

Related

Laravel Socialite doesn't work on Google Chrome

I have one problem with Laravel Socialite login, in my Chrome works normally but in rest of the people browser doesn't work (works in other browsers). Before php update in server to 7.3.18 from 7.1 and update to Laravel 6 from 5.8, all works normally. I try to clear all caches, change session mode to cookie(file before), clear session and cookies in browser but nothing solved the problem.
When try to login, give me this
And this is my code:
public function loginSocial(Request $request){
$this->validate($request, [
'social_type' => 'required|in:google,facebook'
]);
$socialType = $request->get('social_type');
return Socialite::driver($socialType)->stateless()->redirect();
}
public function loginCallback(Request $request){
$socialType = $request->session()->get('social_type');
//Aparently, this get give to $socialType null in ppl browser. I dont understand why this get doesn't works.
$userSocial = Socialite::driver($socialType)->stateless()->user();
//If use 'google' instead $socialType, works fine.
$user = User::where('email',$userSocial->email)->first();
\Auth::login($user);
return redirect()->intended($this->redirectPath());
}
I understand what you are trying to do but sometimes less is more and more is less..... the call back is being made by the provider and not the user. anyway have different methods for each social login
// Google login
public function googleSocialLogin(Request $request){
Socialite::driver('google')->stateless()->redirect();
}
// Google callback
public function googleSocialLoginCallback(){
$userSocial = Socialite::driver('google')->stateless()->user();
$user = User::where('email',$userSocial->email)->first();
\Auth::login($user);
return redirect()->intended($this->redirectPath());
}
// Facebook login
public function facebookSocialLogin(Request $request){
Socialite::driver('facebook')->stateless()->redirect();
}
// Facebook callback
public function facebookSocialLoginCallback(){
$userSocial = Socialite::driver('facebook')->stateless()->user();
$user = User::where('email',$userSocial->email)->first();
\Auth::login($user);
return redirect()->intended($this->redirectPath());
}
With your methods separated you will have different routes for different social login which IMO is far better as they are have slightly different return params and you may want to perform additional function for a particular social login in future.

Unexpected behaviour from auth('api')->user() in Laravel

so i've come across what looks like a really peculiar issue. I had been using auth('api')->user() to get the user collection in a model method used by various controllers. For an API setup as a public route with api middleware its controller was using this model method and the code was only sporadically working.
I'll paste two versions of code below.
This version would sometimes return null for $user even if the user was logged in.
if(Auth::user()){
$user = Auth::user();
}elseif(auth('api')->user()){
$user = auth('api')->user();
}else{
$user = null;
}
The second version of code seems to always return the user collection for $user when the user is logged in.
$apiUser = auth('api')->user();
if(Auth::user()){
$user = Auth::user();
}elseif(auth('api')->user()){
$user = auth('api')->user();
}else{
$user = null;
}
I cannot for the life of me understand why the second version would work properly and the first wouldn't. I only stumbled accross that it worked whilst trying to debug the code. Can anyone try and explain!
You need to use Auth::check() to check if user logged in or not.
So you code will look like:
if (Auth::check()) {
$user = Auth::user();
}

Laravel 5.1: How to authenticate only active users

I want to add another condition in AuthController but I don't know how to do it.
In my Users table, I have a Active field. If a User has Active == 0, i want to not let he/she login into the system. I don't know where to add that condition in Laravel 5.1 AuthController.
Please help me with that.
Thanks a lot guys!
You can override the postLogin method of the AuthenticatesUsers trait in your AuthController:
public function postLogin(Request $request)
{
/* PLACE HERE VALIDATION CODE... */
//attempt login but not log in the user
if ( ! Auth::attempt($credentials, false, false) )
{
//wrong credentials: redirect to login
}
//CREDENTIALS OK
//get user model from last attempt
$user = Auth::getLastAttempted();
//if user is not active...
if (! $user->active)
{
//do whathever you want: for example redirect to login
}
//USER IS ACTIVE
//login the user
Auth::login($user, $request->has('remember'));
//redirect where you need
}
Check the original: vendor\laravel\framework\src\Illuminate\Foundation\Auth\AuthenticatesUsers::postLogin method, to see if you need other instructions inside your overrided method (for example input validation)
You can add your custom postLogin() function in your Auth controller which overrides the default postLogin function with this condition
Auth::attempt(array('email' => $email, 'password' => $password, 'active' => 1))
This way you will only do auth of active users only
Cheers!!
Instead of overriding the whole postLogin function, add this to your AuthController
protected function getCredentials(Request $request)
{
$crendentials=$request->only($this->loginUsername(), 'password');
$crendentials['active']=1;
return $crendentials;
}

Laravel running tests as different users

I am using Laravel 5.1 and I am trying to test my controllers.
I have several roles for my users and policies defined for different actions. Firstly, each of the requests needs to be made by an authenticated user, so running a test with no user returns a 401 Unauthorized, as expected.
But when I want to test the functionality for authorized users, I still get the 401 Unauthorized status code.
It may be worth mentioning that I use basic stateless HTTP authentication on these controllers.
I have tried the following:
public function testViewAllUsersAsAdmin()
{
$user = UserRepositoryTest::createTestAdmin();
Auth::login($user);
$response = $this->call('GET', route('users.index'));
$this->assertEquals($response->getStatusCode(), Response::HTTP_OK);
}
and
public function testViewAllUsersAsAdmin()
{
$user = UserRepositoryTest::createTestAdmin();
$response = $this->actingAs($user)
->call('GET', route('users.index'));
$this->assertEquals($response->getStatusCode(), Response::HTTP_OK);
}
and also this (in case there was anything wrong with my new user, which there shouldn't be)
public function testViewAllUsersAsAdmin()
{
$user = User::find(1);
$response = $this->actingAs($user)
->call('GET', route('users.index'));
$this->assertEquals($response->getStatusCode(), Response::HTTP_OK);
}
but in every case I get a 401 response code so my tests fail.
I can access the routes fine using postman when logging in as a dummy user.
I am running out of ideas, so any help would be appreciated.
You need to add Session::start() in the setUp function or in the beginning of the function which user need to log in.
public function setUp()
{
parent::setUp();
Session::start();
}
or
public function testViewAllUsersAsAdmin()
{
Session::start();
$user = UserRepositoryTest::createTestAdmin();
Auth::login($user);
$response = $this->call('GET', route('users.index'));
$this->assertEquals(Response::HTTP_OK, $response->getStatusCode());
}
Through some experimentation, I found that the problem lay inside my authentication middleware. Since I want the API to be stateless, the authentication looks like this:
public function handle($request, Closure $next)
{
return Auth::onceBasic() ?: $next($request);
}
And apparently, it's not possible to authenticate a user the way I was doing it.
My solution was simply to disable the middleware, using the WithoutMiddleware trait or $this->withoutMiddleware() at the beginning of each test.

Authentication with Doctrine in Zend Framework 2 Good Practices

Lets say that my page has 10 sections, in 6 of them I have to check if the user is logged in, and if not, redirect him to the "login/register" page.
I found myself repeating this code in the controller of those 6 pages:
public function actionthatneedsauthAction()
{
$sl = $this->getServiceLocator();
$authService = $sl->get('doctrine.authenticationservice.orm_default');
$user = $authService->getStorage()->read(); //is the user logged in?
if ($user) { //auth successful
//-------------/*CODE FOR THIS SPECIFIC CONTROLLER GOES HERE*/--------
return new ViewModel(array(
'user' => $user,
'somethingelse' => $somethingelse
));
} else { //auth denied
return $this->redirect()->toRoute(user, array('action' => 'login'));
}
}
I tried to encapsulate that into a service, called islogged (this is a model, not a controller), but I couldn't make it work because I couldn't find a way to redirect to a controller from inside a model, I only know how to redirect to a controller via another controller.
So in my usermanager.php I had a function like this one:
public function islogged()
{
$sl = $this->getServiceLocator();
$authService = $sl->get('doctrine.authenticationservice.orm_default');
$user = $authService->getStorage()->read(); //is the user logged in?
if ($user) { //auth successful
return $user;
} else {
/*
redirect to the login screen, dont know how to do it,
this code doesnt work here:
return $this->redirect()->toRoute(NULL, array(
'controller' => 'user',
'action' => 'login'
));
*/
}
}
so the idea was that in my controllers I only had to write:
$user = islogged();
and all the code repetition I mentioned won't be necessary anymore.
Is it a good practice what I tried to do with the usermanager.php islogged function?
If it is a good practice, how am I supposed to redirect to a controller from inside a model?
If is not a good practice, which will be the way to avoid all that code repetition that I'm having in my controllers?
I know that I can put the authentication step into the onboostrap() but in that case the auth will be triggered for all of my pages, and I just want it in some of them.
I would advise you to implement Doctrine Authentication with official DoctrineModule Authentication described in the docs folder of the repo.
Read this - Link to DoctrineModule Authentication
Then you can handle your Authentication check via the zf2 own Controller and View Helpers identity. See example in the docs here.
I use this ACL Module on my apps: https://github.com/ZF-Commons/zfc-rbac
My Customer overview controller then looks as so:
<?php
namespace RoleBasedCustomer\Controller;
use RoleBasedUser\Service\AuthenticationService;
use RoleBasedUser\Service\UserService;
use RoleBasedUser\Controller\AbstractMultiModelController;
class OverviewController extends AbstractMultiModelController
{
public function __construct(
AuthenticationService $authService,
UserService $userService
) {
$this->authService = $authService;
$this->userService = $userService;
}
public function indexAction()
{
if ( ! $this->authService->hasIdentity() ) {
return $this->redirect()->toRoute('customer/login');
}
}
}
The only thing i had to do is replace these two lines:
$authService = $this->getServiceLocator()
->get('doctrine.authenticationservice.orm_default');
$user = $authService->getStorage()->read(); //is the user logged in?
with this one:
$user = $this->identity();

Categories