A CakePHP 5 plugin for integrating with Supabase. This plugin provides a lightweight, custom API client to interact with Supabase services (Auth, Storage, Functions) and a flexible JWT authenticator, without relying on any external, unmaintained Supabase SDKs.
Core Philosophy: This plugin uses CakePHP's built-in Cake\Http\Client for all API interactions, ensuring long-term maintainability and stability. It assumes your main application connects directly to the Supabase PostgreSQL database via the standard CakePHP datasource configuration.
-
Install via Composer:
composer require cakedc/supabase
-
Load the Plugin: In your
src/Application.php, load the plugin in thebootstrap()method:public function bootstrap(): void { parent::bootstrap(); // Load the Supabase plugin $this->addPlugin('CakeDC/Supabase'); }
This plugin does not manage your database connection. You should configure your primary datasource in config/app.php to connect directly to your Supabase PostgreSQL database, just as you would with any other PostgreSQL database.
-
Copy the Configuration File: Copy the plugin's configuration file from
plugins/cakedc/supabase/config/supabase.phpto your application's main config directory:config/supabase.php. -
Set Environment Variables: Customize
config/supabase.phpand provide your Supabase credentials, preferably using environment variables.Your
config/supabase.phpshould look like this:<?php return [ 'Supabase' => [ // Your Supabase project URL. 'url' => env('SUPABASE_URL', null), // The service_role key. This key has admin privileges and should be kept secret. 'serviceRoleKey' => env('SUPABASE_SERVICE_ROLE_KEY', null), // The JWT secret used to verify the signature of user tokens. 'jwtSecret' => env('SUPABASE_JWT_SECRET', null), ], ];
These settings will be loaded automatically by the plugin's
bootstrap.php.
This plugin provides a SupabaseJwtAuthenticator to validate Supabase JWTs and identify users in your local database.
-
Load the Authentication Component: In your
src/Application.php, load theAuthenticationcomponent. -
Configure the Authenticator: In your
getAuthenticationServicemethod, configure theSupabaseJwtAuthenticator. It is highly flexible and can be configured to use your specific user model and finder.// in src/Application.php use Authentication\AuthenticationService; use Authentication\AuthenticationServiceInterface; use Authentication\Identifier\IdentifierInterface; use Psr\Http\Message\ServerRequestInterface; public function getAuthenticationService(ServerRequestInterface $request): AuthenticationServiceInterface { $service = new AuthenticationService(); // Load identifiers $service->loadIdentifier('Authentication.Token', [ 'dataField' => 'sub', // The JWT's sub claim contains the user UUID 'resolver' => [ 'className' => 'Authentication.Orm', 'userModel' => 'Users', // Your user model 'finder' => 'byUuid', // A custom finder on your UsersTable ], ]); // Load authenticators $service->loadAuthenticator('Authentication.Jwt'); $service->loadAuthenticator('CakeDC/Supabase.SupabaseJwt', [ 'userModel' => 'Users', ]); return $service; }
Note: For the above example to work, you would need a custom finder
findbyUuidin yourUsersTable.php.
The SupabaseService acts as a factory for interacting with the Supabase admin APIs. For best practice, you should use CakePHP's dependency injection container to get an instance of the service.
Here is an example of how to inject and use the SupabaseService in a controller to fetch a user's admin-level data from Supabase.
Add the following code to Application.php
public function services(ContainerInterface $container): void
{
$container->add(SupabaseService::class);
}Then, add the service to the action:
// in src/Controller/UsersController.php
namespace App\Controller;
use CakeDC\Supabase\Service\SupabaseService;
class UsersController extends AppController
{
/**
* Get a user's full Supabase profile.
* This requires admin privileges.
*/
public function viewProfile(SupabaseService $supabaseService, string $userId)
{
$this->request->allowMethod(['get']);
// The user ID from the route, e.g., a UUID
$identity = $this->Authentication->getIdentity();
$loggedInUserId = $identity->get('id');
try {
// Use the custom-built AuthAdmin client via the service
$supabaseUserData = $supabaseService->authAdmin()->getUserById($loggedInUserId);
$this->set([
'success' => true,
'data' => $supabaseUserData,
]);
} catch (\CakeDC\Supabase\Exception\SupabaseApiException $e) {
$this->set([
'success' => false,
'message' => 'Failed to fetch user profile: ' . $e->getMessage(),
]);
$this->response = $this->response->withStatus(500);
}
$this->viewBuilder()->setOption('serialize', ['success', 'data', 'message']);
}
}