Overview
PassTru uses Supabase Authentication for secure user management. All API requests require a valid JWT token obtained through the authentication flow.
Authentication Methods
Supabase Auth supports multiple authentication methods:
Email/Password (primary method)
Magic Links
OAuth providers (Google, GitHub, etc.)
Phone/SMS
Sign Up
Create a new client account:
import { supabase } from '@/integrations/supabase/client'
const { data , error } = await supabase . auth . signUp ({
email: '[email protected] ' ,
password: 'secure-password' ,
options: {
data: {
full_name: 'John Doe'
}
}
})
if ( error ) {
console . error ( 'Sign up error:' , error . message )
} else {
console . log ( 'User created:' , data . user )
}
Response
The authenticated user object Timestamp of account creation
Session object with access and refresh tokens JWT token for API requests
Token to refresh the access token
Token expiration time in seconds
Sign In
Authenticate existing users:
const { data , error } = await supabase . auth . signInWithPassword ({
email: '[email protected] ' ,
password: 'secure-password'
})
if ( error ) {
console . error ( 'Sign in error:' , error . message )
} else {
console . log ( 'Signed in:' , data . session )
}
Get Current Session
Retrieve the active session:
const { data : { session } } = await supabase . auth . getSession ()
if ( session ) {
console . log ( 'Access token:' , session . access_token )
console . log ( 'User:' , session . user )
}
Get Current User
Fetch user details with organization and role information:
// Get authenticated user
const { data : { user } } = await supabase . auth . getUser ()
if ( user ) {
// Fetch user role
const { data : roleData } = await supabase
. from ( 'user_roles' )
. select ( 'role' )
. eq ( 'user_id' , user . id )
. single ()
// Fetch organization
const { data : org } = await supabase
. from ( 'organizations' )
. select ( 'id, slug, name, logo_url' )
. eq ( 'owner_id' , user . id )
. single ()
// Fetch profile
const { data : profile } = await supabase
. from ( 'profiles' )
. select ( 'full_name, avatar_url' )
. eq ( 'user_id' , user . id )
. single ()
console . log ({
user ,
role: roleData ?. role ,
organization: org ,
profile
})
}
Sign Out
End the user session:
const { error } = await supabase . auth . signOut ()
if ( error ) {
console . error ( 'Sign out error:' , error . message )
} else {
console . log ( 'Signed out successfully' )
}
Password Reset
Request Password Reset
const { error } = await supabase . auth . resetPasswordForEmail (
'[email protected] ' ,
{
redirectTo: 'https://yourapp.com/reset-password'
}
)
if ( error ) {
console . error ( 'Reset request error:' , error . message )
} else {
console . log ( 'Reset email sent' )
}
Update Password
const { error } = await supabase . auth . updateUser ({
password: 'new-secure-password'
})
if ( error ) {
console . error ( 'Password update error:' , error . message )
} else {
console . log ( 'Password updated successfully' )
}
Authorization
Check User Role
Use the has_role function to verify user permissions:
const { data : isClient } = await supabase . rpc ( 'has_role' , {
_user_id: user . id ,
_role: 'client'
})
if ( isClient ) {
// User has client role
}
Check Organization Membership
Verify if a user belongs to an organization:
const { data : isMember } = await supabase . rpc ( 'is_org_member' , {
_user_id: user . id ,
_org_id: organizationId
})
if ( isMember ) {
// User is a member of the organization
}
Session Management
Listen for Auth Changes
supabase . auth . onAuthStateChange (( event , session ) => {
switch ( event ) {
case 'SIGNED_IN' :
console . log ( 'User signed in:' , session ?. user )
break
case 'SIGNED_OUT' :
console . log ( 'User signed out' )
break
case 'TOKEN_REFRESHED' :
console . log ( 'Token refreshed:' , session ?. access_token )
break
case 'USER_UPDATED' :
console . log ( 'User updated:' , session ?. user )
break
}
})
Automatic Token Refresh
Supabase automatically refreshes tokens before they expire when autoRefreshToken is enabled in the client configuration.
Making Authenticated Requests
All Supabase client requests automatically include the auth token:
// The Authorization header is automatically added
const { data : events } = await supabase
. from ( 'events' )
. select ( '*' )
. eq ( 'organization_id' , orgId )
// For edge functions, the token is also included automatically
const { data } = await supabase . functions . invoke ( 'send-confirmation-email' , {
body: { attendee_ids: [ 'uuid-1' , 'uuid-2' ] }
})
Row Level Security (RLS)
PassTru uses PostgreSQL Row Level Security to enforce access control at the database level. Users can only access data they own or have been granted permission to view.
Example RLS Policies
Events : Users can only access events from their organization
CREATE POLICY "Users can view their organization's events"
ON events FOR SELECT
USING (
organization_id IN (
SELECT id FROM organizations WHERE owner_id = auth . uid ()
)
);
Attendees : Users can only manage attendees from events they own or are assigned to
CREATE POLICY "Users can manage attendees from their events"
ON attendees FOR ALL
USING (
event_id IN (
SELECT id FROM events WHERE organization_id IN (
SELECT id FROM organizations WHERE owner_id = auth . uid ()
)
)
);
Security Best Practices
Never expose your SUPABASE_SERVICE_ROLE_KEY in client-side code. Use it only in secure server environments.
Use environment variables for API keys
Validate user input before database operations
Implement rate limiting for sensitive operations
Enable MFA for admin accounts
Rotate tokens regularly
Monitor auth logs for suspicious activity
Next Steps
Events API Start creating and managing events
Attendees API Add attendees to your events