Package Exports
- @memberjunction/credentials
- @memberjunction/credentials/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@memberjunction/credentials) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
@memberjunction/credentials
Secure credential management engine for MemberJunction. Provides centralized storage, retrieval, and audit logging of credentials with automatic field-level encryption.
Features
- Centralized Credential Storage - Store all credentials in one place with consistent access patterns
- Field-Level Encryption - Credentials are automatically encrypted at rest using MJ's encryption engine
- Audit Logging - Every credential access is logged for compliance and security monitoring
- Type-Safe Values - Pre-defined interfaces for common credential types (API keys, OAuth, AWS, Azure, etc.)
- Cached Lookups - Credential metadata is cached for fast resolution
- Per-Request Overrides - Support for test/development credential injection
- Validation Support - Optional endpoint-based credential validation
- API Key Management - Fast hash-based lookup for API key authentication
Installation
npm install @memberjunction/credentialsQuick Start
1. Initialize the Engine
import { CredentialEngine } from '@memberjunction/credentials';
// Initialize at application startup
await CredentialEngine.Instance.Config(false, contextUser);2. Retrieve a Credential
import { CredentialEngine, APIKeyCredentialValues } from '@memberjunction/credentials';
// Get a credential with typed values
const cred = await CredentialEngine.Instance.getCredential<APIKeyCredentialValues>(
'OpenAI',
{
contextUser,
subsystem: 'AIService'
}
);
// Use the decrypted values
openai.setApiKey(cred.values.apiKey);3. Store a New Credential
const credential = await CredentialEngine.Instance.storeCredential(
'API Key', // Credential type name
'OpenAI Production', // Credential name
{ apiKey: 'sk-...' }, // Values (will be encrypted)
{
isDefault: true,
description: 'Production OpenAI API key'
},
contextUser
);Credential Types
MemberJunction includes pre-configured credential types with JSON schemas:
| Type | Fields | Use Case |
|---|---|---|
| API Key | apiKey |
OpenAI, Anthropic, SendGrid, etc. |
| API Key with Endpoint | apiKey, endpoint |
Azure OpenAI, custom APIs |
| OAuth2 Client Credentials | clientId, clientSecret, tokenUrl, scope |
OAuth integrations |
| Basic Auth | username, password |
Legacy systems |
| Azure Service Principal | tenantId, clientId, clientSecret |
Microsoft Graph, Azure services |
| AWS IAM | accessKeyId, secretAccessKey, region |
S3, SES, Lambda, etc. |
| Database Connection | host, port, database, username, password |
External databases |
| Twilio | accountSid, authToken |
SMS/Voice services |
Type-Safe Value Interfaces
Use the provided interfaces for compile-time type safety:
import {
CredentialEngine,
APIKeyCredentialValues,
AWSIAMCredentialValues,
AzureServicePrincipalCredentialValues
} from '@memberjunction/credentials';
// OpenAI/Anthropic/etc.
const ai = await CredentialEngine.Instance.getCredential<APIKeyCredentialValues>(
'OpenAI',
{ contextUser }
);
console.log(ai.values.apiKey); // Typed as string
// AWS Services
const aws = await CredentialEngine.Instance.getCredential<AWSIAMCredentialValues>(
'AWS Production',
{ contextUser }
);
console.log(aws.values.accessKeyId, aws.values.secretAccessKey, aws.values.region);
// Azure Services
const azure = await CredentialEngine.Instance.getCredential<AzureServicePrincipalCredentialValues>(
'Microsoft Graph',
{ contextUser }
);
console.log(azure.values.tenantId, azure.values.clientId);Resolution Priority
When you call getCredential(), credentials are resolved in this order:
- Direct Values - If
directValuesis provided in options, use those (useful for testing) - By ID - If
credentialIdis provided, look up that specific credential - By Name - Look up by the credential name passed to
getCredential()
// Priority 1: Direct values (bypasses database)
const cred = await engine.getCredential('OpenAI', {
directValues: { apiKey: 'test-key' },
contextUser
});
// Priority 2: Specific credential by ID
const cred = await engine.getCredential('OpenAI', {
credentialId: 'specific-credential-uuid',
contextUser
});
// Priority 3: By name (most common)
const cred = await engine.getCredential('OpenAI', { contextUser });API Key Lookup
The CredentialEngine caches API keys for fast hash-based lookup, used by authentication systems:
// Look up API key by hash (O(1) from cache)
const apiKey = CredentialEngine.Instance.getAPIKeyByHash(keyHash);
if (apiKey && apiKey.Status === 'Active') {
// Key is valid
console.log('User ID:', apiKey.UserID);
}This is used internally by EncryptionEngine.ValidateAPIKey() for fast API authentication.
Audit Logging
Every credential access is automatically logged to the Audit Logs entity:
const cred = await engine.getCredential('OpenAI', {
contextUser,
subsystem: 'AIService' // Logged for tracking
});Audit log entry includes:
- User who accessed the credential
- Operation type (Decrypt, Create, Update, Validate)
- Subsystem that requested access
- Success/failure status
- Duration in milliseconds
Credential Validation
Validate credentials against provider endpoints:
const result = await engine.validateCredential(credentialId, contextUser);
if (!result.isValid) {
console.error('Credential validation failed:', result.errors);
}
// Result structure
interface CredentialValidationResult {
isValid: boolean;
errors: string[];
warnings: string[];
validatedAt: Date;
}Updating Credentials
Update credential values (automatically re-encrypted):
await engine.updateCredential(
credentialId,
{ apiKey: 'new-sk-...' }, // New values
contextUser
);Cached Data Access
Access cached credential metadata without database calls:
// All credentials
const credentials = engine.Credentials;
// All credential types
const types = engine.CredentialTypes;
// All credential categories
const categories = engine.CredentialCategories;
// Lookup helpers
const type = engine.getCredentialTypeByName('API Key');
const defaultCred = engine.getDefaultCredentialForType('API Key');
const credById = engine.getCredentialById('uuid-here');
const credByName = engine.getCredentialByName('API Key', 'OpenAI');Database Schema
MJ: Credential Types
Defines the shape of credential values:
| Column | Description |
|---|---|
Name |
Type name (e.g., 'API Key') |
Description |
Human-readable description |
FieldSchema |
JSON Schema for validation |
ValidationEndpoint |
Optional URL for validation |
MJ: Credentials
Stores credential instances:
| Column | Description |
|---|---|
Name |
Credential name (e.g., 'OpenAI Production') |
CredentialTypeID |
Foreign key to type |
Values |
Encrypted JSON blob |
IsDefault |
Default for this type |
IsActive |
Active status |
ExpiresAt |
Optional expiration |
LastUsedAt |
Updated on each access |
LastValidatedAt |
Updated on validation |
MJ: Credential Categories
Optional organization:
| Column | Description |
|---|---|
Name |
Category name |
Description |
Description |
ParentCategoryID |
For hierarchy |
Security Considerations
Encryption at Rest
- The
Valuesfield uses MJ field-level encryption - Only decrypted when explicitly accessed via
getCredential()
- The
Audit Trail
- Every access is logged with user, timestamp, and subsystem
- Failed access attempts are also logged
Access Control
- Credentials inherit MJ's entity-level permissions
- Use
contextUserto enforce authorization
Expiration
- Set
ExpiresAton credentials to enforce rotation - Check
expiresAtin the resolved credential for warnings
- Set
Per-Request Override
- Use
directValuesfor testing without database access - Values are marked with
source: 'request'for audit clarity
- Use
Integration with EncryptionEngine
The Credentials package works alongside the Encryption package:
- CredentialEngine - Manages credential storage and retrieval
- EncryptionEngine - Handles API key generation, validation, and field encryption
API key authentication flow:
EncryptionEngine.ValidateAPIKey()hashes the incoming keyCredentialEngine.getAPIKeyByHash()looks up the cached key entity- Validation checks status, expiration, and user account
- User context is returned for authorized operations
License
ISC