[PR #7053] feat(api-key): add referenceId support and authorization hook #7045

Open
opened 2026-03-13 13:22:18 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/7053
Author: @Pankaj3112
Created: 12/29/2025
Status: 🔄 Open

Base: canaryHead: feat/api-keys-reference-scope


📝 Commits (1)

  • fc4c45a feat(api-key): add referenceId support and authorization hook

📊 Changes

11 files changed (+696 additions, -87 deletions)

View changed files

📝 packages/better-auth/src/plugins/api-key/adapter.ts (+174 -72)
📝 packages/better-auth/src/plugins/api-key/api-key.test.ts (+298 -0)
📝 packages/better-auth/src/plugins/api-key/error-codes.ts (+3 -0)
📝 packages/better-auth/src/plugins/api-key/index.ts (+7 -0)
📝 packages/better-auth/src/plugins/api-key/routes/create-api-key.ts (+46 -1)
📝 packages/better-auth/src/plugins/api-key/routes/delete-api-key.ts (+29 -1)
📝 packages/better-auth/src/plugins/api-key/routes/get-api-key.ts (+29 -5)
📝 packages/better-auth/src/plugins/api-key/routes/list-api-keys.ts (+50 -1)
📝 packages/better-auth/src/plugins/api-key/routes/update-api-key.ts (+33 -5)
📝 packages/better-auth/src/plugins/api-key/schema.ts (+10 -1)
📝 packages/better-auth/src/plugins/api-key/types.ts (+17 -1)

📄 Description

What this PR does

Fixes #4746

Adds referenceId support to the API Key plugin, allowing keys to be associated with external entities (such as organizations or projects) and enabling custom authorization logic for managing these keys.

Key Changes

  • Schema Update: Added referenceId field to the apiKey table schema.
  • New Hook: Introduced authorizeReference hook in plugin options to control access to keys based on their referenceId.
  • Authorization Logic: Updated get, list, update, and delete operations to check authorizeReference. This allows authorized users (e.g., organization admins) to manage keys they don't own.
  • Creation Flow: Updated create endpoint to accept and store referenceId.

Configuration

apiKey({
  authorizeReference: async ({ referenceId, user }, ctx) => {
    // Example: Allow if user is an admin of the organization (referenceId)
    const membership = await db.findMembership(user.id, referenceId);
    return membership?.role === "admin";
  }
})

Usage

// Client: Create a key for a specific organization
await authClient.apiKey.create({
    name: "Production Key",
    referenceId: "org_123"
});

// Client: List keys for an organization
await authClient.apiKey.list({
    query: {
        referenceId: "org_123"
    }
});

// Client: Admin updates a key they don't own (authorized via hook)
await authClient.apiKey.update({
    keyId: "key_abc",
    name: "Updated Name"
});

Testing

Creation: Verified keys are created with the correct referenceId.
Authorization: Verified authorizeReference hook is called with correct parameters.
Cross-User Access: Verified that a user (e.g., admin) can manage keys created by another user if authorized by the hook.
Security: Verified that operations fail with UNAUTHORIZED_REFERENCE when the hook returns false.

Breaking Changes

None - The referenceId field is optional, and the authorizeReference hook defaults to standard ownership checks if not provided. Existing functionality remains unchanged.


Summary by cubic

Adds referenceId support to API keys and a new authorization hook so org/project-scoped keys can be created and managed by authorized users (e.g., admins). Endpoints now enforce access by referenceId and support filtering by it.

  • New Features

    • Added referenceId to API keys; create/list/get/update/delete now handle it, with list supporting query.referenceId.
    • Introduced authorizeReference hook to gate access when the requester isn’t the owner; returns UNAUTHORIZED_REFERENCE on denial and REFERENCE_ID_REQUIRED on create when the hook is enabled.
    • Updated storage and DB queries to index and list keys by userId and referenceId for secondary storage and fallback paths.
  • Migration

    • No breaking changes. If you enable authorizeReference, send referenceId on create and implement the hook to define who can manage keys for that reference.

Written for commit fc4c45a22b. Summary will update automatically on new commits.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/7053 **Author:** [@Pankaj3112](https://github.com/Pankaj3112) **Created:** 12/29/2025 **Status:** 🔄 Open **Base:** `canary` ← **Head:** `feat/api-keys-reference-scope` --- ### 📝 Commits (1) - [`fc4c45a`](https://github.com/better-auth/better-auth/commit/fc4c45a22bcd6314ff08b72a01c8365966ce89d8) feat(api-key): add referenceId support and authorization hook ### 📊 Changes **11 files changed** (+696 additions, -87 deletions) <details> <summary>View changed files</summary> 📝 `packages/better-auth/src/plugins/api-key/adapter.ts` (+174 -72) 📝 `packages/better-auth/src/plugins/api-key/api-key.test.ts` (+298 -0) 📝 `packages/better-auth/src/plugins/api-key/error-codes.ts` (+3 -0) 📝 `packages/better-auth/src/plugins/api-key/index.ts` (+7 -0) 📝 `packages/better-auth/src/plugins/api-key/routes/create-api-key.ts` (+46 -1) 📝 `packages/better-auth/src/plugins/api-key/routes/delete-api-key.ts` (+29 -1) 📝 `packages/better-auth/src/plugins/api-key/routes/get-api-key.ts` (+29 -5) 📝 `packages/better-auth/src/plugins/api-key/routes/list-api-keys.ts` (+50 -1) 📝 `packages/better-auth/src/plugins/api-key/routes/update-api-key.ts` (+33 -5) 📝 `packages/better-auth/src/plugins/api-key/schema.ts` (+10 -1) 📝 `packages/better-auth/src/plugins/api-key/types.ts` (+17 -1) </details> ### 📄 Description ## What this PR does Fixes #4746 Adds `referenceId` support to the API Key plugin, allowing keys to be associated with external entities (such as organizations or projects) and enabling custom authorization logic for managing these keys. ## Key Changes - **Schema Update**: Added `referenceId` field to the `apiKey` table schema. - **New Hook**: Introduced `authorizeReference` hook in plugin options to control access to keys based on their `referenceId`. - **Authorization Logic**: Updated `get`, `list`, `update`, and `delete` operations to check `authorizeReference`. This allows authorized users (e.g., organization admins) to manage keys they don't own. - **Creation Flow**: Updated `create` endpoint to accept and store `referenceId`. ## Configuration ```typescript apiKey({ authorizeReference: async ({ referenceId, user }, ctx) => { // Example: Allow if user is an admin of the organization (referenceId) const membership = await db.findMembership(user.id, referenceId); return membership?.role === "admin"; } }) ``` ## Usage ```typescript // Client: Create a key for a specific organization await authClient.apiKey.create({ name: "Production Key", referenceId: "org_123" }); // Client: List keys for an organization await authClient.apiKey.list({ query: { referenceId: "org_123" } }); // Client: Admin updates a key they don't own (authorized via hook) await authClient.apiKey.update({ keyId: "key_abc", name: "Updated Name" }); ``` ## Testing ✅ **Creation**: Verified keys are created with the correct `referenceId`. ✅ **Authorization**: Verified `authorizeReference` hook is called with correct parameters. ✅ **Cross-User Access**: Verified that a user (e.g., admin) can manage keys created by another user if authorized by the hook. ✅ **Security**: Verified that operations fail with `UNAUTHORIZED_REFERENCE` when the hook returns `false`. ## Breaking Changes None - The `referenceId` field is optional, and the `authorizeReference` hook defaults to standard ownership checks if not provided. Existing functionality remains unchanged. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds referenceId support to API keys and a new authorization hook so org/project-scoped keys can be created and managed by authorized users (e.g., admins). Endpoints now enforce access by referenceId and support filtering by it. - **New Features** - Added referenceId to API keys; create/list/get/update/delete now handle it, with list supporting query.referenceId. - Introduced authorizeReference hook to gate access when the requester isn’t the owner; returns UNAUTHORIZED_REFERENCE on denial and REFERENCE_ID_REQUIRED on create when the hook is enabled. - Updated storage and DB queries to index and list keys by userId and referenceId for secondary storage and fallback paths. - **Migration** - No breaking changes. If you enable authorizeReference, send referenceId on create and implement the hook to define who can manage keys for that reference. <sup>Written for commit fc4c45a22bcd6314ff08b72a01c8365966ce89d8. Summary will update automatically on new commits.</sup> <!-- End of auto-generated description by cubic. --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-03-13 13:22:18 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#7045