feat: allow each user to create API keys#955
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Related Knowledge 1 document with suggested updates is ready for review. Zerobyte's Space User Authentication and Account ManagementView Suggested Changes@@ -95,6 +95,34 @@
| `createdAt` | timestamp | Creation time (default: current timestamp) |
| `aaguid` | text | Authenticator attestation GUID |
+### API Key Table
+The [apikey table](https://github.com/nicotsx/zerobyte/blob/fdd8edec702ac43721ceffce5ac9af5cf4e545d5/app/server/db/schema.ts) stores API keys for programmatic authentication:
+
+| Field | Type | Description |
+|-------|------|-------------|
+| `id` | text | Primary key |
+| `name` | text | Optional user-provided name for the API key |
+| `key` | text | Hashed API key value |
+| `referenceId` | text | Foreign key to users table (indexed for efficient user lookup) |
+| `prefix` | text | Key prefix (e.g., "zb_") |
+| `start` | text | Key prefix displayed to users for identification |
+| `configId` | text | Configuration identifier (default: "default") |
+| `enabled` | boolean | Whether the key is enabled |
+| `rateLimitEnabled` | boolean | Whether rate limiting is enabled for this key |
+| `rateLimitTimeWindow` | integer | Rate limit time window in seconds |
+| `rateLimitMax` | integer | Maximum requests in the time window |
+| `requestCount` | integer | Current request count |
+| `remaining` | integer | Remaining requests in the current window |
+| `refillInterval` | integer | Interval for refilling rate limit quota |
+| `refillAmount` | integer | Amount to refill on each interval |
+| `lastRefillAt` | timestamp | Last time the rate limit was refilled |
+| `permissions` | text | Optional permissions data |
+| `metadata` | text | JSON metadata (stores `organizationId` for organization context) |
+| `createdAt` | timestamp | Creation time |
+| `updatedAt` | timestamp | Last update time |
+| `expiresAt` | timestamp | Optional expiration time |
+| `lastRequest` | timestamp | Last time the key was used |
+
### SSO Provider Table
The [SSO provider table](https://github.com/nicotsx/zerobyte/blob/fdd8edec702ac43721ceffce5ac9af5cf4e545d5/app/server/db/schema.ts#L176-L202) stores Single Sign-On provider configurations:
@@ -132,6 +160,10 @@
- **`sso()`** - Single Sign-On support for OIDC and SAML providers with organization provisioning
- **`twoFactor()`** - TOTP-based 2FA with 5 encrypted backup codes
- **`passkey()`** - WebAuthn-based passkey authentication for passwordless sign-in
+- **`apiKey()`** - API key authentication from `@better-auth/api-key` package:
+ - Default prefix: `"zb_"`
+ - Metadata enabled for storing organization context
+ - Rate limiting enabled when `!config.flags.disableRateLimiting`
- **`tanstackStartCookies()`** - Cookie handling for TanStack Start framework
- **`testUtils()`** - Testing utilities (loaded only when `NODE_ENV === "test"`)
@@ -293,11 +325,22 @@
#### Backend Authentication Middleware
**[`requireAuth`](https://github.com/nicotsx/zerobyte/blob/fdd8edec702ac43721ceffce5ac9af5cf4e545d5/app/server/modules/auth/auth.middleware.ts#L22-L50)**
-Applied to protected API routes to ensure user authentication:
-1. Calls `auth.api.getSession()` to retrieve the current session
-2. Validates the user belongs to an organization
-3. Sets request context: `c.set("user", user)` and `c.set("organizationId", activeOrganizationId)`
-4. Makes user and organization data available throughout the request lifecycle
+Applied to protected API routes to ensure user authentication. This middleware supports two authentication methods:
+
+1. **Session-based authentication** (default):
+ - Calls `auth.api.getSession()` to retrieve the current session from cookies
+ - Validates the user belongs to an organization
+ - Sets request context: `c.set("user", user)` and `c.set("organizationId", activeOrganizationId)`
+
+2. **API key authentication** (via `x-api-key` header):
+ - Checks for the `x-api-key` HTTP header
+ - Calls `auth.api.verifyApiKey()` to validate the API key
+ - Verifies the key is associated with a valid user and organization
+ - Extracts `organizationId` from the key's metadata
+ - Validates the user has membership in the associated organization
+ - Sets request context with user and organization data
+
+The middleware first checks for an API key header. If present, it authenticates via API key. Otherwise, it falls back to session-based authentication.
**[`requireOrgAdmin`](https://github.com/nicotsx/zerobyte/blob/fdd8edec702ac43721ceffce5ac9af5cf4e545d5/app/server/modules/auth/auth.middleware.ts#L56-L71)**
|
|
Thanks for putting this together @nguyenquyhy I already had a work-in-progress implementation for API keys on a local branch. I wish you had discussed this in the issue before jumping into implementation, because we ended up duplicating the same feature in parallel. I am keeping the useful pieces from your branch: the zb_ prefix and expiration support. Those will be folded into the main API-key implementation in a commit with you as the co-author. See the PR here |
|
Don't worry. I just needed it right away for my homepage dashboard, and I also want to understand more about zerobyte implementation so I jumped in. Please feel free to close this if you already have something else lined up. |
Allow each user to add API keys to authenticate from API clients (e.g. homepage widget) using x-api-key HTTP header.
#109