Laravel API token based protection for 3rd parties.
Hi,
I am currently using Laravel Jetstream to build myself a dashboard where I can create, update and delete items. Now I want 3rd party companies to be able to use these items on their own sites.
For example a friend has a Wordpress website, and now he wants to display the items from my site on his. I've build an API for this where people can access them ( example.com/api/v1/items ).
Now what I want to do is protect this API with access tokens. I know that Laravel Jetstream comes with Sanctum authentication, but this is not exactly what I'm looking for. Since I'm pretty sure the user needs to be both authenticated and have the token.
I want to be able to add new tokens for specific domains, which in the future will only return custom items for the domain. What would be the best way of doing this ?
My idea was to create a custom middleware that checks for this. Below is a part of the code and what I roughly had in mind. Is this something that is alright to do, or are there better and safer ways. Thanks in advance!
Migration
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('api_access_token', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('host')->unique();
$table->string('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('api_access_token');
}
};
Custom Middleware
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use App\Models\ApiAccessToken;
class APIAccess
{
/**
* 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)
{
$host = request()->getHost();
$bearerToken = request()->bearerToken();
$token = ApiAccessToken::where('token', $bearerToken)
->where('host', $host)
->first();
if($token) {
return response()->json([
'error' => 'You are not authorized to access this api.'
],403);
}
return $next($request);
}
}
Kernel.php
protected $routeMiddleware = [
...
'api_access' => \App\Http\Middleware\APIAccess::class,
];
api.php
Route::group([
'middleware' => ['api_access']
], function () {
Route::get('/items', [ItemController::class, 'getItem']);
});
Please or to participate in this conversation.