ClerkAuth is the Auth component’s Clerk-backed strategy. It wraps the official @clerk/backend SDK to verify session tokens, resolve the current user, and manage accounts — banning, locking, metadata, sessions, and password sign-in — all behind the framework’s IAuth interface. A companion ClerkAuthMiddleware plugs Clerk into the request pipeline and maps a Clerk user onto the framework IUser, so your controllers read context.user and never depend on Clerk directly.
Why Clerk
- Token verification built in.
getCurrentUser(token)verifies the Clerk session token with your secret key and resolves the user in one call. - Drop-in middleware.
ClerkAuthMiddlewareextracts the bearer token, enforces route roles, and maps the Clerk user ontoIUser. - Full account management. Ban, lock, update profiles, manage metadata, and revoke sessions through the Clerk Backend API.
- Password sign-in.
signIn()verifies credentials and mints a Clerk sign-in token. - Container-managed. Registered with
@decorator.auth()and resolved from the container — no manual wiring.
Installation
ClerkAuth ships with @ooneex/auth and depends on the Clerk Backend SDK.
Environment variables
| Variable | Required | Purpose |
|---|---|---|
CLERK_SECRET_KEY | Yes | Clerk Backend API secret key. Missing throws AuthException (API_KEY_REQUIRED). |
ClerkAuth is constructed, so a missing key fails fast at startup rather than on the first request.
How it works
ClerkAuthMiddleware runs in the request pipeline. For each request it:
- Reads the token from the
Authorization: Bearer <token>header (or abearerTokenquery). - Checks the route’s
roles— if the route is guest-only (no roles orROLE_GUEST), it lets the request through without a token. - Otherwise calls
ClerkAuth.getCurrentUser(token), which verifies the token and loads the Clerk user. - Maps the Clerk user onto the framework
IUserand sets it oncontext.user.
privateMetadata (falling back to ROLE_USER), and copies across name, phone, avatar, activity timestamps, and ban/lock flags.
Usage
Register the middleware (andClerkAuth) with the container, then declare route roles — the middleware enforces them automatically.
Password sign-in
signIn() looks up the user by email, verifies the password through Clerk, and returns the user plus a sign-in token (default TTL 30 days):
Account management
ClerkAuth exposes the Clerk user and session APIs directly:
| Method | Purpose |
|---|---|
getCurrentUser(token) | Verify a token and resolve the user, or null. |
getUser(userId) | Fetch a user by id. |
banUser(userId) / unbanUser(userId) | Ban or unban a user. |
isBanned(userId) | Whether the user is banned. |
lockUser(userId) / unlockUser(userId) | Lock or unlock a user. |
isLocked(userId) | Whether the user is locked. |
updateUser(userId, params) | Update user attributes. |
updateUserProfileImage(userId, { file }) | Replace the profile image. |
updateUserMetadata(userId, params) | Update public/private/unsafe metadata. |
getUserMetadata(userId) | Read public/private/unsafe metadata. |
deleteUser(userId) | Delete a user. |
deleteUserProfileImage(userId) | Remove the profile image. |
getSession(sessionId) | Fetch a session. |
getCurrentUserSession(token) | Resolve the session for a token, or null. |
signIn({ email, password, ttl? }) | Verify credentials and mint a sign-in token. |
signOut(sessionId) | Revoke a session. |
Use in the app
In an@ooneex/app application, Clerk plugs in as a request middleware. Add ClerkAuthMiddleware to the middlewares slot of your App config — importing it registers both ClerkAuthMiddleware and ClerkAuth with the container through @decorator.auth(), so there is nothing else to wire.
roles, and maps the Clerk user onto context.user. Controllers then read context.user and declare the roles they require — see Protecting routes above. Set CLERK_SECRET_KEY in your .env.yml (or environment) so the strategy can verify tokens.
Exceptions
ClerkAuth and ClerkAuthMiddleware throw AuthException with a machine-readable key, so callers can branch on it.
| Key | When |
|---|---|
API_KEY_REQUIRED | ClerkAuth is constructed without CLERK_SECRET_KEY. |
INVALID_CREDENTIALS | signIn() is given an unknown email or a wrong password. |
MISSING_BEARER_TOKEN | A protected route is requested without a token. |
INVALID_TOKEN | The token verifies to no user. |
NO_PRIMARY_EMAIL | The Clerk user has no primary email address. |
Best practices
- Keep
CLERK_SECRET_KEYin the environment. Never hard-code it; load it from.envso it stays out of source control. - Store roles and the internal id in Clerk metadata. The middleware reads
privateMetadata.rolesandprivateMetadata.externalId— set them so users map ontoIUsercorrectly. - Read
context.user, not Clerk. Keep controllers provider-agnostic so the auth strategy can change without touching handlers. - Drive access from route roles. Declare
roleson routes and letClerkAuthMiddlewareenforce them instead of re-checking tokens in controllers. - Branch on
AuthException.key. Return401forINVALID_CREDENTIALS,MISSING_BEARER_TOKEN, andINVALID_TOKEN.