Authentication vs Authorization
Two Distinct Concepts
Authentication and authorization are often confused, but they serve fundamentally different purposes. Understanding the distinction is crucial for building secure applications.
Authentication: Who Are You?
Authentication is the process of verifying identity. It answers the question: "Who is this person claiming to be?"
Common Authentication Methods
- Something you know: Password, PIN, security questions
- Something you have: Phone (SMS code), hardware token, authenticator app
- Something you are: Fingerprint, face recognition
- Something you can do: Behavioral biometrics, typing patterns
Authentication Flow
┌─────────────┐ 1. Present credentials ┌─────────────┐
│ User │ ─────────────────────────────→ │ Server │
│ │ │ │
│ "I am │ 2. Verify credentials │ Check: │
│ Alice" │ ←───────────────────────────── │ Is this │
│ │ │ Alice? │
│ │ 3. Issue proof (token) │ │
│ │ ←───────────────────────────── │ │
└─────────────┘ └─────────────┘
Authentication Results
- Success: User identity is confirmed, usually resulting in a token or session
- Failure: Identity cannot be verified, access denied
Real-World Analogy
Authentication is like showing your ID at a building entrance. The security guard checks if you are who you claim to be—they verify your identity.
Authorization: What Can You Do?
Authorization is the process of determining permissions. It answers: "What is this authenticated user allowed to do?"
Authorization Flow
┌─────────────┐ 1. Request action ┌─────────────┐
│ User │ ─────────────────────────────→ │ Server │
│ (Alice) │ │ │
│ │ 2. Check permissions │ Can Alice │
│ "Delete │ │ delete │
│ post #5" │ 3. Allow or deny │ post #5? │
│ │ ←───────────────────────────── │ │
└─────────────┘ └─────────────┘
Authorization Considers
- Identity: Who is making the request?
- Resource: What are they trying to access?
- Action: What operation do they want to perform?
- Context: When, where, and under what circumstances?
Real-World Analogy
Authorization is like having a key card that only opens certain doors. You've proven who you are (authentication), but the key card determines which rooms you can enter (authorization).
The Relationship
Authentication must happen before authorization. You can't determine what someone can do until you know who they are.
┌─────────────────────────────────────────────────────────────┐
│ Request Flow │
│ │
│ 1. Who are you? 2. What can you do? │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ │ Pass │ │ Pass │
│ │Authentication│────────→│Authorization │──────→ Resource │
│ │ │ │ │ │
│ └──────────────┘ └──────────────┘ │
│ │ │ │
│ │ Fail │ Fail │
│ ▼ ▼ │
│ 401 Unauthorized 403 Forbidden │
│ "Who are you?" "You can't do that" │
└─────────────────────────────────────────────────────────────┘
HTTP Status Codes
- 401 Unauthorized: Authentication failed (poorly named—should be "Unauthenticated")
- 403 Forbidden: Authorization failed (authenticated but not permitted)
Authentication Without Authorization
Possible but limited:
// Anyone who logs in can access everything
if (isAuthenticated(user)) {
return allData; // No permission checks
}
This treats all users equally—anyone logged in has full access. Rarely appropriate.
Authorization Without Authentication
Sometimes useful:
// Public content anyone can read
if (action === 'read' && resource.isPublic) {
return resource; // No login required
}
Public APIs or content don't require knowing who's asking—they authorize based on the action alone.
Common Authorization Models
Role-Based Access Control (RBAC)
Permissions assigned to roles; users get roles.
Roles:
├── admin: can create, read, update, delete all
├── editor: can create, read, update own content
└── viewer: can read public content
Users:
├── Alice → admin
├── Bob → editor
└── Charlie → viewer
-- Check if user has required role
CREATE POLICY "Admins can do anything"
ON posts
USING (
EXISTS (
SELECT 1 FROM user_roles
WHERE user_id = auth.uid()
AND role = 'admin'
)
);
Attribute-Based Access Control (ABAC)
Permissions based on attributes of user, resource, and environment.
// Complex rule combining multiple attributes
const canAccess = (
user.department === resource.department &&
user.clearanceLevel >= resource.requiredClearance &&
currentTime.isBusinessHours()
);
Ownership-Based Access Control
Users can only access their own resources.
-- User can only see their own posts
CREATE POLICY "Users see own posts"
ON posts FOR SELECT
USING (user_id = auth.uid());
In the Supabase Context
Supabase separates these concerns:
Authentication (GoTrue)
- Handles user signup and login
- Issues JWT tokens
- Manages sessions
- Provides
auth.uid()function
Authorization (Row Level Security)
- Policies define who can do what
- Runs at the database level
- Uses authentication info from JWT
-- This policy combines both concepts:
CREATE POLICY "Users can edit own posts"
ON posts FOR UPDATE
USING (
-- Authorization: Check ownership
user_id = auth.uid() -- auth.uid() comes from authentication
);
Security Implications
Authentication Attacks
- Credential stuffing: Using leaked passwords from other sites
- Brute force: Trying many passwords
- Phishing: Tricking users into revealing credentials
- Session hijacking: Stealing active sessions
Authorization Attacks
- Privilege escalation: Gaining higher permissions than intended
- IDOR: Insecure Direct Object Reference (accessing others' resources)
- Missing function-level access control: Bypassing checks
Defense in Depth
Never rely on a single layer:
// Frontend check (easily bypassed)
if (user.role === 'admin') {
showDeleteButton();
}
// API check (important)
if (!user.isAdmin) {
throw new Error('Forbidden');
}
// Database check (critical - last line of defense)
CREATE POLICY "Only admins can delete"
ON posts FOR DELETE
USING (is_admin(auth.uid()));
Best Practices
For Authentication
- Never store plain-text passwords: Use proper hashing
- Implement rate limiting: Prevent brute force
- Use HTTPS everywhere: Protect credentials in transit
- Support MFA: Additional security layer
- Secure session management: Proper token handling
For Authorization
- Principle of least privilege: Grant minimum necessary permissions
- Check at every layer: Frontend, API, and database
- Default deny: Explicitly grant access, don't explicitly deny
- Audit access: Log who accessed what
- Regular reviews: Permissions tend to accumulate
Key Takeaways
- Authentication verifies identity: "Who are you?"
- Authorization determines permissions: "What can you do?"
- Authentication comes first: You must identify before you can authorize
- Both are essential: One without the other leaves gaps
- Defense in depth: Check at multiple layers
- Supabase separates concerns: GoTrue for auth, RLS for authorization
Looking Ahead
Now that you understand the distinction, we'll explore how Supabase Auth (GoTrue) handles authentication and how JWT tokens carry identity information.
Security isn't about one perfect lock—it's about multiple barriers that each make unauthorized access harder. Authentication and authorization are two essential barriers in that defense.

