UsefulKey
Plugins

Permissions / Scopes

Require scopes at verify time and manage scopes per key. All requested scopes must be present on the key.

How it works

  • Stores scopes in a configurable metadata field on each key (default: "scopes").
  • On verify, if scopes are provided, the key must include all of them or verification rejects with "insufficient_scope".
  • Provides helpers to grant, revoke, set, and read scopes on keys.

Settings

OptionTypeDefaultDescription
metadataKeystring"scopes"Metadata field name used to persist scopes on a key.

Usage

import { usefulkey } from "betterkey";
import { permissionsScopesPlugin } from "usefulkey/plugins/permissions-scopes";

const uk = usefulkey({}, {
  plugins: [
    permissionsScopesPlugin({ /* metadataKey?: "scopes" */ }),
  ],
});

await uk.grantScopes("key_123", ["read", "write"]);
const scopes = await uk.getScopes("key_123");

// Verify: ALL passed scopes must be present on the key (intersection-all)
await uk.verifyKey({ key, scopes: ["write"] });
await uk.verifyKey({ key, scopes: ["read", "write"] });

Functions added

  • uk.grantScopes(id: string, scopes: string | string[]): Promise<void>
  • uk.revokeScopes(id: string, scopes: string | string[]): Promise<void>
  • uk.setScopes(id: string, scopes: string | string[]): Promise<void>
  • uk.getScopes(id: string): Promise<string[]>

Verification behavior

  • When scopes are provided to verifyKey, all must be contained in the key's metadata field.
  • Failure → { valid: false, reason: "insufficient_scope" }.

Emitted analytics:

  • On block: "scopes.blocked" with { keyId, userId, required, have, ts }.
  • On grant: "scopes.granted" with { keyId, added, result, ts }.
  • On revoke: "scopes.revoked" with { keyId, removed, result, ts }.
  • On set: "scopes.set" with { keyId, result, ts }.