Pinned 2026 toolchains (Go 1.26, Rust 1.98/edition 2024, Python 3.14 + uv, Node 24, Zig 0.16, NixOS 26.05), postgres 18 / mongo 8, lockfiles built from, non-root runtimes, .dockerignore, per-project LICENSE, READMEs with the git.devai.io clone line, checkout@v7 CI. Security fixes in the legacy Rust APIs (any-password login, self-assigned admin, hard-coded JWT secret), JWT alg/exp/sub enforcement across the blog series, safe markdown links in the frontends, and many smaller bugs — every project was built, run and exercised end to end. Adds scripts/publish.sh + a CI publish job that splits every folder into its own repo at git.devai.io/templates/<folder>. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01128fhuZbgivaSJvtMf4s1G |
||
|---|---|---|
| .. | ||
| clerk.rs | ||
| README.md | ||
Auth via Clerk
Replaces the local email+password auth with Clerk hosted auth. The app stops issuing tokens itself and instead verifies Clerk session JWTs (RS256) against your instance's JWKS, checking the issuer.
Setup
-
Create an application in the Clerk dashboard and note your instance's Frontend API URL (e.g.
https://your-instance.clerk.accounts.dev) — that is the token issuer. -
Add the HTTP client to
Cargo.toml:reqwest = { version = "0.13", features = ["json"] } -
Copy
clerk.rstosrc/clerk.rsand deletesrc/auth.rs— Clerk hosts sign-up and sign-in. Insrc/main.rs, replacemod auth;withmod clerk;, then remove the/auth/registerand/auth/loginroutes, the unusedpostimport, and thejwt_secretstate field along with itsAUTH_SECRETline. -
In
src/posts.rs:- import the new extractor:
use crate::clerk::AuthUser; - Clerk user ids are strings (
user_...), not UUIDs: changeauthor_id: UuidinPosttoauthor_id: String, theuser_id: Uuidparameter offind_own_posttouser_id: String, and.bind(author_id)increateto.bind(&author_id).
- import the new extractor:
-
In
schema.sql, make the column match and drop the foreign key (CREATE TABLE IF NOT EXISTSwon't alter an existing table, so start from an empty database):author_id TEXT NOT NULL -
Set the environment variable:
CLERK_ISSUER=https://your-instance.clerk.accounts.dev
What to delete
- The
userstable inschema.sql— Clerk is the user store now. Keep it only if you mirror users locally (e.g. via Clerk webhooks), withoutpassword_hash.
Notes
- Clients send the Clerk session token as
Authorization: Bearer <token>(await session.getToken()in Clerk's frontend SDKs). - The JWKS is fetched on first use and cached. A token signed with an unknown key id triggers a refetch (at most once a minute), so key rotations need no restart.
- Clerk also puts the requesting origin in the
azpclaim; if browsers from other sites could hold your users' tokens, add anazp: Stringfield toClaimsand compare it with your frontend's origin.