A fast and lightweight HTTP proxy for LanguageTool with OIDC authentication and per-user API keys.
- OIDC Authentication: Login via any OpenID Connect provider (Keycloak, Dex, Auth0, etc.)
- Per-User API Keys: Each user gets a unique 64-character API key
- Simple UI: Single-page dashboard with pure HTML/CSS
- API Key Regeneration: Users can regenerate their API key at any time
- Reverse Proxy: Proxies requests to LanguageTool backend with API key validation
go build -o languagetool-proxy ./cmd/serverCopy the example file and fill in your values. The example file contains detailed descriptions of all configuration options.
cp .env.example .env./languagetool-proxyThe server will automatically load the .env file if it exists in the current directory.
- User visits the proxy URL
- User is redirected to OIDC login
- After successful login, user is redirected to the dashboard
- Dashboard shows the user's API key
- User can use the API key in their LanguageTool requests
https://your-proxy-domain.com/{API_KEY}/v2/
You can use cURL to test the API:
curl -si \
-d "language=en-US" \
-d "text=a simple test" \
https://proxy.example.com/a1b2c3d4e5f6.../v2/check- Click "Regenerate API Key" on the dashboard
- Old key is immediately invalidated
- New 64-character key is generated and displayed
- Update your applications with the new key
┌─────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Browser │────▸│ LanguageTool │────▸│ LanguageTool │
│ │ │ User Proxy │ │ Backend │
└─────────────┘ └──────────────────┘ └─────────────────┘
│
▾
┌──────────────────┐
│ SQLite DB │
│ (users, keys) │
└──────────────────┘
- API keys are stored as SHA-256 hashes (never plain text)
- Sessions use secure, HTTP-only cookies
- Session expiration with auto-extend
- HTTPS should be handled by a reverse proxy (Caddy, Nginx)
FROM golang:1.25-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o server ./cmd/server
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/server .
EXPOSE 8080
CMD ["./server"]go build -o languagetool-user-proxy cmd/server/main.goMIT