Skip to content

@memberjunction/api-keys

Server-side API key management and scope-based authorization engine for MemberJunction. Provides key generation, validation, hierarchical scope evaluation, pattern-based access control, and usage logging.

graph TD
    subgraph "API Key Engine"
        A[APIKeyEngine] --> B[ScopeEvaluator]
        A --> C[PatternMatcher]
        A --> D[UsageLogger]
        A --> E[APIKeysEngineBase<br/>Metadata Cache]
    end

    subgraph "Authorization Flow"
        F[Incoming Request] --> G{Format Valid?}
        G -->|Yes| H{Hash Lookup}
        G -->|No| I[Reject]
        H -->|Found| J{Status Active?}
        H -->|Not Found| I
        J -->|Yes| K{Not Expired?}
        J -->|No| I
        K -->|Yes| L{App Binding OK?}
        K -->|No| I
        L -->|Yes| M[User Context]
        L -->|No| I
    end

    subgraph "Scope Evaluation"
        N[AuthorizationRequest] --> O{App Ceiling<br/>Check}
        O -->|Pass| P{Key Scope<br/>Check}
        O -->|Fail| Q[Denied]
        P -->|Pass| R[Allowed]
        P -->|Fail| Q
    end

    style A fill:#2d6a9f,stroke:#1a4971,color:#fff
    style B fill:#7c5295,stroke:#563a6b,color:#fff
    style C fill:#7c5295,stroke:#563a6b,color:#fff
    style D fill:#7c5295,stroke:#563a6b,color:#fff
    style E fill:#2d8659,stroke:#1a5c3a,color:#fff
    style R fill:#2d8659,stroke:#1a5c3a,color:#fff
    style Q fill:#b8762f,stroke:#8a5722,color:#fff
    style I fill:#b8762f,stroke:#8a5722,color:#fff

This package implements a comprehensive API key authorization system with:

  • Key Generation: Cryptographically secure keys in mj_sk_[64 hex] format
  • Key Validation: Format checking, hash lookup, status/expiry verification, app binding checks
  • Two-Level Authorization: Application ceiling + API key scope evaluation
  • Pattern Matching: Wildcard and multi-value patterns for resource-level permissions
  • Usage Logging: Automatic audit trails for all authorization decisions
  • Scope Hierarchy: Structured permission paths (e.g., entity:read, agent:execute)
Terminal window
npm install @memberjunction/api-keys

Requires Node.js 18+ (uses crypto module for key generation and hashing).

Keys follow the format mj_sk_[64 hex characters]:

  • mj_sk_ prefix identifies MemberJunction secret keys
  • 64 hex characters = 32 bytes of cryptographically secure random data
  • Keys are stored as SHA-256 hashes, never in plaintext
graph LR
    A["Application Ceiling<br/>(Maximum allowed)"] --> C{Intersection}
    B["API Key Scopes<br/>(What key grants)"] --> C
    C --> D["Effective<br/>Permissions"]

    style A fill:#2d6a9f,stroke:#1a4971,color:#fff
    style B fill:#7c5295,stroke:#563a6b,color:#fff
    style C fill:#b8762f,stroke:#8a5722,color:#fff
    style D fill:#2d8659,stroke:#1a5c3a,color:#fff

Authorization succeeds only when BOTH levels permit the operation:

  1. Application Ceiling defines the maximum scopes an application allows
  2. API Key Scopes define what scopes are assigned to a specific key
ScopeDescription
full_accessBypass all scope checks
entity:readRead entity records
entity:createCreate new records
entity:updateUpdate existing records
entity:deleteDelete records
view:runExecute RunView queries
agent:executeExecute AI agents
action:executeExecute MJ Actions
prompt:executeExecute AI prompts
query:runExecute SQL queries
metadata:entities:readRead entity metadata
communication:sendSend emails/messages
import { GetAPIKeyEngine } from '@memberjunction/api-keys';
const engine = GetAPIKeyEngine();
await engine.Config(false, contextUser);
const result = await engine.CreateAPIKey({
UserId: 'user-guid',
Label: 'My Integration',
Description: 'Used for CI/CD pipeline',
ExpiresAt: new Date('2026-12-31')
}, contextUser);
if (result.Success) {
// IMPORTANT: Show this key once -- it cannot be recovered
console.log('Raw API Key:', result.RawKey);
console.log('API Key ID:', result.APIKeyId);
}
const result = await engine.ValidateAPIKey({
RawKey: request.headers['x-api-key'],
ApplicationName: 'MCPServer',
Endpoint: '/graphql',
Method: 'POST',
IPAddress: request.ip
}, systemUser);
if (result.IsValid) {
// result.User contains the authenticated UserInfo
// result.APIKeyHash is available for subsequent Authorize() calls
}
const authResult = await engine.Authorize(
apiKeyHash,
'MJAPI', // Application name
'entity:read', // Scope path
'Users', // Resource name
contextUser,
{
endpoint: '/graphql',
method: 'POST',
operation: 'GetUsersRecord'
}
);
if (authResult.Allowed) {
// Proceed with the operation
} else {
console.log('Denied:', authResult.Reason);
console.log('Rules evaluated:', authResult.EvaluatedRules);
}
import { PatternMatcher } from '@memberjunction/api-keys';
PatternMatcher.matches('Users', '*'); // true - wildcard
PatternMatcher.matches('Users', 'Users'); // true - exact
PatternMatcher.matches('Users', 'User*'); // true - prefix
PatternMatcher.matches('Users', '*ers'); // true - suffix
PatternMatcher.matches('Users', '*ser*'); // true - contains
PatternMatcher.matches('Users', 'Users,Roles'); // true - multi-value
const success = await engine.RevokeAPIKey(apiKeyId, contextUser);
ComponentDescription
APIKeyEngineMain orchestrator for key operations and authorization
ScopeEvaluatorTwo-level scope evaluation with priority-based rule matching
PatternMatcherWildcard and multi-value pattern matching for resources
UsageLoggerAudit trail logging for all authorization decisions
APIKeysEngineBaseMetadata caching layer (from @memberjunction/api-keys-base)
import { GetAPIKeyEngine } from '@memberjunction/api-keys';
const engine = GetAPIKeyEngine({
enforcementEnabled: true, // Enable scope checks (default: true)
loggingEnabled: true, // Log all requests (default: true)
defaultBehaviorNoScopes: 'deny', // Keys with no scopes are denied (default)
scopeCacheTTLMs: 60000 // Cache TTL for scope rules
});
EntityDescription
MJ: API KeysAPI key hashes, status, expiration, metadata
MJ: API ScopesHierarchical scope definitions
MJ: API Key ScopesScope rules assigned to specific keys
MJ: API ApplicationsRegistered applications (MJAPI, MCP, A2A)
MJ: API Application ScopesApplication-level scope ceilings
MJ: API Key ApplicationsKey-to-application bindings
Terminal window
npm test
npm run test:coverage

Test files: APIKeyEngine.spec.ts, ScopeEvaluator.spec.ts, PatternMatcher.spec.ts

  1. Default Deny: Keys without scopes have no permissions
  2. Minimal Scopes: Assign only the scopes needed
  3. Resource Restrictions: Use specific patterns instead of * when possible
  4. Expiration: Set expiration dates for temporary keys
  5. Monitoring: Review usage logs for suspicious activity
  6. Rotation: Regularly rotate keys in production

Used by @memberjunction/server (MJAPI), @memberjunction/ai-mcp-server (MCP Server), and @memberjunction/a2aserver (A2A Server).

PackagePurpose
@memberjunction/api-keys-baseMetadata caching layer
@memberjunction/coreRunView, Metadata, UserInfo
@memberjunction/core-entitiesEntity types
@memberjunction/globalClass factory

ISC