The Supabase authentication system has a bug in their session verification that causes "Database error granting user" errors even when authentication is successful. This affects both magic link and password authentication methods.
We've implemented a workaround that bypasses Supabase's session verification while still maintaining security:
- Token Decoding Without Verification: We decode JWT tokens without using Supabase's verification system
- Direct Token Usage: Tokens are used directly for API calls
- Manual Expiration Checks: We manually check token expiration dates
- Decodes JWT tokens without verification
- Validates token expiration manually
- Verifies user profile exists in database
- Extracts user information from token payload
/api/users/*- Uses workaround middleware/api/organizations/*- Uses workaround middleware
- Extracts token from URL hash
- Stores token in localStorage
- Provides clear instructions for token usage
- Client-side authentication management
- Token storage and retrieval
- Automatic expiration checking
- Simplified API calls with authentication
node test-auth-workaround.js YOUR_ACCESS_TOKEN// Send magic link
const auth = new AuthHelper(SUPABASE_URL, SUPABASE_ANON_KEY);
await auth.sendMagicLink('user@example.com', 'http://localhost:3001/callback.html');// In callback.html or your callback page
const auth = new AuthHelper(SUPABASE_URL, SUPABASE_ANON_KEY);
try {
const user = await auth.handleCallback();
console.log('Authenticated as:', user.email);
// Redirect to app
window.location.href = '/dashboard';
} catch (error) {
console.error('Auth failed:', error);
}// Using the auth helper
const auth = new AuthHelper(SUPABASE_URL, SUPABASE_ANON_KEY);
const profile = await auth.apiCall('/api/users/profile');
// Or manually with fetch
const token = localStorage.getItem('codequal_token');
const response = await fetch('/api/users/profile', {
headers: {
'Authorization': `Bearer ${token}`
}
});const auth = new AuthHelper(SUPABASE_URL, SUPABASE_ANON_KEY);
if (auth.isAuthenticated()) {
const user = auth.getCurrentUser();
console.log('Logged in as:', user.email);
} else {
console.log('Not authenticated');
}- DO NOT use the Supabase test tool's "Verify Session" button - it has the bug
- DO NOT call
supabase.auth.getSession()- use the workaround instead - DO store tokens securely in localStorage or sessionStorage
- DO check token expiration before making API calls
While this workaround bypasses Supabase's session verification, it maintains security by:
- Validating token structure and expiration
- Verifying user exists in database
- Using standard JWT decode (not verification, but structure validation)
- Maintaining Bearer token authentication pattern
Once Supabase fixes their session verification bug, you can migrate back by:
- Switching from
authMiddlewareWorkaroundtoauthMiddleware - Using
supabase.auth.getSession()instead of manual token handling - Removing the workaround files
- Ensure you're using the full JWT token, not just part of it
- Check that the token hasn't been truncated
- User needs to sign in again
- Consider implementing refresh token logic
- Ensure user profile is created when user signs up
- Check database triggers are working correctly