Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Lars_M's avatar

Laravel API Security with CORS

Hello together,

I am a junior developer from germany and wanted to try my hand at a new project.

I have implemented a CORS middleware validation for API's in Laravel, which allows to query trusted hosts from a database.

In addition, each query is hashed with a timestamp to the minute to make sure that only real website visitors get access data.

The goal is to provide each registered domain with only the data that is actually associated with the domain from the database so that no authentication via tokens is necessary.

The data is only product data that is requested via GET. It is not sensitive data.

The structure of the platform is as follows:

Laravel Backend with Jetstream -> the middleware -> API -> Vue websites which are registered in the backend

The middleware should be care of the "multi-tenancy"

What do you think about the security? Do I have some kind of thinking error? Is there something I have not considered?

Unfortunately I don't have a possibility for a code review from another developer, so I ask my question here.

My middleware code:


class Cors
{
    public static function getRefferer(Request $request){
        $refferer = explode('://', $request->server('HTTP_REFERER'))[1];
        return rtrim($refferer, '/');
    }

    public static function isTrustedHost(Request $request){
        $refferer = Tenant::where('host', self::getRefferer($request))->first();

        if (!$refferer){
            return false;
        }

        if (!$request->header('Access-Control-Allow-Origin') == $refferer->host){
            return false;
        }
        if (!self::requestHasValidTimeSignature($request, $refferer->host)){
            return false;
        }
        return true;
    }

    public static function requestHasValidTimeSignature(Request $request, $message){
        $hash = base64_encode(hash_hmac('sha256', $message, date('i'), true));

        if ($hash == $request->header('Time-Signature')){
            return true;
        }
        else{
            return false;
        }
    }

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse)  $next
     * @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
     */
    public function handle(Request $request, Closure $next)
    {
        if (!self::isTrustedHost($request))
        {
            abort(403, 'Access denied');
        }
        return $next($request);
    }
}

0 likes
0 replies

Please or to participate in this conversation.