Laravel, Socialite & Middleware Infinite Redirect Loop - php

I followed the laracasts tutorial on Socialite. My ultimate aim is to connect to azure ad, but I was having problems with various aspects of that so I thought I'd start with his github tutorial and get it working in principle first. I was fine until I tried to use middleware - now I get caught in infinite redirect loops. If I break out of the loop and go to the homepage, it has successfully logged me in - but obviously the user won't know that and will think it's failed.
Any help would be greatly appreciated.
Ed.
AuthController:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\AuthenticateUser;
class AuthController extends Controller {
public function login(AuthenticateUser $authenticateUser, Request $request) {
$authenticateUser->execute($request->has('code'), $this);
return \Socialite::with('github')->redirect();
}
public function logout() {
if (\Auth::check()) \Auth::logout();
return view('auth.loggedout');
}
}
AuthenticateUser:
<?php
namespace App;
use Illuminate\Contracts\Auth\Guard;
use Laravel\Socialite\Contracts\Factory as Socialite;
use App\Repositories\UserRepository;
use Request;
class AuthenticateUser {
private $socialite;
private $auth;
public function __construct(UserRepository $users, Socialite $socialite, Guard $auth) {
$this->users = $users;
$this->socialite = $socialite;
$this->auth = $auth;
}
public function execute($hasCode) {
if (!$hasCode) {
return $this->getAuthorizationFirst();
}
$user = $this->users->findbyEmail($this->getUser());
$this->auth->login($user, true);
return redirect('/');
}
public function getAuthorizationFirst() {
return $this->socialite->driver('github')->redirect();
}
public
function getUser() {
return $user = $this->socialite->driver('github')->user();
}
}
routes.php:
Route::get('o365/connect', 'AuthController#login');
Route::get('o365/callback', 'AuthController#login');
Route::get('auth/logout', 'AuthController#logout');
Authenticate Middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Authenticate {
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth) {
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next) {
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('o365/connect');
}
}
if (\Auth::check()) {
return $next($request);
}
}
}

Related

Laravel 5.4, Login page keep redirecting

I'm having an issue where a login page keeps redirecting me back to login instead of going to the HomePage.
My Routes file:
Route::group(['middleware' => ['auth']], function () {
Route::get('/', function () {
return redirect()->route('dash');
});
Route::get('dash', 'DashController#index')->name('dash');
});
Route::get('login', ['as' => 'login', 'uses' => 'LDAPAuthController#index']);
Route::post('login', 'LDAPAuthController#login');
Everything else is set to its normal default setting:
RedirectIfAuthenticated Middleware:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/home');
}
return $next($request);
}
}
My login controller:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Input;
use Illuminate\Http\Request;
use App\Services\CakePHPHash;
use App\Users;
use Redirect;
use Auth;
use View;
class LDAPAuthController extends Controller {
public function login(Request $request) {
$user = Users::where('email', strtolower($request->email))->first();
$hash = new CakePHPHash;
if(($hash->hash($request->password, null, true)) !== $user->password) {
return back()->with('error', 'Username and/or password are incorrect.');
}
Auth::login($user);
return Redirect::to('/');
}
public function logout() {
Auth::logout();
Session::flush();
return back()->with('error', 'You just logged out.');
}
public function index(Request $request) {
return View::make('auth.login');
}
}
My Sample Dash Controller:
<?php
namespace App\Http\Controllers;
use \App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Input;
use Auth;
class DashController extends Controller {
public function index() {
return view('Home.home');
}
}
I simplified my Users model down to just changing primary and table name:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Session;
use Auth;
class Users extends Authenticatable
{
protected $table = 'users';
protected $primaryKey = 'user_id';
public function getRememberToken()
{
return null; // not supported
}
public function setRememberToken($value)
{
// not supported
}
public function getRememberTokenName()
{
return null; // not supported
}
/**
* Overrides the method to ignore the remember token.
*/
public function setAttribute($key, $value)
{
$isRememberTokenAttribute = $key == $this->getRememberTokenName();
if (!$isRememberTokenAttribute)
{
parent::setAttribute($key, $value);
}
}
}
This isn't the first I'll be making an App in Laravel, but this is giving me headaches unlike before. Another piece of info I'm concerned about is that the $user gives out the right user and user_id, but the login_web_ session is giving out a different one (not the right user_id) from debugbar. Auth::check() returns true though.

Laravel login will not redirect after login

Everyone. I have been stuck with Laravel redirecting after login. The connection works and after I login it redirects to a blank page but if I change the url path I can access the different web pages. Any assistance would be highly appreciated! I am using LDAP to connect and it is working.
On my AuthController I have the protected $redirectTo paths set. See picture below.
Please let me know if there is any other code I should provide.
Thank you!!!
(RedirectIfAuthenticated.php)
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
protected $auth;
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/computers/create');
}
return $next($request);
}
}
My Routes
Route::group(['middleware' => ['web']], function () {
Route::auth();
Route::get('login', 'LoginController#index');
Route::post('login', 'LoginController#check_password');
Route::patch('computers/{inventories}', 'InventoriesController#update');
Route::get('computers/search', 'InventoriesController#search');
Route::resource('computers', 'InventoriesController');
});
Route::get('/home', 'HomeController#index');
loginController.php
<?php namespace App\Http\Controllers;
/**
* #class Login
*/
use App\User;
use Illuminate\Http\Request;
class Login extends Controller
{
/**
* Show the application dashboard to the user.
*
* #return Response
*/
public function index()
{
return view('auth.login');
}
public function check_password(Request $req)
{
//die('has to stop here');
$user = User::check_password($req);
//var_dump($user); die;
if ($user)
{
return redirect('/computers/create');
}
else
{
return redirect('login')->with('message', 'Login Failed');
}
}
}
AuthController.php
<?php
namespace App\Http\Controllers\Auth;
use App\User;
use Validator;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class AuthController extends Controller
{
/*
|--------------------------------------------------------------------------
| Registration & Login Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users, as well as the
| authentication of existing users. By default, this controller uses
| a simple trait to add these behaviors. Why don't you explore it?
|
*/
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
/**
* Where to redirect users after login / registration.
*
* #var string
*/
protected $redirectTo = '/computers/create';
protected $redirectAfterLogout = '/login';
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct()
{
//$this->auth = $auth;
//$this->registrar = $registrar;
$this->middleware($this->guestMiddleware(), ['except' => 'logout']);
}
/**
* Get a validator for an incoming registration request.
*
* #param array $data
* #return \Illuminate\Contracts\Validation\Validator
*/
//Using Ldap
// protected function validator(array $data)
// {
// return Validator::make($data, [
// 'name' => 'required|max:255',
// 'email' => 'required|email|max:255|unique:users',
// 'password' => 'required|min:6|confirmed',
// ]);
//}
/**
* Create a new user instance after a valid registration.
*
* #param array $data
* #return User
*/
//Removed b/c LDAP is being usedcd
// protected function create(array $data)
// {
// return User::create([
// 'name' => $data['name'],
// 'email' => $data['email'],
// 'password' => bcrypt($data['password']),
// ]);
// }
}
InventoriesController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use DB;
use App\Inventory;
use App\Http\Requests\InventoryRequest;
class InventoriesController extends Controller
{
public function __construct()
{
//$this->middleware('auth'); //does not allow users to login, redirects back to login when using LDAP credentials
}
public function index(Request $request)
{
$location = $request->input("building");
if ($location != null) {
$inventories = Inventory::where('building', $location)->get();
} else {
$inventories = Inventory::all();
}
return view('computers.index', compact('inventories'));
}
public function show($inventories)
{
$inventories = Inventory::findOrFail($inventories);
return view::make('computers.show')
->with('inventory', $inventories);
}
public function create(){
//flash('Hello World', 'This is the message');
return view('computers.create');
}
/**
* Store a newly created resource in storage.
*
* #param inventory $request
* #return Response
*
*/
public function store(InventoryRequest $request)
{
Inventory::create($request->all());
flash('Success!', 'Inventory Successfully Updated!');
//s
// return redirect()->back(); //temporary
return back();
}
public function edit($inventories)
{
$inventories = Inventory::findOrFail($inventories);
return view('computers.edit', compact('inventories'));
}
public function update(InventoryRequest $request, Inventory $inventories){
$inventories->update($request->all());
flash('Success!', 'Inventory Successfully Updated!');
return back();
}
public function search()
{
$search = \Request::get('q'); //<-- we use global request to get the param of URI
// $search = Input::get('search');
$inventories = Inventory::where('lastName','LIKE','%'.$search.'%')
-> orwhere('firstName', 'LIKE','%'.$search.'%' )
-> orwhere('department', 'LIKE','%'.$search.'%' )
-> orwhere('building', 'LIKE','%'.$search.'%' )
-> orwhere('room', 'LIKE','%'.$search.'%' )
-> orwhere('manufacturer', 'LIKE','%'.$search.'%' )
-> orwhere('device', 'LIKE','%'.$search.'%' )
-> orwhere('model', 'LIKE','%'.$search.'%' )
-> orwhere('tag', 'LIKE','%'.$search.'%' )
-> orwhere('macAddress', 'LIKE','%'.$search.'%' )
-> orwhere('status', 'LIKE','%'.$search.'%' )
-> orwhere('comments', 'LIKE','%'.$search.'%' )
->get();
return view('computers.search',compact('inventories'));
}
}
Check the RedirectIfAuthenticated.php Middleware. It should look like this by default:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/home');
}
return $next($request);
}
}
Make sure that what is returned is the good page!! If you don't have that Middleware maybe take a look at Laravel's doc to create one!

Call to a member function isAdmin() on null in laravel

I want to basic authenticate if User is Admin then Request next otherwise redirect to homepage
User.php:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password','role_id','is_active','photo_id',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function role(){
return $this->belongsTo('App\Role');
}
public function photo(){
return $this->belongsTo('App\Photo');
}
public function isAdmin(){
if ($this->role()->name=="administrator"){
return true;
}
return false;
}
}
last function is isAdmin()
Admin.php (this is middleware):
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class Admin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (Auth::check()){
if (Auth::user()->isAdmin()){
return $next($request);
}
}
return redirect('/');
}
}
routes.php:
<?php
Route::get('/', function () {
return view('welcome');
});
Route::get('/admin',function(){
return view('admin.index');
});
Route::group(['middleware'=>'admin'],function(){
Route::resource('/admin/users','AdminUsersController');
});
Route::auth();
Route::get('/home', 'HomeController#index');
I get the following error:
FatalErrorException in Admin.php line 21:
Call to a member function isAdmin() on null
I also added 'admin' =>\App\Http\Middleware\Admin::class, in kernel.php and imported the class in Admin.php.
This is because of no user session. Middleware works only when user is login. So you need to login first and then check for middleware
Auth::user() return null if user is not authenticated.
to solve this issue use Illuminate/Support/Optional as follows
optional(Auth::user())->isAdmin()
if Auth::user() return null then the isAdmin() will never be called.
Please try this: change your method to static on User.php model.
static function isAdmin(){
if ($this->role()->name=="administrator"){
return true;
}
return false;
}
Next: Modify middleware it should work.
<?php
namespace App\Http\Middleware;
use Closure;
class Admin
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if (auth()->check()){
if (\Admin::isAdmin()){
return $next($request);
}
}
return abort(404); //redirect the user to not found page.
}
}
Because you do not have any role, first insert some data in the roles table.

Laravel 5.2 \Illuminate\Support\Facades\Auth::logout() or $this->auth->logout() not working

I am creating an web application using Laravel 5.2. I have login successfully into the application, but when i tried to logout. It does not allow me to do so.
When i investigate, i came to know that \Illuminate\Support\Facades\Auth::logout() returning null using dd(\Illuminate\Support\Facades\Auth::logout());. I have also tried $this-auth->logout(); this statement also return null.
I am not using default laravel scaffolding, instead i have create my usercontroller and doing the same thing.
Effort:
Route.php
Route::get('/', 'HomeController#index');
Route::get('logout/','UserController#logout');
Route::group(['middleware' => ['web']], function () {
Route::get('login/','UserController#loginForm');
Route::post('login/','UserController#login');
Route::get('register/','UserController#register');
Route::post('register/','UserController#store');
Route::get('home/',['as' => 'home', 'uses' => 'HomeController#index']);
});
UserController.php
namespace App\Http\Controllers;
use App\User;
use App\Profile;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* User model instance
* #var User
*/
protected $user;
protected $profile;
/**
* For Guard
*
* #var Authenticator
*/
protected $auth;
/**
* Create a new authentication controller instance.
*
* #return void
*/
public function __construct(Guard $auth, User $user)
{
$this->user = $user;
$this->auth = $auth;
$this->middleware('guest', ['except' => 'logout']);
}
public function login(Request $request)
{
if ($this->auth->attempt($request->only('email', 'password'))) {
// dd(\Illuminate\Support\Facades\Auth::user());
dd(\Illuminate\Support\Facades\Auth::user());
return redirect()->route('home');
}
return redirect('login')->withErrors([
'email' => 'The email or the password is invalid. Please try again.',
]);
}
/**
* Log the user out of the application.
*
* #return Response
*/
protected function logout()
{
// \Illuminate\Support\Facades\Auth::logout();
dd(\Illuminate\Support\Facades\Auth::logout());
$this->auth->logout();
\Session::flush();
return redirect('login');
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function loginForm()
{
return view('user.login', ['title' => 'Login Page']);
}
....
}
I am lot able to understand why user is not getting logout ? Please help Me.

Laravel-5 adding hasRole method to Auth

I'm trying to extend the Laravel-5.1 Auth middleware so that I can add my own method to it:
Auth::hasRole()
What do I need to do in order to add the new method hasRole to Auth?
Here is my routes file:
/* Administrator Routes */
Route::group(['namespace' => 'Admin', 'middleware' => 'timesheets.admin:Administrator'], function()
{
Route::get('home', 'AdminController#index');
});
Here is my middleware file:
<?php
namespace App\Http\Middleware\Auth;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class AdminAuthenticate
{
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $role)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
if (auth()->check() && auth()->user()->hasRole($role)) {
return $next($request);
}
}
}
Could you try adding the following to your User model:-
public function hasRole($role)
{
return User::where('role', $role)->get();
}
This should firstly check to see if you User table has the field 'role' and then check your parameter $role against the role field.
You can the check by doing the following:
if( Auth::user()->hasRole($role) )
You may need to adjust the example to your needs. Let me know if you need anything else.
/------------EDIT-----------------/
If you have two seperate tables, one holding the user information and the other holding the users privileges/roles you could add another function to the User model:
public function userID()
{
return $this->user_id;
}
This will check for if you have a user ID field if so, it will return the id for the authenticated user.
Then add this to your hasRoles method:
public function hasRoles($userID, $roles)
{
return Your\User\Roles\Model::where('role', $role)->where('user_id', $user_id)->get();
}
Your middleware would look like this:
public function handle($request, Closure $next, $role)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
$userID = Auth::user()->userID();
if (auth()->check() && auth()->user()->hasRole($userID, $role)) {
return $next($request);
}
}
If I understood correctly what you want. I believe this should work for you.
I've taken a different tack by using a trait in my User model.
<?php
namespace App\Traits;
use App\Role;
use App\User;
trait HasRoles{
public function roles()
{
return $this->belongsToMany('App\Role');
}
public static function findByRole(Role $role)
{
return $role->users()->get();
}
public function hasRole(Role $role)
{
return $this->roles()->get()->contains($role);
}
}
There are some good packages to help with this if you don't want to brew your own. I can recommend both:
Zizaco Entrust: https://github.com/Zizaco/entrust
and
Sentinel: https://cartalyst.com/manual/sentinel/2.0

Categories