I'm trying to get authenticated subdomain routing working for some specific variable subdomains:
app.example.com
staging.app.example.com
testing.app.example.com
These should be guarded by the auth middleware. They all essentially reference app.example.com but for different environments.
Everything that hits these domains should go to the guest routes:
example.com
staging.example.com
testing.example.com
This is what I've tried so far...
Created this middleware to prevent the subdomain parameter from messing up other routes and to allow successful authentication to redirect to app.example.com:
class Subdomain
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$route = $request->route();
$subdomain = $route->parameter('subdomain');
if (!empty($subdomain) && preg_match('/^(staging|testing)\.(app.\)?/', $subdomain, $m)) {
\Session::put('subdomain', $m[1]);
}
$route->forgetParameter('subdomain');
return $next($request);
}
}
Added this to Kernel.php:
protected $routeMiddleware = [
'subdomain' => \App\Http\Middleware\Subdomain::class,
];
Contents of routes.php:
Route::group(['domain' => '{subdomain?}example.com', 'middleware' => 'subdomain'], function () {
// Backend routes
Route::group(['middleware' => 'auth'], function () {
Route::get('/', ['as' => 'dashboard', 'uses' => 'Controller#dashboard']);
// ...various other backend routes...
});
// Frontend routes
Route::auth();
Route::get('/', function () {
return view('frontend');
});
});
When I access any route, I can trace that nothing hits the subdomain middleware...it just routes to the 404 page.
How would I make this work in Laravel 5.2?
Since the goal of my setup was to allow handling certain subdomain groups with optional environment prefixes, I handled it in the following way.
I dropped the Subdomain class as being unnecessary.
I added this to the .env file so that each environment can have it's own domain so the local dev server still works independent of the staging and production server:
APP_DOMAIN=example.dev
On production and staging it would simply be:
APP_DOMAIN=example.com
Within config/app.php I added:
'domain' => env('APP_DOMAIN', null),
I added these methods to \App\Http\Controllers\Controller:
public static function getAppDomain()
{
return (!in_array(\App::environment(), ['local', 'production']) ? \App::environment() . '.' : '') . 'app.' . config('app.domain');
}
public static function getAppUrl($path = '', $secure = false)
{
return ($secure ? 'https' : 'http') . '://' . static::getAppDomain() . ($path ? '/' . $path : '');
}
Within Auth\AuthController.php I added this to handle redirects to the app.example.com from example.com even if prefixed with staging or testing:
public function redirectPath()
{
if (\Auth::check()) {
return redirect()->intended(static::getAppUrl())->getTargetUrl();
} else {
return $this->redirectTo;
}
}
New contents of routes.php:
// Backend routes
Route::group(['domain' => Controller::getAppDomain(), 'middleware' => 'auth'], function () {
Route::get('/', ['as' => 'dashboard', 'uses' => 'Controller#dashboard']);
// ...various other backend routes...
});
// Frontend routes
Route::auth();
Route::get('/', function () {
return view('frontend');
});
Hope this helps if anyone tries similar!
Related
I am trying to set up localization in a laravel app but my middleware seems to be causing an ERR_TOO_MANY_REDIRECTS error. The site is going to differ per region slightly and I am using the laravel lang/ files to swap out phone numbers etc. This works okay. When I change my locale I get the correct numbers from the lang files. And when I just have the middleware to check if the cookie has been set to set the locale that works too.
I also have middleware to forget the prefix on localised routes so I don't have to update my methods with a locale parameter.
My issue is setting a url prefix if a cookie has been set with an allowed locale in my middleware. I also want to ignore the prefix if the locale is 'en' as it will be default.
Below is the code for everything
routes/web.php
Route::get('/', 'HomeController#index')->name('home');
Route::get('/reader/{identifier}', 'ReaderController#show')->name('reader');
Route::get('/locale/{locale}', SetLocaleController::class)->name('set.locale');
Route::group(['prefix' => '{locale?}', 'where' => ['locale' => implode('|', array_keys(config('app.allowed_locales')))], 'middleware' => 'redirect.localization'], function () {
Route::get('/', 'HomeController#index')->name('home');
Route::middleware('forget.prefix')->get('/reader/{identifier}', 'ReaderController#show')->name('reader');
});
Middleware/Localization.php - This is added to the web middleware group in Kernel.php. It checks for a cookie and sets the locale and should redirect to the proper locale prefix. If no cookie is set then we get the users geo and set it.
public function handle($request, Closure $next)
{
// Get requested url
$segments = collect($request->segments());
if ($segments->count() && Arr::exists(config('app.allowed_locales'), $segments[0])) {
$segments->shift();
}
$locale = Cookie::get('locale');
if ($locale ?? false) {
// Set the app locale.
App::setLocale($locale);
if ($locale != 'en') {
$segments->prepend($locale);
return redirect()->to($segments->implode('/'));
}
} else {
// Check for geo here and set it.
}
return $next($request);
}
Middleware/RedirectLocalization.php - This middleware is only set on the route group for the prefix. It checks if the locale passed is allowed and the sets the locale and cookie. This is set in the $routeMiddleware array in Kernel.php
public function handle($request, Closure $next)
{
$locale = $request->segment(1);
if (Arr::exists(config('app.allowed_locales'), $locale)) {
// Set the app locale.
App::setLocale($locale);
// Save app locale in a Cookie.
Cookie::queue(Cookie::make('locale', $locale, 525600));
}
return $next($request);
}
Controllers/SetLocaleController.php - This is where the locale can be manually set from a menu on the site.
public function __invoke($locale, Request $request)
{
$redirectUrl = parse_url(url()->previous());
$segments = Str::of($redirectUrl['path'])->trim('/')->explode('/');
if (Arr::exists(config('app.allowed_locales'), $segments[0])) {
$segments->shift();
}
if (Arr::exists(config('app.allowed_locales'), $locale)) {
// Set the app locale.
App::setLocale($locale);
// Save app locale in a Cookie.
Cookie::queue(Cookie::make('locale', $locale, 525600));
// Add locale to segments for redirect.
if ($locale != 'en') {
$segments->prepend($locale);
}
} else {
// Set locale to current locale.
App::setLocale(config('app.fallback_locale'));
}
// Redirect back
return redirect()->to($segments->implode('/'));
}
Controllers/ReaderController.php - Nothing out of the ordinary here but I wanted to add it to explain the forget.prefix middleware. If I don't add the forget.prefix middleware then the $reader param becomes the locale.
public function show($reader, Request $request)
{
$reader = Reader::find($reader);
return view('readers.show', [
'reader' => $reader
]);
}
Middleware/ForgetPrefix.php - This middleware removes the prefix so we can access parameter in controller methods without having to add a $locale param to the method in the controller.
public function handle($request, Closure $next)
{
$request->route()->forgetParameter('locale');
return $next($request);
}
So my question is how can I set the URL prefix if the locale has been set in a cookie without getting the too many redirects error?
So I found that my issue was coming from having the Middleware/Localization.php added to the web middleware group. I added this middleware to $routeMiddleware in Kernel.php. Instead I only added the Middleware/Localization.php to the default locale routes.
My updated web/routes.php
Route::group(['middleware' => 'localization'], function () {
Route::get('/', 'HomeController#index')->name('home');
Route::get('/reader/{identifier}', 'ReaderController#show')->name('reader');
});
Route::group(['prefix' => '{locale?}', 'where' => ['locale' => implode('|', array_keys(config('app.allowed_locales')))], 'middleware' => 'redirect.localization'], function () {
Route::get('/', 'HomeController#index')->name('home');
Route::group(['middleware' => 'forget.prefix'], function () {
Route::get('/reader/{identifier}', 'ReaderController#show')->name('reader');
});
});
// Switch Locale route
Route::get('/locale/{locale}', SetLocaleController::class)->name('set.locale');
I have the below mentioned route:
Route::get('/', 'HomeController#index');
Route::get('administrator', array('before' => 'auth', 'uses' => 'Administrator\IndexController#index'));
//Route::get('/administrator', 'Administrator\IndexController#index');
Route::group(['prefix' => 'administrator'], function() {
Route::get('login', 'Administrator\IndexController#index')->name('login');
Route::post('login', 'Auth\LoginController#doLogin');
Route::get('logout', 'Auth\LoginController#logout');
});
My intention is when someone try to access http://127.0.0.1:8000/administrator/ this will go directly to the login page of the administrator.
However, when I tried to access the same, it said 404 not found.
IndexController under Administrator folder is looks below:
class IndexController extends Controller {
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct() {
$this->middleware('guest')->except('doLogout');
}
public function index() {
//$session = session()->all();
if(Auth::check() == 1){
return Redirect::intended('/administrator/dashboard')->with('successMessage', 'You have successfully logged in.');
}
//print_r($session);
//echo $session['_token'];
//if($session['_token'] == '')
$data = array();
$data['title'] = "Shop To My Door - Administrator Panel";
return view('Administrator.index.index', $data);
}
}
You have route and group with the same name "administrator"
My suggestion for routing:
Route::get('/', 'HomeController#index');
Route::group(['prefix' => 'administrator'], function() {
Route::get('/', 'Administrator\IndexController#index');
Route::get('login', 'Administrator\IndexController#login');
Route::post('login', 'Auth\LoginController#doLogin');
Route::get('logout', 'Auth\LoginController#logout');
});
I have a protected route group:
Route::group(['prefix' => 'member', 'middleware' => 'auth'], function () {
Route::get('/')->name('member.home')->uses('MemberController#index');
Route::get('show')->name('member.show')->uses('MemberController#show');
// ...various additional protected member routes...
});
However, I have two routes that should not be protected:
Route::get('member/pay')->name('member.pay')->uses('MemberController#pay');
Route::get('member/confirm/{payment}')->name('member.confirm')->uses('MemberController#confirm');
So long as 'middleware' => 'auth' is applied to that separate route group, ALL of the member prefixed routes are covered by it even if I don't place them in the group.
I've tried moving the unprotected routes above and below the protected route group but I still get 401 unauthorized unless I remove the middleware entirely.
This isn't impacting any of my other routes...only the ones prefixed by member.
How can I exclude these two routes from auth?
One approach would be to remove the middleware assignment from the Route group and instead assign the middleware in your MemberController constructor. That way you can exclude which methods should not have it applied, like so:
class MemberController extends Controller
{
/**
* Instantiate a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth')->except(['pay', 'confirm']);
}
}
Use nested groups like this.
Route::group([ 'prefix' => 'member' ], function() {
// Protected routes
Route::group([ 'middleware' => 'auth' ], function() {
Route::get('/', 'MemberController#index')->name('member.home');
Route::get('show', 'MemberController#show')->name('member.show');
// ...various additional protected member routes...
});
// Non protected routes
Route::get('pay', 'MemberController#pay')->name('member.pay');
Route::get('confirm/{payment}', 'MemberController#confirm')->name('member.confirm');
// ...various additional non protected member routes...
});
how about
Route::group(['prefix' => 'member'], function () {
Route::get('/')->name('member.home')->uses('MemberController#index')->middleware('auth');
Route::get('show')->name('member.show')->uses('MemberController#show')->middleware('auth');
//
Route::get('member/pay')->name('member.pay')->uses('MemberController#pay');
Route::get('member/confirm/{payment}')->name('member.confirm')->uses('MemberController#confirm');
});
I have been struggling with this from quiet a time now, what i am trying is to redirect all the url's hit by non-logged in users to login page and it gives me this error, which I am sure is because it is creating a loop on /login URL. authentication is checking for authorized user in login page also. however I wish the login page should be an exception when checking the auth. I may be doing something wrong which I am not able to get. here goes my code.
routes.php
Route::post('login', 'Auth\AuthController#login');
Route::get('login' , 'Auth\AuthController#showLoginForm');
Route::get('/' , 'Auth\AuthController#showLoginForm');
kernel.php
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'can' => \Illuminate\Foundation\Auth\Access\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'acl' => \App\Http\Middleware\CheckPermission::class,
];
Authenticate class
class Authenticate
{
public function handle($request, Closure $next, $guard = null) {
if (Auth::guard($guard)->guest()) {
if ($request->ajax() || $request->wantsJson()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
}
return $next($request);
}
}
AuthController class
class AuthController extends Controller {
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
protected $redirectTo = '/dashboard';
protected $loginPath = '/login';
protected $redirectPath = '/dashboard';
public function __construct(){
$this->middleware('auth', ['except' =>'login']);
/* I have been trying these many things to fix this, all in loss.
// $this->middleware('acl'); // To all methods
// $this->middleware('acl', ['only' => ['create', 'update']]);
// $this->middleware('guest', ['only' => ['/login']]);
// echo "Message"; exit;
// $this->middleware('auth');
// $this->middleware('auth', ['only' => ['login']]);
// $this->middleware('auth', ['only' => ['/login']]);
// $this->middleware('auth', ['except' => 'login']);
// $this->middleware('guest');
// $this->middleware('guest', ['only' => ['logout' , 'login', '/login', '/']]);
}
Please help me, It going all above my head, seems some sort of rocket science to me. well btw I am new to laravel and may be doing some silly thing around, apologies for that. Thanks in Advance.
You need add route login outside Laravel group:
routes.php
Route::auth();
Route::group(['middleware' => 'auth'], function () {
// All route your need authenticated
});
Aditionally, you can see yours route list using:
php artisan route:list
Why you are doing all this just to redirect every non-logged in user to login form?
i think you can just do this
Routes.php
Route::post('login', 'Auth\AuthController#login');
Route::get('login' , 'Auth\AuthController#showLoginForm');
Route::get('/' , 'Auth\AuthController#showLoginForm');
Route::group(['middleware' => 'auth'], function () {
// any route here will only be accessible for logged in users
});
and auth controller construct should be like this
AuthController
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
}
The problem is with your routes.
When I enter and I am not logged out you send me to login(get) route. And as you are specifying the middleware in the construct function in the AuthController, every time a method of the AuthController is called, construct function is called again and sends you back at login.. and it repeats indefinitely.
like #mkmnstr say
The problem is with your routes.
When I enter and I am not logged out you send me to login(get) route. And as you are specifying the middleware in the construct function in the AuthController, every time a method of the AuthController is called, construct function is called again and sends you back at login.. and it repeats indefinitely.
to fix that u should add
Auth::logout();
Here
...
} else {
Auth::logout(); // user must logout before redirect them
return redirect()->guest('login');
}
...
If your working with custom middleware you must follow it's all rules
in my case, I have to define a custom route class in the web middleware group.
In the world of copy-paste sometime we make mistakes.
Middleware :
public function handle($request, Closure $next)
{
if(!isset(session('user'))){
return redirect('login');
}
return $next($request);
}
}
My Mistake in Kernel.php
if custom middleware class present in web $middlewareGroups will check condition 2 times so it will give error as: redirected you too many times
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\webUser::class, //Remove
],
protected $routeMiddleware = [
'webUser'=> \App\Http\Middleware\webUser::class //Keepit
]
I had same problem after creating my own route service provider. The problem was that when I tried to login, in first time login page showed and after entering credentials I encountered "redirected too many times" and redirected to my admin dashboard and login route!
the solution was: adding middleware "web" into my routes:
Route::middleware('web')->group(base_path('Admin/routes.php'));
i tried to configure laravel for apache2.
But if I open http://localhost/ it redirect me to http://localhost/login and there is nothing to display.
If I try http://localhost/index.php/login I get the view blade to login. But how can I remove the /index.php/
The Apache vHost config
And the "main" route
Route::get('/home', function() {
return Redirect::to('login');
});
Route::group([], function() {
Route::get('/', function() {
return Redirect::to('dashboard');
Route::get('galleries', 'GalleryController#getGalleries');
Route::get('galleries/{GID}', 'GalleryController#getPicuteGallery');
Route::get('news', 'NewsController#index');
Route::get('dashboard', 'DashboardController#index');
Route::get('search', 'Search\SearchController#index');
Route::get('calendar', 'CalendarController#index');
Route::get('symposium', 'SymposiumController#index');
Route::get('conference', 'ConferenceController#index');
Route::get('publication', function() {
return view('publication');
});
});
The Auth routes are predefined by AdminLTE installer.
/**
* Define the AdminLTETemplate routes.
*/
protected function defineRoutes()
{
if (!$this->app->routesAreCached()) {
$router = app('router');
$router->group(['namespace' => $this->getAppNamespace().'Http\Controllers'], function () {
require __DIR__.'/../Http/routes.php';
});
}
}
And the AdminLTE Router
<?php
/*
* Same configuration as Laravel 5.2:
* See https://github.com/laravel/framework/blob/5.2/src/Illuminate /Auth/Console/stubs/make/routes.stub
*/
Route::group(['middleware' => 'web'], function () {
Route::auth();
Route::get('/home', 'HomeController#index');
Route::get('/', function () {
return view('welcome');
});
});
---UPDATE---
I found out that the mod_rewrite wasnt enabled. Now the web site works fine.
But I need to add the 'middleware' => 'web' class
Remove ['middleware' => 'web'] from you routes.php, because since Laravel 5.2.27 this middleware applies automatically to all your routes and if you're adding it manually, it may give you broken app.
UPDATE:
You have a function which redirects you to 'dashboard' (why?) and also the function is not closed. So try to remove these lines:
Route::get('/', function() {
return Redirect::to('dashboard');