ADR 0005: Clerk for Authentication
ADR 0005: Clerk for Authentication
Section titled “ADR 0005: Clerk for Authentication”- Status: Accepted
- Date: 2026-04-14
- Deciders: Ideony team
Context
Section titled “Context”Ideony needs consumer and professional sign-up with social login (Google/Apple/Facebook), email/OTP flows, role-based access control, and webhook events for user lifecycle management. Building this from scratch would be a significant, security-critical investment that delays the product.
Decision
Section titled “Decision”Use Clerk as the identity platform. The backend verifies JWTs via @clerk/backend verifyToken(). Webhooks are verified with svix signature using req.rawBody (not JSON.stringify(body)). The mobile app uses @clerk/clerk-expo (not @clerk/expo). Role is stored in Clerk public metadata and extracted via @CurrentUser() — never from request body.
Consequences
Section titled “Consequences”- Social login, OTP, MFA, and session management are handled out of the box.
- Deep theming via
appearance.elements(not justvariables) enables Airbnb-quality UI. - Clerk BAPI session creation for E2E tests bypasses FAPI rate limits (429s).
- Clerk webhooks via svix provide reliable user lifecycle events.
@clerk/clerk-expov2.19.31 exposes old API (create/prepareFirstFactor/attemptFirstFactor/setActive); newerfinalize/password/emailCodeAPI not available in types.ClerkAPIResponseErrordoes not extendError; requires agetClerkMessage()helper.safeIdentifierin Clerk responses is obfuscated (e.g.,j**n@example.com); match bystrategy, not value.
Alternatives considered
Section titled “Alternatives considered”- Auth.js (NextAuth) — rejected: React Native support is limited; not designed for mobile-first.
- Supabase Auth — rejected: couples auth to a specific database platform; Ideony uses its own PostgreSQL.
- Custom JWT auth — rejected: security-critical, high maintenance, delays MVP.