|
| 1 | +# CloudSync Authentication for Developers |
| 2 | + |
| 3 | +## Direct Database Connections from Mobile |
| 4 | + |
| 5 | +**NEVER have mobile/web clients connect directly to PostgreSQL, even with pgjwt.** |
| 6 | + |
| 7 | +``` |
| 8 | +❌ DANGEROUS (Don't do this) |
| 9 | +Mobile App → PostgreSQL (direct connection) |
| 10 | + - Exposes database to internet |
| 11 | + - Database credentials in app (can be decompiled) |
| 12 | + - Any client can execute SQL |
| 13 | + - No way to audit/control access |
| 14 | + - Doesn't scale |
| 15 | +
|
| 16 | +✅ CORRECT (Do this) |
| 17 | +Mobile App → Auth Server → PostgreSQL |
| 18 | + - App only talks to lightweight auth service |
| 19 | + - Auth server controls database access |
| 20 | + - Database hidden behind application layer |
| 21 | + - Credentials secure |
| 22 | + - Scalable and auditable |
| 23 | +``` |
| 24 | + |
| 25 | +**Even for quick testing:** Provide a real-world example (auth server), not a shortcut that teaches bad practices. Quick start should resemble production architecture. |
| 26 | + |
| 27 | +--- |
| 28 | + |
| 29 | +## Understanding JWT Authentication Patterns |
| 30 | + |
| 31 | +PostgreSQL projects use these main patterns: |
| 32 | + |
| 33 | +### Core Patterns |
| 34 | + |
| 35 | +1. **Database-native** — Validate tokens inside PostgreSQL |
| 36 | + - Best for: PostgREST, API-first architectures |
| 37 | + - Limitation: Requires JWKS endpoint, less flexibility |
| 38 | + - Database handles auth logic |
| 39 | + |
| 40 | +2. **Application-layer** ← **What CloudSync implements** |
| 41 | + - Validate tokens in the microservice |
| 42 | + - Pass user context to PostgreSQL (as JSON claims) |
| 43 | + - Full control, scalable, industry standard |
| 44 | + - Separates auth from database |
| 45 | + |
| 46 | +3. **Hybrid** — Both API and DB validate |
| 47 | + - Application validates JWT signature |
| 48 | + - Database enforces RLS policies using claims |
| 49 | + - Defense-in-depth approach |
| 50 | + - Recommended for sensitive data |
| 51 | + |
| 52 | +### Common Variations |
| 53 | + |
| 54 | +4. **API Gateway Pattern** — Validation at gateway layer |
| 55 | + - Gateway validates JWT, extracts claims |
| 56 | + - Passes claims to backend microservices as headers/context |
| 57 | + - Still application-layer, just centralized |
| 58 | + |
| 59 | +5. **Token Introspection Pattern** — Dynamic validation |
| 60 | + - Instead of signature validation, call auth service: "is this token valid?" |
| 61 | + - Better for token revocation, shorter-lived tokens |
| 62 | + - Adds latency (requires extra call per request) |
| 63 | + |
| 64 | +6. **Service-to-Service JWT** — Internal microservice authentication |
| 65 | + - Services authenticate to each other with JWTs |
| 66 | + - Different from client authentication |
| 67 | + - Uses same JWT mechanisms |
| 68 | + |
| 69 | +**CloudSync uses pattern 2 (application-layer)** with pattern 3 (RLS). |
| 70 | + |
| 71 | +--- |
| 72 | + |
| 73 | +## PostgreSQL JWT Extensions: Why We Don't Recommend Them |
| 74 | + |
| 75 | +**pg_session_jwt** (Neon Extension) |
| 76 | +- ✅ Validates JWTs at database layer with RLS integration |
| 77 | +- ✅ Good for: PostgREST, Postgres-centric apps |
| 78 | +- ❌ For CloudSync: Redundant (microservice already validates) |
| 79 | +- ❌ Adds DB-layer complexity without benefit |
| 80 | +- ❌ Not portable (Neon-specific initially) |
| 81 | + |
| 82 | +**pgjwt** (GitHub Extension) |
| 83 | +- ✅ Generates + verifies JWTs in SQL |
| 84 | +- ❌ HS256-only (no key rotation, no RS256) |
| 85 | +- ❌ **CRITICAL:** Clients cannot connect directly to PostgreSQL |
| 86 | +- ❌ **DEPRECATED:** Removed in PostgreSQL 17+ (not forward-compatible) |
| 87 | +- Only use for: Learning (local development only, PostgreSQL 15 or earlier) |
| 88 | + |
| 89 | +**Custom extensions you might find:** |
| 90 | +- Various community JWT extensions exist but have limited adoption |
| 91 | +- Most have the same issues: HS256-only, adds DB load, not portable |
| 92 | +- Evaluate against: production-readiness, portability, flexibility, maintenance |
| 93 | + |
| 94 | +**Verdict:** Extensions add complexity without benefits for CloudSync. Application-layer validation (auth server) is: |
| 95 | +- ✅ Simpler (use standard JWT libraries) |
| 96 | +- ✅ More flexible (HS256, RS256, ES256, etc.) |
| 97 | +- ✅ More secure (database stays hidden) |
| 98 | +- ✅ Better separation of concerns |
| 99 | +- ✅ Scales independently |
| 100 | +- ✅ **Industry standard** (PostgREST uses this pattern with Auth0, custom auth servers, etc.) |
| 101 | + |
| 102 | +**PostgREST (industry benchmark):** |
| 103 | +PostgREST doesn't generate JWTs. Instead, it validates JWTs from **external auth services** (Auth0, custom servers) and uses the JWT's `role` claim to control database access. |
| 104 | + |
| 105 | +--- |
| 106 | + |
| 107 | +## Recommended Authentication Methods for CloudSync |
| 108 | + |
| 109 | +### 1. Auth Server + HS256 (Development) |
| 110 | +**Best for:** Development and testing |
| 111 | + |
| 112 | +```javascript |
| 113 | +// auth-server/server.js |
| 114 | +app.post('/token', (req, res) => { |
| 115 | + const token = jwt.sign( |
| 116 | + { sub: 'user-123', role: 'authenticated' }, |
| 117 | + process.env.JWT_SECRET, |
| 118 | + { expiresIn: '24h', algorithm: 'HS256' } |
| 119 | + ); |
| 120 | + res.json({ token }); |
| 121 | +}); |
| 122 | +``` |
| 123 | + |
| 124 | +**Pros:** Simple, separate from database, real-world pattern |
| 125 | + |
| 126 | +**Cons:** Can't rotate keys without redeployment, secret must sync across services |
| 127 | + |
| 128 | +### 2. Auth Server + RS256 (Production) |
| 129 | +**Best for:** Production deployments |
| 130 | + |
| 131 | +```bash |
| 132 | +# Generate RSA keys once, persist to volume |
| 133 | +openssl genrsa -out private.pem 2048 |
| 134 | +openssl rsa -in private.pem -pubout -out public.pem |
| 135 | + |
| 136 | +# Auth server signs with private.pem |
| 137 | +# CloudSync fetches public key via JWKS endpoint |
| 138 | +# Keys can be rotated without redeployment |
| 139 | +``` |
| 140 | + |
| 141 | +**Pros:** Industry standard, asymmetric, key rotation, production-ready |
| 142 | + |
| 143 | +**Cons:** More setup complexity |
| 144 | + |
| 145 | +--- |
| 146 | + |
| 147 | +## Learning: pgjwt (Backend Developers Only) |
| 148 | + |
| 149 | +**Not recommended for CloudSync testing**, but useful for understanding token generation: |
| 150 | + |
| 151 | +```sql |
| 152 | +CREATE EXTENSION IF NOT EXISTS pgjwt; |
| 153 | + |
| 154 | +-- Backend developer tests token generation |
| 155 | +SELECT sign( |
| 156 | + json_build_object('sub', 'user-123', 'role', 'authenticated'), |
| 157 | + 'secret-key', |
| 158 | + 'HS256' |
| 159 | +) AS token; |
| 160 | + |
| 161 | +-- Test RLS with generated token |
| 162 | +SET request.jwt.claims = '{"sub":"user-123"}'; |
| 163 | +SELECT * FROM todos; -- Verify RLS filters correctly |
| 164 | +``` |
| 165 | + |
| 166 | +**When to use:** Backend developers learning RLS, testing SQL token logic |
| 167 | + |
| 168 | +**When NOT to use:** Testing CloudSync (still requires auth server for clients) |
| 169 | + |
| 170 | +**Why not for CloudSync:** Even though pgjwt generates tokens, you still need an auth server because clients can't connect to PostgreSQL. Use a simple auth server instead — it's simpler, real-world, and PostgreSQL 17+ compatible. |
| 171 | + |
| 172 | +--- |
| 173 | + |
| 174 | +## Client Apps (Android/Web/SQLite) |
| 175 | + |
| 176 | +### How to get a JWT token |
| 177 | + |
| 178 | +**Flow for all client types:** |
| 179 | +``` |
| 180 | +Client app |
| 181 | + ↓ (HTTP POST /auth/login) |
| 182 | +Auth Server (generates JWT) |
| 183 | + ↓ (returns JWT) |
| 184 | +Client app (stores & uses JWT) |
| 185 | + ↓ (HTTP request with Authorization: Bearer <token> through cloudsync extension) |
| 186 | +CloudSync Microservice |
| 187 | +``` |
0 commit comments