Overview
Paw & Care uses Supabase authentication with JWT (JSON Web Token) based authentication. All API requests must include a valid JWT token in the Authorization header.
Getting Started
Set up your Supabase project credentials:
VITE_SUPABASE_URL=https://your-project.supabase.co
VITE_SUPABASE_ANON_KEY=your-anon-key
2. Initialize Supabase Client
import { createClient } from '@supabase/supabase-js' ;
const supabase = createClient (
process . env . VITE_SUPABASE_URL ,
process . env . VITE_SUPABASE_ANON_KEY
);
Authentication Flow
Sign Up
Create a new user account:
const { data , error } = await supabase . auth . signUp ({
email: '[email protected] ' ,
password: 'secure-password' ,
options: {
data: {
firstName: 'Sarah' ,
lastName: 'Chen' ,
role: 'veterinarian'
}
}
});
Sign In
Authenticate an existing user:
const { data , error } = await supabase . auth . signInWithPassword ({
email: '[email protected] ' ,
password: 'secure-password'
});
if ( data . session ) {
const accessToken = data . session . access_token ;
// Use this token in API requests
}
Get Current Session
Retrieve the active session:
const { data : { session } } = await supabase . auth . getSession ();
if ( session ) {
console . log ( 'User ID:' , session . user . id );
console . log ( 'Access token:' , session . access_token );
}
Sign Out
const { error } = await supabase . auth . signOut ();
Making Authenticated Requests
Using Supabase Client
The Supabase client automatically includes the JWT token:
// Automatically authenticated
const { data : pets } = await supabase
. from ( 'pets' )
. select ( '*' );
Using REST API Directly
Include the JWT token in the Authorization header:
curl -X GET http://localhost:3000/api/pets \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json"
Using API Client
The API client handles token management:
import { petsApi } from '@/lib/api' ;
const pets = await petsApi . getAll ();
Token Management
Token Expiration
JWT tokens expire after 1 hour. Refresh tokens are valid for 30 days.
Auto-Refresh
Supabase automatically refreshes tokens:
supabase . auth . onAuthStateChange (( event , session ) => {
if ( event === 'TOKEN_REFRESHED' ) {
console . log ( 'Token refreshed:' , session ?. access_token );
}
});
Manual Refresh
const { data , error } = await supabase . auth . refreshSession ();
User Roles & Permissions
Available Roles
Full access to all practice data and operations
Read/write access to appointments and records, limited admin access
Access to scheduling, client management, limited medical record access
Full system administration and configuration
Checking User Role
const { data : { user } } = await supabase . auth . getUser ();
const role = user ?. user_metadata ?. role ;
if ( role === 'veterinarian' ) {
// Allow access to sensitive operations
}
Row Level Security (RLS)
Supabase enforces row-level security policies:
Pets Table Policy
-- Users can only access pets from their practice
CREATE POLICY "Users can view their practice pets"
ON pets FOR SELECT
USING (practice_id = auth . jwt () ->> 'practice_id' );
Medical Records Policy
-- Only veterinarians can finalize records
CREATE POLICY "Veterinarians can finalize records"
ON medical_records FOR UPDATE
USING ( auth . jwt () ->> 'role' = 'veterinarian' );
Security Best Practices
Never expose your Supabase service role key in client-side code. Only use the anon key.
Secure Token Storage
// ✅ Good: Store in httpOnly cookie (server-side)
res . cookie ( 'auth-token' , token , {
httpOnly: true ,
secure: true ,
sameSite: 'strict'
});
// ❌ Bad: Store in localStorage (vulnerable to XSS)
localStorage . setItem ( 'token' , token );
Validate Tokens Server-Side
import { createClient } from '@supabase/supabase-js' ;
const supabase = createClient (
process . env . SUPABASE_URL ,
process . env . SUPABASE_SERVICE_KEY // Server-side only
);
const { data : { user }, error } = await supabase . auth . getUser ( token );
Error Handling
Handle authentication errors:
const { data , error } = await supabase . auth . signInWithPassword ({
email ,
password
});
if ( error ) {
switch ( error . message ) {
case 'Invalid login credentials' :
// Show user-friendly error
break ;
case 'Email not confirmed' :
// Prompt to verify email
break ;
default :
console . error ( 'Auth error:' , error );
}
}
Common Error Codes
Missing or invalid JWT token
Valid token but insufficient permissions
Incorrect email or password
Testing Authentication
Test API authentication:
# Check health endpoint (no auth required)
curl http://localhost:3000/api/health
# Test authenticated endpoint
curl -X GET http://localhost:3000/api/pets \
-H "Authorization: Bearer $TOKEN "
Next Steps
Pets API Manage pet records
Appointments Schedule appointments