Update an Identity in Hyperledger Fabric using Node SDK

0
128

Hyperledger Fabric uses Certificate Authority and Cryptogen tool to generate the crypto material for any identity in the network. Cryptogen tool is used only for development purpose but actually using a Certificate Authority is the preferred choice. If any user wants to do transaction in the network, the user needs to have a certificate which will be generated by admin registered for that organization. So first we need to enroll admin in the organization and then register, enroll user with admin context. This can be done using CertificateAuthority class in Fabric Node SDK.

Lets take the fabcar example in the fabric samples, when you do ./startFabric.sh, the fabric network will be up and running with chaincode installed and instantiated in the peers. If you need to make a transaction from the client using node SDK you run enrollAdmin.js to enroll admin which generates key pair and certificate for the admin in the wallet folder you provided, and registerUser.js to register, enroll user which generates the same for user. We use the user certificates to call chaincode methods and submit transactions. We can pass custom attributes to the user certificates which can be used to perform access level control in chaincode which we call it as Attribute Based Access Control(ABAC). Suppose if you want to change the certificate attributes, one way is we can re-renroll the user many times based on MaxEnrollment parameter you have given. This generates new certificate each time you enroll the user. The other way is updating the certificate attributes using the IdentityService from Node SDK. Lets take a look at it.

Lets try to register user “testinguser” with custom attributes. We create a custom attribute called “role” and assign value “patient” to it.

 attrs: [{ name: “role”, value: “patient”, ecert: true }]

is the way you add custom attribute.

Below is the code for registerUser.js, the custom attributes are added while registering the user

'use strict';
const { FileSystemWallet, Gateway, X509WalletMixin } = require('fabric-network');
const path = require('path');
const ccpPath = path.resolve(__dirname, '..', '..', 'first-network', 'connection-org1.json');
async function main() {
try {
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.exists('testinguser');
if (userExists) {
console.log('An identity for the user "testinguser" already exists in the wallet');
return;
}
// Check to see if we've already enrolled the admin user.
const adminExists = await wallet.exists('admin');
if (!adminExists) {
console.log('An identity for the admin user "admin" does not exist in the wallet');
console.log('Run the enrollAdmin.js application before retrying');
return;
}
// Create a new gateway for connecting to our peer node.
const gateway = new Gateway();
await gateway.connect(ccpPath, { wallet, identity: 'admin', discovery: { enabled: true, asLocalhost: true } });
// Get the CA client object from the gateway for interacting with the CA.
const ca = gateway.getClient().getCertificateAuthority();
const adminIdentity = gateway.getCurrentIdentity();
// Register the user, enroll the user, and import the new identity into the wallet.
const secret = await ca.register({ affiliation: 'org1.department1', enrollmentID: 'testinguser', role: 'client', attrs: [{ name: "role", value: "patient", ecert: true }] }, adminIdentity);
const enrollment = await ca.enroll({ enrollmentID: 'testinguser', enrollmentSecret: secret });
const userIdentity = X509WalletMixin.createIdentity('Org1MSP', enrollment.certificate, enrollment.key.toBytes());
await wallet.import('testinguser', userIdentity);
console.log('Successfully registered and enrolled admin user "testinguser" and imported it into the wallet');
// retrieve the registered identity
const identityService = ca.newIdentityService();
const retrieveIdentity = await identityService.getOne("testinguser",adminIdentity)
console.log("user attributes: ",retrieveIdentity.result.attrs)
} catch (error) {
console.error(`Failed to register user "testinguser": ${error}`);
process.exit(1);
}
}
main();

You can see the identity details logged in the console with custom attribute “role” of value “patient”.

Lets try to change the attribute “role” from patient to doctor,

Doing it in CLI way,

fabric-ca-client identity modify testinguser --json '{"secret": "newPassword", "affiliation": ".", "attrs": [{"name": "role", "value": "patient"}]}'

If you want to change the attribute using Node SDK, there is IdentityService class which can be used to create/update/delete/retrieve an identity.

Lets see the code below,

'use strict';
const { FileSystemWallet, Gateway, X509WalletMixin, User } = require('fabric-network');
const path = require('path');
const ccpPath = path.resolve(__dirname, '..', '..', 'first-network', 'connection-org1.json');
async function main() {
try {
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'wallet');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.exists('testinguser');
if (!userExists) {
console.log('An identity for the user "testinguser" does not exist in the wallet');
console.log('Run the registerUser.js application before retrying');
return;
}
const gateway = new Gateway();
await gateway.connect(ccpPath, { wallet, identity: 'admin', discovery: { enabled: true, asLocalhost: true } });
const ca = gateway.getClient().getCertificateAuthority();
const adminIdentity = gateway.getCurrentIdentity();
const identityService = ca.newIdentityService();
let updateObj = {
type:"client",
affiliation:"org1.department1" ,
attrs: [{ name: "role", value: "doctor", ecert: true }] ,
caname:"ca_peerOrg1"
}
// update identity
const response = await identityService.update("testinguser",updateObj,adminIdentity)
console.log("userIdenity attributes: ",response.result.attrs)
} catch (error) {
console.error(`Failed to update "testinguser" attributes: ${error}`);
process.exit(1);
}
}
main();

When you run the code , you can see the details of the modified “role” attribute with value doctor. Great!

In this way, you can update the identity details in Hyperledger Fabric without re-enrolling.

Happy Learning!!!


Update an Identity in Hyperledger Fabric using Node SDK was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.