Using 'auth' middleware with subdomains

I am trying to pass certain functions in my controller via auth middleware. However, the routes associated with these features require the subdomain in the url to work. The functions seem to work when they are not passed through middleware or when they are passed through custom middleware, but the "auth" middleware throws an error:

UrlGenerationException on line UrlGenerationException.php 17: Missing required parameters for [Route: login] [URI: login].

This is similar to the error you get when you try to run a function without the $ account variable in the parameter list (since it expects a subdomain with a route).

Digging deeper into the Authenticate class called by the "auth" middleware, I found that the string causing the error is in the public function authentication ($ guard array) as shown below.

protected function authenticate(array $guards)

{
    if (empty($guards)) {
        /** ANYTHING BEFORE THIS RETURN STATEMENT RUNS WITH NO ERRORS **/
        return $this->auth->authenticate();
    }

    foreach ($guards as $guard) {
        if ($this->auth->guard($guard)->check()) {
            return $this->auth->shouldUse($guard);
        }
    }

    throw new AuthenticationException('Unauthenticated.', $guards);
}

      

Here are some of my codes for reference (only relevant code snippets will be included):

File routes

routes \ web.php

Route::group(['domain' => '{account}.'.env('APP_URL')], function () {
  include('appRoutes/bcm.php');
});

      

routes \ appRoutes \ bcm.php

/********************************************/
/*********STATIC PAGE ROUTES******************/
/********************************************/

Route::get('/boards-commissions', 'BCM\PagesController@home');


/********************************************/
/*********BOARD ROUTES***********************/
/********************************************/

Route::get('/boards-commissions/boards', 'BCM\BoardsController@index');

Route::get('/boards-commissions/boards/archive/index', 
'BCM\BoardsController@archiveIndex');

      

Controllers

Application \ Http \ Controllers \ BCM \ BoardsController.php

namespace App\Http\Controllers\BCM;

use Auth;
use Session;
use Validator;

use Illuminate\Http\Request;
use Illuminate\Foundation\Validation\ValidatesRequests;

//Models
use App\Models\BCM\Board;

class BoardsController extends Controller
{
    public function __construct()
    {
        $this->middleware('bcm_app_access');
        $this->middleware('auth', ['except' => array('index', 'show')]);
        $this->middleware('bcm_admin', ['only' => array('edit', 'update', 
'create', 'store', 'archive', 'showArchive', 'showArchivedBoard', 'restore')]);
    }

    public function index($account, Request $request) {
        $boards = Board::all();
        $user = $request->user();
        return view('bcm.boards.index')->with('boards', $boards)->with('user', $user);
    }

    public function archiveIndex($account, Request $request) {
        $boards = Board::all();
        $user = $request->user();
        return view('bcm.boards.archiveList')->with('boards', $boards)->with('user', $user);
    }
}

      

It seems that only the auth middleware is not working so far. The index function works very simply (since it is excluded from the auth middleware in the controller design), although it goes through the bcm_app_access middleware. But archiveIndex will throw the UrlGenerationException error mentioned above when it goes through the auth middleware.

I have a feeling that the $ account parameter needs to be added or included somewhere for the auth middleware to know that it needs to reference it, but I'm not sure where to add it and I don't know what else the files are being referenced. when $ this-> auth-> authenticate (); runs, so I don't know where to add this. Any thoughts?

+3


source to share


2 answers


In the original question, I wanted to know how to get the auth middleware to work with subdomains. I still haven't figured out what to do, but I got it functional working by creating basic custom middleware. The point of the authentication middleware was to check if the site user was logged in or started as a guest. To mimic this functionality, I created middleware by running

php artisan make:middleware SubdomainAuth

      

at the command line. Then I configured the auto-generated middleware file to look like this:

<?php
namespace App\Http\Middleware;
use Closure;
use Auth;
class SubdomainAuth
{
    /**
     * Handle an incoming request to make sure that a valid user is logged in.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next) {
        $user = Auth::user();
        if ($user == null) {
          return redirect('/login');
        }
        return $next($request);
    }
}

      

Finally, I configured my kernel to recognize new middleware by adding the line



'sub_auth' => \App\Http\Middleware\SubdomainAuth::class,

      

in app / Http / Kernel.php. From there I was able to replace the auth middleware in my controllers with the sub_auth middleware I created. My example from the question above looks like this:

namespace App\Http\Controllers\BCM;

use Auth;
use Session;
use Validator;

use Illuminate\Http\Request;
use Illuminate\Foundation\Validation\ValidatesRequests;

//Models
use App\Models\BCM\Board;

class BoardsController extends Controller
{
    public function __construct()
    {
        $this->middleware('bcm_app_access');
        $this->middleware('sub_auth', ['except' => array('index', 'show')]);
        $this->middleware('bcm_admin', ['only' => array('edit', 'update', 
'create', 'store', 'archive', 'showArchive', 'showArchivedBoard', 'restore')]);
    }

    public function index($account, Request $request) {
        $boards = Board::all();
        $user = $request->user();
        return view('bcm.boards.index')->with('boards', $boards)->with('user', $user);
    }

    public function archiveIndex($account, Request $request) {
        $boards = Board::all();
        $user = $request->user();
        return view('bcm.boards.archiveList')->with('boards', $boards)->with('user', $user);
    }
}

      

This workaround successfully shields those who are not logged in and redirects them to the login page. However, I am not sufficiently aware of how the Authenticate middleware works to know if there is any added security that my custom class is missing from the SubdomainAuth class I created.

+1


source


I faced the same problem. Here's my solution:

Laravel Auth Middleware handles it by default ("login") which is in \ Light \ Foundation \ Exceptions \ handler.php

protected function unauthenticated($request, AuthenticationException $exception)
{
    return $request->expectsJson()
                ? response()->json(['message' => $exception->getMessage()], 401)
                : redirect()->guest(route('login'));
}

      

You can change here to change the route ("login", " subdomain ") to make it work. But personally, I would like to leave the framework intact. Instead, I modified the exception handler to overwrite the "failed" function.



Add new function to \ app \ Exceptions \ Handler.php

protected function unauthenticated($request, AuthenticationException $exception)
{
    $subdomain = explode("//",explode('.', $request->url())[0])[1];
    return $request->expectsJson()
                ? response()->json(['message' => $exception->getMessage()], 401)
                : redirect()->guest(route('login',$subdomain));
}

      

I used $ request to get the url and fetch it. I think if you can look deeper into userResolver you can retrieve the subdomain variable defined in your routes / web.php, but I'm happy with that for now.

0


source







All Articles