KeyHippo extends Supabase's Row Level Security (RLS) to support API key authentication and Role-Based Access Control (RBAC) directly in Postgres.
KeyHippo enables API key authentication and fine-grained access control in Supabase applications while preserving Row Level Security policies. It handles both session-based and API key authentication using SQL and introduces an RBAC system for managing permissions.
Features:
-
API Key Management:
- Secure key issuance and validation
- Key rotation and revocation
- Automatic key expiration
- Claims-based metadata
- HTTP notifications for key events
-
Role-Based Access Control (RBAC):
- Hierarchical group-based permissions
- Built-in roles (admin, user)
- Fine-grained permission management
- Default role assignment for new users
- Create a new Supabase migration for the KeyHippo extension:
supabase migration new add_keyhippo_extension
-
Copy the contents of
extension/keyhippo--1.2.5.sql
into the newly created migration file in thesupabase/migrations
directory. -
Apply the migration to install the extension:
supabase migration up
- For projects with existing users:
SELECT keyhippo.initialize_existing_project();
This will:
- Create default groups (Admin Group, User Group)
- Create default roles (Admin, User)
- Set up default permissions
- Create a default scope
- Assign the User role to existing users (when using initialize_existing_project)
KeyHippo integrates with your Supabase application in two main ways:
- Direct SQL Access: Use KeyHippo functions through your application's database connection
- REST API: Access via PostgREST endpoints (requires valid API key in x-api-key header)
-- Generate a new API key
SELECT * FROM keyhippo.create_api_key('Primary API Key', 'default');
-- Verify an API key (internal use)
SELECT * FROM keyhippo.verify_api_key('your-api-key');
-- Get key metadata in RLS policies
SELECT keyhippo.key_data();
-- Revoke an API key
SELECT keyhippo.revoke_api_key('key-id-uuid');
-- Rotate an existing key
SELECT * FROM keyhippo.rotate_api_key('key-id-uuid');
-- Update key claims
SELECT keyhippo.update_key_claims('key-id-uuid', '{"custom": "data"}'::jsonb);
KeyHippo supports HTTP notifications for:
- Key expiry events
- Audit log events
- Installation tracking
Configure endpoints through keyhippo_internal.config:
-- Set audit log endpoint
UPDATE keyhippo_internal.config
SET value = 'https://your-endpoint.com/audit'
WHERE key = 'audit_log_endpoint';
-- Enable HTTP logging
SELECT keyhippo_internal.enable_audit_log_notify();
Example of a policy supporting both authentication methods and RBAC:
CREATE POLICY "owner_access"
ON "public"."resource_table"
FOR SELECT
USING (
auth.uid() = resource_table.owner_id
AND keyhippo.authorize('manage_resources')
);
This policy grants access when:
- The user is authenticated (via session token or API key)
- They are the owner of the resource
- They have the 'manage_resources' permission
Create a new group, role, and assign permissions:
-- Create a new group
SELECT keyhippo_rbac.create_group('Developers', 'Group for developer users') AS group_id;
-- Create a new role (role_type can be 'admin' or 'user')
SELECT keyhippo_rbac.create_role('Developer', 'Developer role', group_id, 'user'::keyhippo.app_role) AS role_id;
-- Assign permissions to the role (using valid app_permission enum values)
SELECT keyhippo_rbac.assign_permission_to_role(role_id, 'manage_api_keys'::keyhippo.app_permission);
-- Assign the role to a user
SELECT keyhippo_rbac.assign_role_to_user(auth.uid(), group_id, role_id);
Available permissions:
- manage_groups
- manage_roles
- manage_permissions
- manage_scopes
- manage_user_attributes
- manage_api_keys
KeyHippo provides secure user impersonation for debugging purposes:
-- Login as another user (requires postgres role)
CALL keyhippo_impersonation.login_as_user('<user_id>');
-- Login as anonymous user (requires postgres role)
CALL keyhippo_impersonation.login_as_anon();
-- Perform actions as the impersonated user
-- The session will automatically expire after 1 hour
-- End impersonation session
CALL keyhippo_impersonation.logout();
Features:
- Requires postgres role for impersonation
- Automatic session expiration (1 hour)
- Audit logging of impersonation events
- Support for anonymous user impersonation
KeyHippo organizes its functionality across several schemas:
- keyhippo: Main schema for API key management and core functions
- keyhippo_rbac: Role-Based Access Control functionality
- keyhippo_internal: Internal configuration and utilities
- keyhippo_impersonation: User impersonation functionality
KeyHippo provides API key management with the following features:
Key Operations:
-- Create a new API key
SELECT * FROM keyhippo.create_api_key('My API Key', 'default');
-- Revoke an existing key
SELECT keyhippo.revoke_api_key('key-id-uuid');
-- Rotate an existing key
SELECT * FROM keyhippo.rotate_api_key('key-id-uuid');
-- Update key claims
SELECT keyhippo.update_key_claims('key-id-uuid', '{"custom": "data"}'::jsonb);
Integration:
-- Get current key data in RLS policies
SELECT keyhippo.key_data();
-- Check authorization in RLS policies
SELECT keyhippo.authorize('manage_api_keys');
-- Get current user context
SELECT * FROM keyhippo.current_user_context();
KeyHippo provides a RBAC system that integrates with Postgres RLS policies:
- Groups: Logical grouping of users (e.g., "Admin Group", "User Group")
- Roles: Assigned to users within groups, with role types:
- 'admin': Full system access
- 'user': Limited access based on assigned permissions
- Permissions: Built-in permissions:
- manage_groups
- manage_roles
- manage_permissions
- manage_scopes
- manage_user_attributes
- manage_api_keys
On initialization, KeyHippo creates:
- Default groups: "Admin Group" and "User Group"
- Default roles: "Admin" (admin type) and "User" (user type)
- Admin role gets all permissions
- User role gets 'manage_api_keys' permission
- New users automatically get the "User" role
-- Check if user has permission in RLS policy
SELECT keyhippo.authorize('manage_api_keys');
-- Get current user's permissions
SELECT permissions FROM keyhippo.current_user_context();
KeyHippo provides user impersonation functionality to assist with debugging and maintnence tasks.
-- Start impersonation (requires postgres role)
CALL keyhippo_impersonation.login_as_user('<user_id>');
-- Impersonate anonymous user
CALL keyhippo_impersonation.login_as_anon();
-- End impersonation session
CALL keyhippo_impersonation.logout();
- Only postgres role can initiate impersonation
- Sessions automatically expire after 1 hour
- All actions during impersonation are logged
- Original role is preserved and restored on logout
- State tracking prevents session manipulation
KeyHippo's authentication and authorization integrate with Supabase's Row Level Security policies. Use auth.uid() to get the current user's ID and keyhippo.authorize() to check permissions within your RLS policies.
Example RLS Policy:
CREATE POLICY "user_can_view_own_data" ON "public"."user_data"
FOR SELECT USING (
auth.uid() = user_data.user_id
AND keyhippo.authorize('manage_api_keys')
);
Note: The example uses 'manage_api_keys' as it's one of the built-in permissions. Your application can define additional permissions as needed.
We welcome community contributions. For guidance, see our Contributing Guide.
KeyHippo is distributed under the MIT license. See the LICENSE file for details.
- Install Nix (if not already installed):
For Linux/macOS (multi-user installation recommended):
sh <(curl -L https://nixos.org/nix/install) --daemon
For single-user installation:
sh <(curl -L https://nixos.org/nix/install) --no-daemon
- Clone the repository:
git clone https://github.com/integrated-reasoning/KeyHippo.git
cd KeyHippo
- Enter the Nix development shell:
nix develop
- Set up the local Supabase instance:
make setup-supabase
KeyHippo uses pgTAP for testing. To run the test suite:
# Run all tests
make test
# Run pgTAP tests specifically
make pg_tap
The test suite verifies:
- API key management functionality
- RBAC system operations
- Impersonation features
- Security controls
- Integration with RLS policies
For technical support and discussions:
- Open an issue on our GitHub repository
- Follow us on Twitter for updates
- Visit keyhippo.com