Authentication Flow with Better Auth Plugins
This document describes the complete authentication and authorization flow across the Gremlin system with the new Better Auth plugin architecture.System Architecture Overview
1. User Registration Flow
Step-by-Step Process
1.1 User Initiates Sign-Up
1.2 Bun Backend Processes Registration
1.3 Frontend Receives Token
2. User Login Flow
Step-by-Step Process
2.1 User Initiates Sign-In
2.2 Bun Backend Verifies Credentials
2.3 Frontend Receives Token
3. Authenticated Request Flow (Go Backend)
Step-by-Step Process
3.1 Frontend Makes Authenticated Request
3.2 Bun Backend Verifies JWT (if applicable)
3.3 Go Backend Processes Request
4. Organization Management Flow
4.1 Create Organization
4.2 Invite Member to Organization
4.3 Accept Invitation (Optional Flow)
5. Permission Query Flow (Go Backend)
Authorization for Protected Operations
Cache Invalidation Flow
6. Role Hierarchy & Permissions
Platform Roles (Better Auth Admin Plugin)
Organization Roles (Better Auth Organization Plugin)
7. Error Handling
Common Error Scenarios
| Scenario | Status Code | Response |
|---|---|---|
| Missing/Invalid JWT | 401 | { "error": "Unauthorized", "message": "Invalid token" } |
| Expired JWT | 401 | { "error": "Unauthorized", "message": "Token expired" } |
| Insufficient permissions | 403 | { "error": "Forbidden", "message": "Insufficient permissions" } |
| User not found | 404 | { "error": "Not Found", "message": "User not found" } |
| Organization not found | 404 | { "error": "Not Found", "message": "Organization not found" } |
| Duplicate email | 409 | { "error": "Conflict", "message": "Email already exists" } |
| Invalid request | 400 | { "error": "Bad Request", "message": "Invalid input" } |
| Server error | 500 | { "error": "Internal Server Error", "message": "Something went wrong" } |
8. Security Measures
JWT Security
- Signature: HS256 using shared BETTER_AUTH_SECRET
- Expiration: Typically 24 hours
- Storage: HttpOnly Cookie (recommended) or secure storage
- Transport: HTTPS only (enforced in production)
Password Security
- Hashing: scrypt with salt rounds
- Storage: Hashed passwords in accounts table, never plaintext
- Comparison: Constant-time comparison to prevent timing attacks
Database Security
- Access Control: PostgreSQL user permissions restrict access
- Connection: SSL/TLS encryption in production
- Secrets: Environment variables, not hardcoded
Multi-Tenancy
- Isolation: Organization data accessed via organizationId in context
- RBAC: Role-based access control at organization level
- Audit: Member actions logged for compliance
9. Migration from Old Auth System
Key Changes
- No NATS User Sync: Previously, users were synced via NATS events. Now they’re queried directly from PostgreSQL.
- No Local User Table (Go): Go backend no longer creates/maintains its own users table.
- Direct Query Pattern: Go backend queries Better Auth tables (users, members, organizations).
- Centralized Mutations: All write operations go through Better Auth API on Bun.
For Backend Developers
- Use PermissionService for authorization checks
- Query users/orgs using provided repositories
- Cache invalidation happens via NATS events automatically
- Permission checks are fast (cached, with < 50ms latency target)
For Frontend Developers
- Update user/org creation calls to use Better Auth API
- Read operations remain unchanged (Go backend still provides queries)
- Handle new permission error responses (403)
10. Monitoring & Troubleshooting
Key Metrics to Monitor
- Auth latency: Time to verify JWT and fetch user data
- Cache hit rate: Permission cache effectiveness
- NATS connection: Event delivery for cache invalidation
- Database query performance: User/org queries should be < 50ms
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| ”Token expired” errors | JWT expires after 24h | Implement token refresh flow |
| ”Unauthorized” on valid token | Token signature mismatch | Verify BETTER_AUTH_SECRET matches Bun |
| Stale permissions | Cache not invalidated | Check NATS connection and member.role.changed events |
| Slow permission checks | Cache miss, many database hits | Check Redis connection and cache TTL |
| ”User not found” after signup | Database replication lag | Add retry logic with exponential backoff |