Whitelist Domain Authentication Laravel - laravel

I'm looking for the best way to only allow certain domains to access my laravel application. I'm currently using Laravel 5.1 and am using a Middleware to redirect if the referring domain isn't located in the whitelisted domains.
class Whitelist {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
//requesting URL
$referer = Request::server('HTTP_REFERER');
//parse url to match base in table
$host = parse_url($referer, PHP_URL_HOST);
$host = str_replace("www.", "", $host);
//Cached query to whitelisted domains - 1400 = 24 hours
$whiteList = Cache::remember('whitelist_domains', 1400, function(){
$query = WhiteListDomains::lists('domain')->all();
return $query;
});
//Check that referring domain is whitelisted or itself?
if(in_array($host, $whiteList)){
return $next($request);
}else{
header('HTTP/1.0 403 Forbidden');
die('You are not allowed to access this file.');
}
}
}
Is there a better way to go about doing this, or am I on the right track?
Any help would be appreciated.
Thanks.

You're on the right track, the implementation seems to be fine.
However, do not trust the HTTP_REFERER as a means of authentication/identification as it can be modified easily.

Related

Efficient update of the table field on each request

I want to update the user table field on each request if the user is authorized. I have not encountered such a task before. I tried to write on the AppServiceProvider.php file:
public function boot()
{
if(Auth::id()) {
$user = User::find(Auth::id());
$user->updated_at = Carbon::now()->setTimezone("America/Los_Angeles");
$user->save();
}
}
But in this case I could not take access to the authorized user.
Can I get access to the service provider to an authorized user?
Or solve this problem with creating middleware?
Note: I am doing this task to find out the time of the user's last activity.
Is the solution found right? Is there a load on the server?
by creating a new middleware try this one
php artisan make:middleware UserActivityUpdateMiddleware
UserActivityUpdateMiddleware
<?php
namespace App\Http\Middleware;
use Closure;
class UserActivityUpdateMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(Auth::User()) {
$user = User::find(Auth::user()->id);
$user->updated_at = Carbon::now()->setTimezone("America/Los_Angeles");
$user->save();
}
return $next($request);
}
}

Laravel - How to OR among middlewares for a route?

There is a table users in my website and a user is allowed to update a user if it is admin or it is his/her account. I can put this rule inside a middleware and impose it on the route but I want to create separate middlewares and OR among them. Can I do that?
The following code
Route::group(['middleware' => ['admin','Owner']],
function () {
Route::resource('roles', 'RoleController');
Route::resource('locations', 'LocationController');
Route::resource('recipients', 'RecipientController');
Route::resource('classifications', 'ClassificationController');
});
has AND behavior. I think it is possible to do this using some if ... else ... statement inside the web.php or the UserController but I need to know if there is any other way out.
Thanks in advance
update
Here is Owner middleware
class OwnerMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next, $id)
{
if(Auth::guest())
return abort(403, 'Access Denied');
if(Auth::user()->id != $id)
return abort(403, 'Access Denied');
return $next($request);
}
}
Then I pass the $id parameter to it.
There really isn't an "OR" for middleware. It either acts or passes. You have to expand the current middleware to check ownership or permission to edit.
However, I'd recommend using a policy with middleware to resolve this:
See: https://laravel.com/docs/master/authorization#via-middleware

Middleware to check if ajax request is authenticated is not working

I am trying to handle ajax request that were initiated from idle/expired session(maybe the page was left open and the session got expired). I wrote the below middleware but it's not working as expected:
namespace App\Http\Middleware;
use Closure;
class AjaxSessionCheck
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if(!\Auth::check())
{
if($request->ajax())
{
return response()->json(['Session_error'=>'Session Expired'], 401);
//throw new AuthenticationException('Unauthenticated');
}
}
return $next($request);
}
}
To check if this worked i logged into the same page that contains the form from two separate tabs and then logged out from one of the tab, making the session invalid on the other tab as well. Then i initiated an ajax request(user clicks a delete button).
Any help to the right direction will be much appreciated!
for better coverage use if ($request->isJson() || $request->wantsJson()) {

Laravel v5.2 moving middleware from web group to global?

I was logging request for my site, for guest users and authenticated users, but then i faced a problem that if a user is logged in and a 404 exception kick in then in that case i Auth::user() was null,
class LoggingMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
$info = [];
//$info = get everything i need from request and response.
$info['user_detail'] = Auth::user()->id;
var_dump(Auth::user());
dispatch(new LogRequests($info));
}
}
what i did then moved the StartSession middle ware from web group to global middle ware group. Now it is working fine. Is there any issue that can arise by moving the middleware from web group to global?
Global middleware is run every time an HTTP request is made to your application, so if the context of your LoggingMiddleware works with this in mind, then there should be no problem.

Upgrading from Laravel 4.2 to Laravel 5 - Container

I still have some trouble understanding all the changes from Laravel 4.2 to 5.0.
I have already managed to import all my models, controllers, config etc. I have namespaced almost everything but one thing that I can't seem to manage is to transform this code from 4.2 app\filters.php to my new 5.0 application.
Here's part of the code with some added explanations below that I'm having problems with. The following code was added so that we can conveniently ask for the permissions inside a group for all the actions/visible fields for the current user.
if(App::make('Authflag', $usergroup->id)->can(GroupPermissions::EDIT_MEMBERS)) ...
Code from 4.2:
App::before(function($request) {
App::instance('Authflags', array());
App::bind('Authflag', function($app, $param) {
$authflags = App::make('Authflags');
if(isset($authflags[$param]))
{
return $authflags[$param];
}
// Calculate generate flag value
$authflags[$param] = $authflag;
App::instance('Authflags', $authflags);
return $authflag;
});
});
Explanation:
instance Authflags contains group_id => permissionObject
Code explanation:
Get the Authflags array instance
If we already have the needed permissionObject return it
Else generate/calculate/request the permissionObject
Update the Authflags instance
Return the created permissionObject
But whatever I try I keep getting the ReflectionException in Container.php line 776: Class Authflag does not exist.
I tried to create a contract and a service and set a binding inside the AppServiceProvider. But I'm pretty sure I was doing a completely wrong/different thing.
I tried to just copy this code with some modifications inside the AppServiceProvder. But It just seemed wrong and didn't work.
(Come to think of it the whole code should have probably been inside the start/global.php)
How can I port this code to Laravel 5.0?
You have to use a middleware "encapsulation". Here is an example, that will show where you would have to put your custom before and after parts of your app.
use Closure;
class ChangeCookieLifetime {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
//anything put here will be run BEFORE your app
$response = $next($request);
//anything put here will be run AFTER your app
return $response
}
}
In your particular case iw dould like this:
use Closure;
class ChangeCookieLifetime {
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
App::instance('Authflags', array());
App::bind('Authflag', function($app, $param) {
$authflags = App::make('Authflags');
if(isset($authflags[$param]))
{
return $authflags[$param];
}
// Calculate generate flag value
$authflags[$param] = $authflag;
App::instance('Authflags', $authflags);
return $authflag;
});
$response = $next($request);
//anything put here will be run AFTER your app
return $response
}
}
Although I can't promise that the parts I inserted will work, this is the direct "translation" from Laravel 4.2 to Laravel 5

Resources