laravel5.1 Manually Authenticating Users - php

In my app I use the default authentification to login my users to their dashboard.
Now I would like to create a backend for supporters and one for admins.
I use this code at the moment to login as admin:
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use App;
use Artisan;
use Validator;
use Auth;
class AdminLoginController extends Controller
{
public function index()
{
return view('admin.login');
}
public function authenticate(Request $request)
{
if (Auth::attempt(['username' => $request->username, 'password' => $request->password, 'id' => 1]))
{
// Authentication passed...
dd("correct");
}
else
{
dd("login data incorrect!");
}
}
}
How can I use now the well known redirects after login.
In my AuthController I use for the users I use this code:
/**
* Where to redirect users after login / registration.
*
* #var string
*/
protected $redirectTo = '/dashboard';
protected $redirectAfterLogout = 'auth/login';
protected $redirectPath = '/dashboard';
1.) How can I use this in my code above? I would like to redirect admins logged into the app like users to specified urls using this laravel feature.
2.) What's the best way, to check more "ids" in the if statement? Because there will be more than one admin.

first of all you are checking username, password along with a ID. So only user with Id = 1 is going to be authenticated by your function. You dont need to put an id check there.
Now for the redirect you can make a function which returns back the url based on the user type. Here is a very basic example`
public function getRedirectUrl(){
if(auth()->user()->isAdmin()){
return url('/admin-dashboard');
}
elseif(auth()->user()->isUser()){
return url('/user-dashboard')
}
}
Make sure you have isAdmin() and isUser() function defined in your User model like
public function isAdmin(){
return $this->user_type == UserType::ADMIN;
}
So in your authentication function just do return redirect($this->getRedirectUrl())

Related

User wise redirect after Login Using Laratrust

I am new in Laravel. I am trying laratrust for role wise authentication. Can any one tell me, how to redirect user according to their role after login.
I.E:
Admin User
Redirect to : /admin
Employee User
Redirect to: /employee
There's no need to overwrite the entire login logic, if you source dive into the Framework you'll see that Laravel uses the following to determine the redirect path after the login.
/**
* Get the post register / login redirect path.
*
* #return string
*/
public function redirectPath()
{
if (method_exists($this, 'redirectTo')) {
return $this->redirectTo();
}
return property_exists($this, 'redirectTo') ? $this->redirectTo : '/home';
}
So all you need to do is add a redirectTo() method to your app\Http\Controllers\Auth\LoginController.php and put your custom logic in that method where you should be able to use $this->guard()->user() to get the authenticated user and generate the custom logic that you need to implement.
/**
* Get the post register / login redirect path.
*
* #return string
*/
public function redirectTo()
{
if ($this->guard()->user()->hasRole('admin')) {
return '/admin';
}
return '/employee';
}
I have used something like this in laravel 5.4.35
I have overwrite laravel login function.
This is some code segment of my Auth/LoginController.php
But you have to do something, before asking for the the whole answer.
Find about how to overwrite Laravel default login function.
<?php
namespace App\Http\Controllers\Auth;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Auth;
use Illuminate\Support\Facades\Lang;
class LoginController extends Controller
{
public function login(Request $request)
{
//validate the form data
$this->validate($request,[
'email'=> 'required|email',
'password'=> 'required|min:8|max:16'
]);
if($this->hasTooManyLoginAttempts($request)){
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
if (Auth::validate(['email'=>$request->email,'password'=>$request->password])){
$user = Auth::getLastAttempted();
if(Auth::attempt(['email'=>$request->email,'password'=>$request->password],$request->remember)){
$this->clearLoginAttempts($request);
$role="";//yo have to catch user roles acording to your system.
if($role==1){// then use the conditional logic to redirect.
return redirect('/admin');
}elseif($role==2){
return redirect('/employee');
}
}
$this->incrementLoginAttempts($request);
return redirect()->back()->withInput($request->only('email','remember'))->withErrors([
'err' => 'Matching credential not found'
]);
}
$this->incrementLoginAttempts($request);
return redirect()->back()->withInput($request->only('email','remember'))->withErrors([
'err' => 'Matching credential not found'
]);
}
}

Auth::user & sessions with Socialite

FIXED THE ISSUE
I had <a href='{{ Auth::logout }}'>Logout</a> which caused every page to log the user out.
app/Http/Controllers/SocialAuthFacebookController.php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Socialite;
use App\Services\SocialFacebookAccountService;
use Auth;
class SocialAuthFacebookController extends Controller
{
/**
* Create a redirect method to facebook api.
*
* #return void
*/
public function redirect()
{
return Socialite::driver('facebook')->redirect();
}
/**
* Return a callback method from facebook api.
*
* #return callback URL from facebook
*/
public function callback(SocialFacebookAccountService $service)
{
$user = $service->createOrGetUser( Socialite::driver('facebook')->user() );
Auth::login($user,true);
return redirect()->to('/');
}
}
app/SocialFacebookAccount.php
namespace App;
use Illuminate\Database\Eloquent\Model;
class SocialFacebookAccount extends Model
{
protected $fillable = ['user_id', 'provider_user_id', 'provider'];
public function user()
{
return $this->belongsTo(User::class);
}
}
app/Services/SocialFacebookAccountService.php
namespace App\Services;
use App\SocialFacebookAccount;
use App\User;
use Laravel\Socialite\Contracts\User as ProviderUser;
class SocialFacebookAccountService
{
public function createOrGetUser(ProviderUser $providerUser)
{
$account = SocialFacebookAccount::whereProvider('facebook')
->whereProviderUserId($providerUser->getId())
->first();
if ($account) {
return $account->user;
} else {
$account = new SocialFacebookAccount([
'provider_user_id' => $providerUser->getId(),
'provider' => 'facebook'
]);
$user = User::whereEmail($providerUser->getEmail())->first();
if (!$user) {
$user = User::create([
'email' => $providerUser->getEmail(),
'name' => $providerUser->getName(),
'password' => md5(rand(1,10000)),
'image' => $providerUser->getAvatar(),
]);
}
$account->user()->associate($user);
$account->save();
return $user;
}
}
}
I am currently using Facebook and that works out so this is not what I'm asking.
I have this snippet on my master.blade.php and it works when I first sign into Facebook however when I go onto another page, such as /about it logs me out. I've tried Auth::viaRemember but this does nothing.
How do I store the user's credential in a session so that users won't get logged out just for moving to another page?!
The facebook api will valid your request and give some basic user details only..you have to store the user details in your db first(after fb api request successfull) and then you have to start session with saved user id (Using AuthLoginUsingID function).

How to use middleware for custom UserProvider in Laravel 5.5?

I'm new to Laravel (5.5) and want to create an application with a custom authentication mechanism:
If the user is not logged in, he/she should be redirected to /login.
I want to use the session-guard.
I have written and registered custom classes
LdapUser extends Illuminate\Auth\GenericUser and
LdapUserProvider implements Illuminate\Contracts\Auth\UserProvider. Actually both are dummy implementations at the moment that return generic objects. Later, I want to check, if the user exists in my external ldap-directory and if the credentials are valid. Registration, internal user management or password reset are not intended. I just want to use the user's name and some properties in my blade templates.
I modified config/app.php and config/auth.php, so that this provider can be used.
Now, I wonder how to proceed in order to actually use the authentication and access the LdapUser in my blade templates. I tried {{ Auth::user()->name }}, which led to this error message: "Trying to get property of non-object."
How to I tell my app to check, if a valid session exists and otherwise redirect to the login page?
How can I access the user's properties inside the blade templates?
This is my route:
Route::group(['middleware' => 'auth'], function () {
Route::get('/helloworld', function () {return 'Hello World!';});
});
Route::get('/login', 'LdapLoginController#showLoginForm')->name('showLoginForm');
/helloworld now redirects to /login where I see the login-form, which is going to be handled by the LdapLoginController:
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
class LdapLoginController extends Controller
{
use AuthenticatesUsers;
}
I would now expect that the session guard uses the LdapUserProvider to check the credentials:
namespace App\Providers;
use App\LdapUser;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Contracts\Auth\UserProvider;
class LdapUserProvider implements UserProvider
{
public function retrieveById($id)
{
return $this->dummyUser();
}
public function retrieveByCredentials(array $credentials)
{
return $this->dummyUser();
}
public function validateCredentials(Authenticatable $user, array $credentials)
{
return true;
}
public function retrieveByToken($identifier, $token)
{
return new \Exception('not implemented');
}
public function updateRememberToken(Authenticatable $user, $token)
{
return new \Exception('not implemented');
}
protected function dummyUser()
{
$attributes = array(
'id' => 123,
'username' => 'chuckles',
'password' => \Hash::make('SuperSecret'),
'name' => 'Dummy User',
);
return new LdapUser($attributes);
}
}
Unfortunately, after submitting the login form, I'm always redirected back to /login, no matter what I enter :-(
Any help is greatly appreciated!

Laravel: Integrating Throttle in Custom Login

How to integrate laravel throttle if I did not use the default LoginController given by laravel?
here's my controller:
use AuthenticatesUsers;
//function for login
public function login(Request $requests){
$username = $requests->username;
$password = $requests->password;
/**to login using email or username**/
if(filter_var($username, FILTER_VALIDATE_EMAIL)) {
Auth::attempt(['email' => $username, 'password' => $password]);
} else {
Auth::attempt(['username' => $username, 'password' => $password]);
}
if(Auth::check()){
if(Auth::user()->type_user == 0){
return view('users.dashboard');
}
else{
return view('admin.dashboard');
}
}
else{
return Redirect::back()->withInput()->withErrors(['message'=>$login_error],'login');
}
}
I want to limit the failed logins but I can't seem to make it work using my own controller. Can you guys help me please?
add the following code inside your method. make it the first thing
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
now add the following code where log in fails. this will increment the failed attempt count.
$this->incrementLoginAttempts($request);
on successful login, add the following code so it resets.
$this->clearLoginAttempts($request);
Try adding throttling to your controller's constructor, like so:
/**
* Create a new login controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('throttle:3,1')->only('login');
}
Unfortunately, the Laravel docs don't say much about throttling:
https://laravel.com/docs/6.x/authentication#login-throttling
However, the 3,1 part of the string corresponds to a maximum of 3 tries with a decay time of 1 minute.
throttle could be defined in /project-root/laravel/app/Http/Kernel.php in the routeMiddleware array like so:
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,.
The Laravel documentation explains this method here: https://laravel.com/docs/6.x/middleware#assigning-middleware-to-routes
use Trait ThrottlesLogins present in Illuminate\Foundation\Auth and override the 2 functions as mentioned below. I have tested it on Laravel 5.6 and working fine.
public function maxAttempts()
{
//Lock out on 5th Login Attempt
return 5;
}
public function decayMinutes()
{
//Lock for 1 minute
return 1;
}
Although, this answer is very late, but here is , what i did, and it worked. I hope it helps you too. I am using laravel 5.2.
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\MessageBag;
use Cookie;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class UserController extends Controller
{
/** Add This line on top */
use AuthenticatesAndRegistersUsers,ThrottlesLogins;
/** This way, you can control the throttling */
protected $maxLoginAttempts=3;
protected $lockoutTime=300;
public function postUserSignIn(Request $request)
{
/** This line should be in the start of method */
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
/** Validate the input */
$validation = $this->validate($request,[
'email' => 'required|email',
'password' => 'required|min:4'
]);
/** Validation is done, now login user */
//else to user profile
$check = Auth::attempt(['email' => $request['email'],'password' => $request['password']]);
if($check){
$user = Auth::user();
/** Since Authentication is done, Use it here */
$this->clearLoginAttempts($request);
if ($user->role == 1 || $user->role == 2){
if(Session::has('cart')){
return redirect()->route('cart');
}
return redirect()->intended();
}elseif($user->role == 99) {
return redirect()->route('dashboard');
}
}else{
/** Authentication Failed */
$this->incrementLoginAttempts($request);
$errors = new MessageBag(['password' => ['Email and/or Password is invalid']]);
return redirect()->back()->withErrors($errors);
}
}
}
Route::post('login', ['before' => 'throttle:2,60', 'uses' => 'YourLoginController#Login']);
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return redirect()->route('login')->with('alert-warning', 'Too many login attempts');
}
protected function hasTooManyLoginAttempts(Request $request)
{
$maxLoginAttempts = 3;
$lockoutTime = 1; // In minutes
return $this->limiter()->tooManyAttempts(
$this->throttleKey($request), $maxLoginAttempts, $lockoutTime
);
}
try my version:
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller{
use AuthenticatesUsers;
public function login(Request $request){
if($this->hasTooManyLoginAttempts($request)){
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}else{
if (Auth::attempt(['username' => $request->login_username, 'password' => $request->login_password])) {
session()->put(['username'=>Auth::user()->username,'userid'=>Auth::user()->id]);
return redirect()->intended('anydashboard');
}else{
$this->incrementLoginAttempts($request);
//my '/' path is the login page, with customized response msg...
return redirect('/')->with(['illegal'=>'Login failed, please try again!'])->withInput($request->except('password'));
}
}
}
}
in order to use Eloquent Model Auth (which is default), your AUTH_MODEL should implements AuthenticatableContract, so double check your model:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract,CanResetPasswordContract
{
use Authenticatable, CanResetPassword;
//protected $fillable = [];
...
}

set custom sql for Authorization in Laravel 5

I am new on Laravel and use Authorization. I am looking for the way to change default sql for Auth. Actually, Laravel does it using this simple sql command at below:
SELECT * FROM users WHERE login="something" AND password = "something" LIMIT 1
I am trying to change default sql like this:
SELECT
u.id, u.name, c.company
FROM
users u, companies c
WHERE
u.login="something" AND
u.password = "something" AND
u.companyId = c.id
LIMIT 1
I understood that I should create custom Authorization system: crate new user Provider and Auth Provider.
Firstly, I created Auth folder inside App and added there CustomUserProvider.php
CustomUserProvider.php
<?php namespace App\Auth;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Contracts\Auth\UserProvider as UserProviderInterface;
use App\Models\User;
class CustomUserProvider implements UserProviderInterface {
protected $model;
public function __construct(UserContract $model)
{
$this->model = $model;
}
public function retrieveById($identifier)
{
}
public function retrieveByToken($identifier, $token)
{
}
public function updateRememberToken(UserContract $user, $token)
{
}
public function retrieveByCredentials(array $credentials)
{
}
public function validateCredentials(UserContract $user, array $credentials)
{
}
}
My customAuthProvider.php file, in App/Providers:
<?php namespace App\Providers;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use App\Auth\CustomUserProvider;
use Illuminate\Support\ServiceProvider;
class CustomAuthProvider extends ServiceProvider {
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
$this->app['auth']->extend('custom',function()
{
return new CustomUserProvider(new User);
});
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
//
}
}
At the end I set driver to custom in config/Auth.php
'driver' => 'custom'
I am looking for the way using this custom classes how can I use custom sql command for Authorization (Login)?
Or maybe this way is wrong?
If all you need are additional constraints on the query that fetches user from the database during authentication, there is much simpler way to do that.
First of all, Laravel offers an AuthenticatesUsers trait that you can use in your controller to handle authentication requests. The default implementation fetches user from the database using username field and then, if matching user is found, it validates their password.
The list of attributes that is used to fetch user from the database can be customized by overriding getCredentials method in your controller. In your case the following should be enough to load user using their username and company id:
protected function getCredentials(Request $request)
{
return $request->only($this->loginUsername(), 'password', 'companyId);
}
Once you add that, user should provide their username, companyId and password in the login form and they will be authenticated only if there exists a user with given username that belongs to given company and the password provided is valid.
UPDATE: If you decide not to use the trait, but want to authenticate users manually, you can do so in a really similar manner. When calling Auth::attempt() you just need to pass all the criteria that should be used to authenticate the user, e.g.:
Auth::attempt([
'username' => Input::get('username'),
'companyId' => Input::get('companyId'),
'password' => Input::get('password')
]);
I tried this package and it helped me:
https://github.com/ollieread/multiauth/

Categories