Skip to main content

Overview

HoodCloud uses Clerk as the primary authentication provider. Clerk enables authentication via email, social login, wallet-based sign-in, and other identity methods. When Clerk is enabled (default):
  • Clerk issues JWTs that HoodCloud validates via JWKS
  • User accounts are created and updated automatically via Clerk webhooks
  • Users can optionally register a wallet (Ethereum or Solana) after authentication

Prerequisites

  • A Clerk account with an application created
  • The auth-server deployed and accessible via HTTPS (required for webhook delivery)
  • Database migration 020_external_auth_id applied

Configuration

Auth Provider Modes

The AUTH_PROVIDER environment variable controls which JWT validators are active:

Environment Variables

Set AUTH_PROVIDER, AUTH_CLERK_SECRET_KEY, AUTH_CLERK_AUTHORIZED_PARTY on both auth-server and api-server. Set AUTH_CLERK_WEBHOOK_SIGNING_SECRET on auth-server only.
Full reference with defaults and security classifications: Environment Variables

Example Configuration

Obtaining Clerk Credentials

Secret Key

  1. Log in to Clerk Dashboard
  2. Select your application
  3. Go to API Keys
  4. Copy the Secret Key (starts with sk_live_ for production or sk_test_ for development)
  5. Store as AUTH_CLERK_SECRET_KEY
Note: For production, store secrets in Vault at secret/hoodcloud/app-credentials. See Vault Operations for details.

Authorized Party

The authorized party is the URL of your frontend application. Clerk includes this in the azp (authorized party) claim of issued JWTs. HoodCloud validates this claim to ensure tokens were issued for your application. Set AUTH_CLERK_AUTHORIZED_PARTY to a comma-separated list of allowed frontend origins (e.g., https://hoodcloud.io,https://app.hoodcloud.io).

Webhook Signing Secret

The signing secret is generated when you create a webhook endpoint in Clerk. See the next section for webhook setup.

Webhook Configuration

Clerk webhooks notify HoodCloud when users are created, updated, or deleted. The auth-server processes these events at POST /webhooks/clerk.

Setup in Clerk Dashboard

  1. Go to Webhooks in the Clerk Dashboard
  2. Click Add Endpoint
  3. Set the endpoint URL to your auth-server’s public URL:
  4. Subscribe to these events:
    • user.created
    • user.updated
    • user.deleted
  5. Click Create
  6. Copy the Signing Secret (starts with whsec_)
  7. Store as AUTH_CLERK_WEBHOOK_SIGNING_SECRET

Webhook Events

Webhook Security

Webhooks are verified using Svix HMAC-SHA256 signature verification. The auth-server rejects any request with an invalid or missing signature. The webhook endpoint:
  • Does not require JWT authentication
  • Does not have rate limiting (Clerk controls delivery rate)
  • Is mounted conditionally — only when AUTH_PROVIDER is clerk or both

User Lifecycle

Clerk-Authenticated Users

  1. User signs up or logs in via Clerk (email, social, etc.)
  2. Clerk sends user.created webhook → HoodCloud creates local user with external_auth_id
  3. User’s frontend receives a Clerk JWT
  4. Frontend sends JWT to HoodCloud API → Clerk validator verifies via JWKS and resolves to local user ID
  5. (Optional) User registers an Ethereum wallet via POST /api/v1/wallet/register-public-key

Wallet Registration

Clerk-authenticated users can register an Ethereum or Solana wallet: Endpoint: POST /api/v1/wallet/register-public-key Request (Ethereum):
Request (Solana):
  • The message must contain the authenticated user’s UUID
  • Ethereum: The signature must be a valid EIP-191 personal_sign over the message
  • Solana: The signature must be a valid Ed25519 signature over the message bytes
  • The server auto-detects the wallet type from the address format and verifies accordingly
Response (200):

Migration Path: SIWE to Clerk

Phase 1: Enable Multi-Provider Mode

Deploy with both validators active:
In this mode:
  • Existing SIWE users continue authenticating with wallet signatures
  • New Clerk users are created via webhooks
  • The multi-validator tries Clerk first, then falls back to SIWE
  • Both token types are accepted on all API endpoints

Phase 2: Migrate Frontend

  1. Integrate Clerk SDK into the frontend
  2. Update sign-in flows to use Clerk
  3. Existing SIWE sessions remain valid until they expire
  4. New sessions use Clerk JWTs

Phase 3: Switch to Clerk-Only

Once all users are migrated:
This disables SIWE JWT validation. The SIWE auth endpoints (/auth/nonce, /auth/verify) remain on the auth-server but issued tokens will no longer be accepted by the API server.

Database Changes

Migration 020_external_auth_id makes the following schema changes: These changes are backward-compatible. Existing SIWE users retain their wallet_address and have external_auth_id = NULL.

Troubleshooting

Webhook signature verification fails

Symptom: Auth-server logs Failed to verify webhook signature Causes:
  • AUTH_CLERK_WEBHOOK_SIGNING_SECRET does not match the signing secret in Clerk Dashboard
  • The webhook endpoint URL in Clerk does not match the auth-server’s actual URL
  • A proxy or load balancer is modifying request headers
Fix: Verify the signing secret matches. Re-create the webhook endpoint in Clerk if needed.

User not found after Clerk login

Symptom: API returns authentication errors for Clerk-authenticated users. Validator logs no local account for clerk user. Causes:
  • The user.created webhook was not delivered or failed
  • Webhook endpoint is not reachable from Clerk’s servers
  • AUTH_CLERK_WEBHOOK_SIGNING_SECRET is missing (webhook handler not initialized)
Fix:
  1. Check Clerk Dashboard → Webhooks → check delivery status for the endpoint
  2. Verify the auth-server is reachable at the configured webhook URL
  3. Check auth-server logs for webhook processing errors
  4. Manually trigger a re-delivery from Clerk Dashboard if needed

Authorized party mismatch

Symptom: Validator logs verify authorized party: got "X", want one of [...] Cause: AUTH_CLERK_AUTHORIZED_PARTY does not include the azp claim origin from the Clerk JWT. Fix: Add the missing frontend origin to AUTH_CLERK_AUTHORIZED_PARTY (comma-separated list).

Multi-provider mode — wrong validator used

Symptom: SIWE tokens fail validation, or Clerk tokens fail validation in both mode. Note: In both mode, the multi-validator tries Clerk first, then SIWE. If a SIWE token is passed to the Clerk validator, it will fail (expected), and the multi-validator will fall back to SIWE. This is normal behavior — no action needed unless both validators fail.