1"use strict";(self.webpackChunk=self.webpackChunk||[]).push([[4434],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var a=n(7294);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){i(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function o(e,t){if(null==e)return{};var n,a,i=function(e,t){if(null==e)return{};var n,a,i={},r=Object.keys(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||(i[n]=e[n]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}var l=a.createContext({}),d=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},c=function(e){var t=d(e.components);return a.createElement(l.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},h=a.forwardRef((function(e,t){var n=e.components,i=e.mdxType,r=e.originalType,l=e.parentName,c=o(e,["components","mdxType","originalType","parentName"]),p=d(n),h=i,m=p["".concat(l,".").concat(h)]||p[h]||u[h]||r;return n?a.createElement(m,s(s({ref:t},c),{},{components:n})):a.createElement(m,s({ref:t},c))}));function m(e,t){var n=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=n.length,s=new Array(r);s[0]=h;var o={};for(var l in t)hasOwnProperty.call(t,l)&&(o[l]=t[l]);o.originalType=e,o[p]="string"==typeof e?e:i,s[1]=o;for(var d=2;d<r;d++)s[d]=n[d];return a.createElement.apply(null,s)}return a.createElement.apply(null,n)}h.displayName="MDXCreateElement"},9416:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>m,frontMatter:()=>o,metadata:()=>d,toc:()=>p});var a=n(7462),i=n(3366),r=(n(7294),n(3905)),s=["components"],o={title:"Decentralized Identity"},l=void 0,d={unversionedId:"sdk/general/connectivity/guides/did",id:"sdk/general/connectivity/guides/did",title:"Decentralized Identity",description:"Verifiable Credentials",source:"@site/../docs/7.sdk/general/connectivity/guides/did.md",sourceDirName:"7.sdk/general/connectivity/guides",slug:"/sdk/general/connectivity/guides/did",permalink:"/sdk/general/connectivity/guides/did",draft:!1,editUrl:"https://github.com/elastos/Elastos.Wiki/edit/master/website/../docs/7.sdk/general/connectivity/guides/did.md",tags:[],version:"current",lastUpdatedBy:"racollette",lastUpdatedAt:1677302017,formattedLastUpdatedAt:"Feb 25, 2023",frontMatter:{title:"Decentralized Identity"},sidebar:"sdkSidebar",previous:{title:"Setup",permalink:"/sdk/general/connectivity/guides/setup"},next:{title:"User Experience",permalink:"/sdk/general/connectivity/guides/ux"}},c={},p=[{value:"Verifiable Credentials",id:"verifiable-credentials",level:2},{value:"Instantiate the DID Access Helper",id:"instantiate-the-did-access-helper",level:3},{value:"Get User's DID data / credentials",id:"get-users-did-data--credentials",level:3},{value:"Import Credentials to a User's DID",id:"import-credentials-to-a-users-did",level:3},{value:"Issue a Credential for Another DID",id:"issue-a-credential-for-another-did",level:3},{value:"Delete Credentials from User's DID",id:"delete-credentials-from-users-did",level:3},{value:"Request to Publish User's DID",id:"request-to-publish-users-did",level:3},{value:"Sign Any Data with User's DID",id:"sign-any-data-with-users-did",level:3},{value:"Elastos IO Adapter",id:"elastos-io-adapter",level:2}],u={toc:p},h="wrapper";function m(e){var t=e.components,o=(0,i.Z)(e,s);return(0,r.kt)(h,(0,a.Z)({},u,o,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"verifiable-credentials"},"Verifiable Credentials"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"Verifiable Credentials")," are blocks of data related to a specific DID. They usually store users' names, emails, phone numbers, and other important types of application-specific information. Applications can generate these credentials, ask users to import them to their DID profile (privately or publicly), and verify them (make sure who issued a credential)."),(0,r.kt)("h3",{id:"instantiate-the-did-access-helper"},"Instantiate the DID Access Helper"),(0,r.kt)("p",null,"The DID Access Helper makes it easy to execute remote operations in the wallet in just a few lines of code. All of the below examples use an instance of this helper tool that are created as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'// Connectivity SDK classes\nimport {\n connectivity,\n DID as ConnDID,\n} from "@elastosfoundation/elastos-connectivity-sdk-js";\n\n// DID SDK classes, used to manipulate inputs/outputs to the connectivity SDK\nimport {\n DID,\n DIDBackend,\
1n DIDStore,\n Issuer,\n Mnemonic,\n RootIdentity,\n VerifiableCredential,\n} from "@elastosfoundation/did-js-sdk";\n\nlet didAccess = new ConnDID.DIDAccess();\n')),(0,r.kt)("h3",{id:"get-users-did-data--credentials"},"Get User's DID data / credentials"),(0,r.kt)("p",null,'In order for a third party application to get a user\'s "DID string" (DID identifier) or email, it can request the identity wallet to "get some credentials". Here\'s how it works:'),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'// Request credentials from the wallet\nlet presentation = await didAccess.getCredentials({\n claims: {\n name: true, // Mandatory\n avatar: {\n required: false, // Optional\n reason: "Show who you are to others"\n }\n }\n);\n\n// The returned information is a Verifiable Presentation that contains\n// one or more credentials. The DID SDK can then be used to manipulate\n// those credentials.\nlet nameCredential = presentation.getCredentials().find((c) => {\n // Find the "name" credential\n return c.getId().getFragment() === "name";\n});\nconsole.log("Thank you for joining " + nameCredential.getSubject().getProperty("name"));\n}\n')),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"If you want to get a user's DID string (did:elastos:abc) only, pass an empty list of claims.")),(0,r.kt)("p",null,"Here's an example of a user prompt generated inside the Elastos Essentials identity wallet (using the ",(0,r.kt)("strong",{parentName:"p"},"Elastos Essentials Connector"),"), after a call to didAccess.getCredentials(). On the client-side, the call to didAccess.getCredentials() receives a response only after the user accepts or rejects this request:"),(0,r.kt)("p",null,(0,r.kt)("img",{alt:"image",src:n(8654).Z,width:"722",height:"1474"})),(0,r.kt)("h3",{id:"import-credentials-to-a-users-did"},"Import Credentials to a User's DID"),(0,r.kt)("p",null,'The main idea behind DIDs is for various actors to generate credentials to and read credentials from users. As seen above, receiving credentials from users can be considered as a "read" operation. The below code now describes how to "write" data.'),(0,r.kt)("p",null,"In a decentralized world, applications never write DID data (credentials) directly somewhere. Instead, they ",(0,r.kt)("strong",{parentName:"p"},"generate credentials")," and ",(0,r.kt)("strong",{parentName:"p"},"ask users to import credentials to their identity profile"),". Users can choose to make such credentials visible from all (by publishing them on the blockchain) or to keep them private (stored only on their device)."),(0,r.kt)("p",null,"The first step before asking a user to import a credential is to create the credential itself. More details on creating credentials are provided in the ",(0,r.kt)("a",{parentName:"p",href:"/sdk/did/js/introduction/"},"DID SDK documentation"),". For our Connectivity SDK guide, we utilize the simplest possible way to do so."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'// For this guide, always re-create a new identity for the signer of the created credential.\n// In real life, the signer should remain the same.\nDIDBackend.initialize(\n new ConnDID.ElastosIODIDAdapter(ConnDID.ElastosIODIDAdapterMode.MAINNET)\n);\nlet didStore = await DIDStore.open("any-did-store-name");\nlet rootIdentity = RootIdentity.createFromMnemonic(\n Mnemonic.getInstance().generate(),\n "",\n didStore,\n "unsafepass",\n true\n);\n\n// The issuer is the entity who creates the credential. Usually, the current application.\nlet issuerDID = await rootIdentity.newDid("unsafepass", 0, true); // Index 0, overwrite\nlet issuer = new Issuer(issuerDID);\n\n// The target DID is the user. We want to issue a credential, for him.\n// Such DID string should first be obtained from\n// a call to didAccess.getCredentials()\nlet targetDID = DID.from("did:elastos:abcdef");\n\n// Create the credential and sign it with the app identity.\nlet vcb = new VerifiableCredential.Builder(issuer, targetDID);\nlet credential = await vcb\n .id("#diploma")\n .properties({\n year: "2009",\n speciality: "Marketing",\n })\n .type("DiplomaCredential")\n .seal("unsafepass");\n')),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"In production applications, creating the credential should happen on the server side as this requires access to the issuer's DID private key which cannot be deployed on the client side. Then, the generated credentials are usually transmitted to the application's client side (ex: a web browser) where the connectivity SDK can be called.")),(0,r.kt)("p",null,"We can now ask the Connectivity SDK to send this credential to the connected user, so they can add it to their identity profile:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"// Send the credential to the identity wallet (essentials)\nlet didAccess = new ConnDID.DIDAccess();\nlet options: ConnDID.ImportCredentialOptions = {\n // If true, the identity wallet may force user to publish\n // his recent changes on the blockchain. Useful in case the\n // application needs the credential to be usable publicly and\n // not only remain on user's device.\n forceToPublishCredentials: true,\n};\n\nlet importedCredentials = await didAccess.importCredentials(\n [credential],\n options\n);\n")),(0,r.kt)("h3",{id:"issue-a-credential-for-another-did"},"Issue a Credential for Another DID"),(0,r.kt)("p",null,"Third party applications can prepare credential information on their side and request the user to sign and return a credential from the identity application. For instance, for convenience, a medical web app can prepare data for a doctor to create a drug prescription credential, and the doctor only needs to check the content then sign this, from his i
1dentity app, without manually doing any other operation."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'let issuedCredential = await didAccess.issueCredential(\n "did:elastos:iqeXQuCuUuZ2mdHuPUhQpQGFs4HqHixm3G", // For who?\n ["PrescriptionCredential"], // Credential type, to match a standard format\n // Real content\n {\n drug1: {\n quantity: 1234,\n frequency: "Twice per day",\n },\n },\n "testissue" // Credential name\n);\n')),(0,r.kt)("h3",{id:"delete-credentials-from-users-did"},"Delete Credentials from User's DID"),(0,r.kt)("p",null,"When applications consider a credential currently in a user's profile as obsolete, they can request to delete it. As usual with decentralized identities, applications have no way to directly delete credentials by themselves - instead, they need to ask the identity wallet and user to do this."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'// Ask user to delete the email. He can confirm or reject\n// this request\nlet deletedCredentials = await didAccess.deleteCredentials([\n "#email30", // Credential ID\n]);\n')),(0,r.kt)("h3",{id:"request-to-publish-users-did"},"Request to Publish User's DID"),(0,r.kt)("p",null,"Applications can request for the identity wallet to publish the user's latest public DID profile (their \"DID Document\") at the current moment. Normally, this doesn't need to be done manually by applications, but here is how to trigger this request:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},"// If user agrees with this request, the transaction ID for the on\n// going publication is returned and can be check on the identity\n// chain explorer.\nlet txId = await didAccess.requestPublish();\n")),(0,r.kt)("h3",{id:"sign-any-data-with-users-did"},"Sign Any Data with User's DID"),(0,r.kt)("p",null,"Any arbitrary string can be signed by a user's DID. The returned value contains the signing DID string, its public key, the generated signature, and a JWT token containing the whole response."),(0,r.kt)("p",null,"The JWT can be used to verify that the returned information is genuine."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'let signedData = await didAccess.signData(\n "data-to-sign",\n { extraField: 123 },\n "customSignatureField"\n);\n')),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},(0,r.kt)("strong",{parentName:"p"},"Advanced"),": if you plan to use the JWT token as-is, you can specify additional custom fields to add in that JWT, and the signature field name.")),(0,r.kt)("h2",{id:"elastos-io-adapter"},"Elastos IO Adapter"),(0,r.kt)("p",null,"For some operations, the DID SDK requires a ",(0,r.kt)("strong",{parentName:"p"},"DID adapter")," to be a provider. A DID adapter is basically a single method, that can query the Elastos Identity blockchain in order to retrieve DID Document, or Verifiable credentials."),(0,r.kt)("p",null,"For convenience, the connectivity SDK provides a simple DID adapter, that communicates with the ",(0,r.kt)("strong",{parentName:"p"},"elastos.io")," identity node (service provided by the gelaxy core blockchain team). Of course, dApp developers are free to implement their own custom DID adapters to talk to the identity blockchain node or their choice instead of using this one."),(0,r.kt)("p",null,"The adapter can be instantiated like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-ts"},'import { DID } from "@elastosfoundation/elastos-connectivity-sdk-js";\n\n// Mainnet\nlet adapter = DID.ElastosIODIDAdapter(DID.ElastosIODIDAdapterMode.MAINNET);\n\n// Testnet\nlet adapter = DID.ElastosIODIDAdapter(DID.ElastosIODIDAdapterMode.TESTNET);\n')))}m.isMDXComponent=!0},8654:(e,t,n)=>{n.d(t,{Z:()=>a});const a=n.p+"assets/images/profile-request-aa45598f59537eda7d70500957cdc284.png"}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.