Distributed p2p database on IPFS with automatic peer synchronization and conflict-free writes
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
OrbitDB's identity system provides cryptographic identity management for database operations and peer authentication. It enables secure, verifiable operations across the distributed network.
The Identities class manages identity creation, verification, and keystore integration.
/**
* Creates an Identities instance
* @param params Configuration parameters
* @param params.ipfs IPFS instance for storage
* @param params.keystore Optional keystore instance
* @returns Promise resolving to Identities instance
*/
function Identities(params: {
ipfs: IPFS;
keystore?: KeyStore;
}): Promise<Identities>;
interface Identities {
/** Creates a new identity */
createIdentity(options?: IdentityOptions): Promise<Identity>;
/** Verifies an identity's authenticity */
verifyIdentity(identity: Identity): Promise<boolean>;
/** The keystore used by this identities instance */
keystore: KeyStore;
}
interface IdentityOptions {
/** Identity provider to use */
provider?: IdentityProvider;
/** Identity ID (auto-generated if not provided) */
id?: string;
/** Additional provider-specific options */
[key: string]: any;
}Usage Examples:
import { createHelia } from 'helia';
import { Identities, PublicKeyIdentityProvider } from '@orbitdb/core';
const ipfs = await createHelia();
// Create identities instance
const identities = await Identities({ ipfs });
// Create default identity
const identity1 = await identities.createIdentity();
// Create identity with custom provider
const identity2 = await identities.createIdentity({
provider: PublicKeyIdentityProvider()
});
// Create identity with specific ID
const identity3 = await identities.createIdentity({
id: 'my-custom-id'
});
console.log('Identity 1:', identity1.id);
console.log('Identity 2:', identity2.id);
console.log('Identity 3:', identity3.id);Individual identities contain cryptographic information and metadata.
interface Identity {
/** Unique identifier for this identity */
id: string;
/** Public key for verification */
publicKey: string;
/** Cryptographic signatures proving identity */
signatures: {
id: string;
publicKey: string;
};
/** Identity type (e.g., 'publickey') */
type: string;
/** The identity provider that created this identity */
provider: IdentityProvider;
}
/**
* Checks if an object is a valid Identity
* @param identity Object to test
* @returns True if object is a valid Identity
*/
function isIdentity(identity: any): identity is Identity;
/**
* Checks if two identities are equal
* @param identity1 First identity
* @param identity2 Second identity
* @returns True if identities are equal
*/
function isEqual(identity1: Identity, identity2: Identity): boolean;Usage Examples:
import { isIdentity, isEqual } from '@orbitdb/core';
const ipfs = await createHelia();
const identities = await Identities({ ipfs });
// Create identities
const identity1 = await identities.createIdentity();
const identity2 = await identities.createIdentity();
// Check if objects are identities
console.log(isIdentity(identity1)); // true
console.log(isIdentity({ id: 'fake' })); // false
// Compare identities
console.log(isEqual(identity1, identity1)); // true
console.log(isEqual(identity1, identity2)); // false
// Access identity properties
console.log('ID:', identity1.id);
console.log('Public Key:', identity1.publicKey);
console.log('Type:', identity1.type);
console.log('Signatures:', identity1.signatures);Verify the authenticity and integrity of identities.
import { Identities } from '@orbitdb/core';
const ipfs = await createHelia();
const identities = await Identities({ ipfs });
// Create and verify identity
const identity = await identities.createIdentity();
const isValid = await identities.verifyIdentity(identity);
console.log('Identity is valid:', isValid);
// Verify identity from another source
const receivedIdentity = JSON.parse(someIdentityJson);
const isReceivedValid = await identities.verifyIdentity(receivedIdentity);
console.log('Received identity is valid:', isReceivedValid);The default identity provider using public key cryptography.
/**
* Creates a PublicKeyIdentityProvider instance
* @param options Provider configuration options
* @returns PublicKeyIdentityProvider instance
*/
function PublicKeyIdentityProvider(options?: any): PublicKeyIdentityProvider;
interface PublicKeyIdentityProvider extends IdentityProvider {
/** Provider type identifier */
type: 'publickey';
/** Gets the ID from an identity */
getId(identity: Identity): string;
/** Signs identity data with keystore */
signIdentity(data: any, keystore: KeyStore): Promise<string>;
/** Verifies an identity's signatures */
verifyIdentity(identity: Identity): Promise<boolean>;
}Usage Examples:
import {
Identities,
PublicKeyIdentityProvider,
createOrbitDB
} from '@orbitdb/core';
const ipfs = await createHelia();
// Create identities with public key provider
const identities = await Identities({ ipfs });
const identity = await identities.createIdentity({
provider: PublicKeyIdentityProvider()
});
// Use identity with OrbitDB
const orbitdb = await createOrbitDB({
ipfs,
identity,
identities
});
console.log('OrbitDB identity:', orbitdb.identity.id);Create custom identity providers for different authentication schemes.
/**
* Registers a custom identity provider
* @param provider Identity provider implementation
*/
function useIdentityProvider(provider: IdentityProvider): void;
/**
* Gets a registered identity provider by type
* @param type The provider type identifier
* @returns The identity provider instance
* @throws Error if provider type is not supported
*/
function getIdentityProvider(type: string): IdentityProvider;
interface IdentityProvider {
/** Unique type identifier */
type: string;
/** Gets the ID from an identity */
getId(identity: Identity): string;
/** Signs identity data */
signIdentity(data: any, keystore: KeyStore): Promise<string>;
/** Verifies an identity */
verifyIdentity(identity: Identity): Promise<boolean>;
/** Optional: creates identity data */
createIdentity?(options: any): Promise<any>;
}Usage Examples:
import { useIdentityProvider } from '@orbitdb/core';
// Custom OAuth-based identity provider
const OAuthIdentityProvider = {
type: 'oauth',
getId(identity) {
return identity.oauthId;
},
async signIdentity(data, keystore) {
// Sign with OAuth provider's key
const key = await keystore.getKey('oauth-signing-key');
return keystore.sign(key, data);
},
async verifyIdentity(identity) {
// Verify OAuth token with provider
try {
const response = await fetch(`https://oauth-provider.com/verify`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${identity.oauthToken}` }
});
return response.ok;
} catch (error) {
return false;
}
},
async createIdentity(options) {
// Create identity from OAuth token
return {
oauthId: options.userId,
oauthToken: options.token,
publicKey: options.publicKey
};
}
};
// Register the custom provider
useIdentityProvider(OAuthIdentityProvider);
// Use custom provider
const identities = await Identities({ ipfs });
const oauthIdentity = await identities.createIdentity({
provider: OAuthIdentityProvider,
userId: 'user123',
token: 'oauth-token',
publicKey: 'public-key-data'
});Example of a JWT-based identity provider.
const JWTIdentityProvider = {
type: 'jwt',
getId(identity) {
return identity.sub; // JWT subject
},
async signIdentity(data, keystore) {
// Sign data with JWT private key
const key = await keystore.getKey('jwt-key');
return keystore.sign(key, JSON.stringify(data));
},
async verifyIdentity(identity) {
try {
// Verify JWT signature and expiration
const jwt = identity.token;
const decoded = this.decodeJWT(jwt);
// Check expiration
if (decoded.exp && decoded.exp < Date.now() / 1000) {
return false;
}
// Verify signature (simplified)
return this.verifyJWTSignature(jwt, identity.publicKey);
} catch (error) {
return false;
}
},
decodeJWT(token) {
const parts = token.split('.');
return JSON.parse(atob(parts[1]));
},
verifyJWTSignature(token, publicKey) {
// JWT signature verification logic
// Implementation depends on JWT library
return true; // Simplified
}
};
useIdentityProvider(JWTIdentityProvider);Identities can be stored and reused across sessions.
import { Identities } from '@orbitdb/core';
const ipfs = await createHelia();
const identities = await Identities({ ipfs });
// Create identity
const identity = await identities.createIdentity();
// Store identity (serialize)
const identityData = JSON.stringify({
id: identity.id,
publicKey: identity.publicKey,
signatures: identity.signatures,
type: identity.type
});
localStorage.setItem('orbitdb-identity', identityData);
// Later: restore identity
const storedData = localStorage.getItem('orbitdb-identity');
const restoredIdentity = JSON.parse(storedData);
// Verify restored identity
const isValid = await identities.verifyIdentity(restoredIdentity);
if (isValid) {
const orbitdb = await createOrbitDB({
ipfs,
identity: restoredIdentity,
identities
});
}Identities are automatically integrated with OrbitDB operations.
import { createHelia } from 'helia';
import { createOrbitDB, Identities } from '@orbitdb/core';
const ipfs = await createHelia();
// Create custom identity
const identities = await Identities({ ipfs });
const identity = await identities.createIdentity({ id: 'my-app-user' });
// Create OrbitDB with custom identity
const orbitdb = await createOrbitDB({
ipfs,
identity,
identities
});
// All database operations will use this identity
const db = await orbitdb.open('my-db');
await db.add('Hello from my custom identity');
// Check which identity created entries
const entries = db.log.entries;
entries.forEach(entry => {
console.log('Entry created by:', entry.identity);
console.log('Matches our identity:', entry.identity === identity.id);
});Manage multiple identities for different purposes.
const ipfs = await createHelia();
const identities = await Identities({ ipfs });
// Create different identities for different roles
const adminIdentity = await identities.createIdentity({ id: 'admin' });
const userIdentity = await identities.createIdentity({ id: 'user' });
const guestIdentity = await identities.createIdentity({ id: 'guest' });
// Use different identities for different databases
const adminDB = await createOrbitDB({
ipfs,
identity: adminIdentity,
identities
});
const userDB = await createOrbitDB({
ipfs,
identity: userIdentity,
identities
});
// Admin database with strict access control
const adminData = await adminDB.open('admin-data', {
AccessController: IPFSAccessController({
write: [adminIdentity.id]
})
});
// User database with broader access
const userData = await userDB.open('user-data', {
AccessController: IPFSAccessController({
write: [adminIdentity.id, userIdentity.id]
})
});Handle identity-related errors appropriately.
import { Identities, isIdentity } from '@orbitdb/core';
try {
const ipfs = await createHelia();
const identities = await Identities({ ipfs });
// Create identity
const identity = await identities.createIdentity();
// Verify identity
const isValid = await identities.verifyIdentity(identity);
if (!isValid) {
throw new Error('Identity verification failed');
}
// Use with OrbitDB
const orbitdb = await createOrbitDB({ ipfs, identity, identities });
} catch (error) {
if (error.message.includes('Identity')) {
console.error('Identity error:', error.message);
} else if (error.message.includes('KeyStore')) {
console.error('KeyStore error:', error.message);
} else {
console.error('Unexpected error:', error.message);
}
}
// Validate identity objects
function validateIdentity(identity) {
if (!isIdentity(identity)) {
throw new Error('Invalid identity object');
}
if (!identity.id || !identity.publicKey) {
throw new Error('Identity missing required fields');
}
return true;
}The identity system provides the cryptographic foundation for secure, verifiable operations in OrbitDB's distributed environment.
Install with Tessl CLI
npx tessl i tessl/npm-orbitdb--core