
Laravel check request origin / domain
When I was working on a chat application project, my CTO asked me to add a security level to the application for checking the domain of all the incoming HTTP requests to the application and check if those domains are allowed to make a call to our application.
Laravel makes it easy to add a level between the incoming HTTP requests and our application by using middleware. Middleware acts like the middle woman between all the HTTP requests to your application so you can perform a variety of actions when a request is being called such as authentication, cors policy, check if the user is logged in and more.
To start with what I was needed to do, first I added the allowed domains. The best place to add it is on the .env file.
The .env file is a configuration file of your application that matches the environment your application is currently running on. On this file, you usually have your database credentials, the cache driver your application is using and some API keys of an external service you are using.
For my case, I added this line to the .env file
ALLOWED_DOMAINS=localhost,domain.com,front.domain.com
Obviously, “domain” should be the real domain name.
After adding this line, I created a new middleware in the application by running the artisan command
php artisan make:middleware DomainCheckMiddleware
This will create a middleware file under the app/Http/Middleware folder.
On this file, I added the mechanism of checking and verify if this domain is allowed.
class DomainCheckMiddleware
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$allowedHosts = explode(',', env('ALLOWED_DOMAINS'));
$requestHost = parse_url($request->headers->get('origin'), PHP_URL_HOST);
if(!app()->runningUnitTests()) {
if(!\in_array($requestHost, $allowedHosts, false)) {
$requestInfo = [
'host' => $requestHost,
'ip' => $request->getClientIp(),
'url' => $request->getRequestUri(),
'agent' => $request->header('User-Agent'),
];
event(new UnauthorizedAccess($requestInfo));
throw new SuspiciousOperationException('This host is not allowed');
}
}
return $next($request);
}
}
Basically, this code will get theALLOWED_DOMAINS
I created in the .env file and convert it to an array of the allowed domains.
Then it will get the origin
of the request, and if we are not running tests, it will run over the newly created array and check if the origin is on this array. If it is NOT on the array, it will get some of the request info, fire an UnauthorizedAccess
event and will throw a new SuspiciousOperationException
.
SuspiciousOperationException
is an event that Laravel provides out of the box.
The last thing I was needed to do in order to make the middleware to work, is to add it to the $middleware
array on the Kernel.php
file in the app/Http
folder.
protected $middleware =[...App\Http\Middleware\DomainCheckMiddleware::class,
];
Now my middleware is working and will run on every HTTP request to my application.
The only thing is to create and handle the onUnauthorizedAccess
event. I made it write to my log
file the request data. It looks something like this
public function onUnauthorizedAccess($event)
{
$data = $event->data; Log::warning('access_from_unauthorized_domain_' . date('Y-m-d_H:i:s'), $data);
}
You would probably want the event to send an email, send a slack message, write to some tracking service you use but for us, writing to the log file was enough.