anon-identity
Version:
Decentralized identity framework with DIDs, Verifiable Credentials, and privacy-preserving selective disclosure
119 lines • 4.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DelegationManager = void 0;
const crypto_1 = require("../core/crypto");
class DelegationManager {
async createDelegationCredential(issuerDID, issuerKeyPair, agentDID, agentName, grant, metadata) {
const now = new Date();
const credentialId = `${issuerDID}/delegations/${Date.now()}`;
const credential = {
'@context': [
'https://www.w3.org/2018/credentials/v1',
'https://w3id.org/security/suites/ed25519-2020/v1'
],
type: ['VerifiableCredential', 'DelegationCredential'],
id: credentialId,
issuer: issuerDID,
issuanceDate: now.toISOString(),
expirationDate: grant.expiresAt.toISOString(),
credentialSubject: {
id: agentDID,
parentDID: issuerDID,
name: agentName,
scopes: grant.scopes,
services: {
[grant.serviceDID]: {
scopes: grant.scopes,
constraints: grant.constraints
}
},
validFrom: now.toISOString(),
validUntil: grant.expiresAt.toISOString(),
delegationDepth: metadata?.delegationDepth,
maxDelegationDepth: metadata?.maxDelegationDepth,
canDelegate: metadata?.canDelegate
}
};
// Sign the credential
const proof = await this.createProof(credential, issuerDID, issuerKeyPair);
credential.proof = proof;
return credential;
}
async createProof(credential, issuerDID, keyPair) {
// Remove proof from credential for signing
const { proof, ...credentialWithoutProof } = credential;
// Create canonical string representation
const canonicalCredential = JSON.stringify(credentialWithoutProof, Object.keys(credentialWithoutProof).sort());
// Sign the credential
const signature = (0, crypto_1.signData)(canonicalCredential, keyPair.privateKey);
return {
type: 'Ed25519Signature2020',
created: new Date().toISOString(),
verificationMethod: `${issuerDID}#key-1`,
proofPurpose: 'assertionMethod',
jws: signature
};
}
validateDelegation(credential) {
// Check expiration
if (new Date(credential.expirationDate) < new Date()) {
return false;
}
// Check validity period
const validFrom = new Date(credential.credentialSubject.validFrom);
const validUntil = new Date(credential.credentialSubject.validUntil);
const now = new Date();
if (now < validFrom || now > validUntil) {
return false;
}
// Additional validation would include signature verification
// This would be done by the service provider
return true;
}
extractScopes(credential, serviceDID) {
const serviceGrant = credential.credentialSubject.services[serviceDID];
return serviceGrant?.scopes || [];
}
hasScope(credential, serviceDID, scope) {
const scopes = this.extractScopes(credential, serviceDID);
return scopes.includes(scope);
}
canAgentDelegate(credential) {
// Check if the credential allows delegation
if (!credential.credentialSubject.canDelegate) {
return false;
}
// Check delegation depth
const currentDepth = credential.credentialSubject.delegationDepth ?? 0;
const maxDepth = credential.credentialSubject.maxDelegationDepth ?? 3;
return currentDepth < maxDepth;
}
validateAgentDelegation(parentCredential, childScopes, serviceDID) {
// First check if parent can delegate
if (!this.canAgentDelegate(parentCredential)) {
return {
valid: false,
reason: 'Parent agent cannot delegate further'
};
}
// Check if parent credential is still valid
if (!this.validateDelegation(parentCredential)) {
return {
valid: false,
reason: 'Parent delegation credential is invalid or expired'
};
}
// Check if all child scopes are within parent's scope
const parentScopes = this.extractScopes(parentCredential, serviceDID);
const hasAllScopes = childScopes.every(scope => parentScopes.includes(scope));
if (!hasAllScopes) {
return {
valid: false,
reason: 'Child scopes exceed parent agent\'s permissions'
};
}
return { valid: true };
}
}
exports.DelegationManager = DelegationManager;
//# sourceMappingURL=delegation-manager.js.map