Auth Service
The Auth service is a thin Go wrapper around Clerk, translating Clerk user events into GospeLib domain events and providing a stable internal interface. It manages user records in PostgreSQL and publishes lifecycle events to Redis Streams.
Quick Reference
| Property | Value |
|---|---|
| Port | 8200 |
| Language | Go |
| Framework | Chi v5 |
| Module path | github.com/gospelib/main/services/auth |
| Entry point | cmd/server/main.go |
| Auth provider | Clerk (Phase 1–2), migratable to custom (Phase 3) |
| Data store | PostgreSQL (gl_users table) |
Responsibilities
- Webhook receiver — Handles Clerk user events (
user.created,user.updated,session.created) - User sync — Persists Clerk user records to the
gl_usersPostgreSQL table - JWT middleware — Shared JWT validation logic reused by the gateway
- User profiles — Exposes
/users/{id}for other services to fetch user data - Entitlement join — Exposes
/users/{id}/entitlementsjoining user records with billing plans - Event publishing — Publishes
user.created/user.updatedevents togl:events:usersRedis Stream
Why Clerk?
Building a production-grade auth system (MFA, magic links, social auth, session management, device trust) is a 2–6 month project. Clerk handles all of this for $0–$100/month at GospeLib's scale. The auth service exists as a wrapper — swapping Clerk for a custom implementation later changes the wrapper, not anything downstream.
Running Locally
cd services/auth
go run ./cmd/server
The service starts on port 8200 and requires PostgreSQL to be running.
Environment Variables
| Variable | Default | Description |
|---|---|---|
GOSPELIB_AUTH_PORT | 8200 | HTTP listen port |
GOSPELIB_AUTH_DATABASE_URL | postgres://localhost:5432/gospelib | PostgreSQL connection string |
GOSPELIB_AUTH_CLERK_WEBHOOK_SECRET | — | Clerk webhook signing secret |
GOSPELIB_AUTH_CLERK_JWKS_URL | — | Clerk JWKS endpoint for JWT validation |
GOSPELIB_AUTH_REDIS_URL | redis://localhost:6380 | Redis for event publishing |
Health Check
curl http://localhost:8200/health
# {"status": "ok"}
Entry Point Pattern
The cmd/server/main.go follows the standard Go service pattern:
- Configure Zerolog (JSON structured logging)
- Load config from environment variables
- Initialize PostgreSQL connection + run migrations
- Create Chi router with middleware
- Register routes — health, webhook (public), user endpoints (internal)
- Start HTTP server in a goroutine
- Wait for
SIGINT/SIGTERM - Graceful shutdown with 10-second context
PostgreSQL Schema
CREATE TABLE gl_users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
clerk_id TEXT UNIQUE NOT NULL,
email TEXT NOT NULL,
display_name TEXT,
plan_id TEXT NOT NULL DEFAULT 'free',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE TABLE gl_user_devices (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES gl_users(id) ON DELETE CASCADE,
platform TEXT NOT NULL CHECK (platform IN ('ios', 'android', 'web')),
push_token TEXT,
app_version TEXT,
last_seen_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);
Docker
FROM golang:1.25-alpine AS builder
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /app ./cmd/server
FROM alpine:3.20
RUN apk --no-cache add ca-certificates
COPY --from=builder /app /app
EXPOSE 8200
ENTRYPOINT ["/app"]
Related Pages
- Clerk Integration — webhook handling and JWT validation flow
- Architecture > Security > Auth Flow — end-to-end authentication
- Billing Service — subscription and entitlement management