Show code cell source
const plantuml = require('plantuml');
const tslab = require("tslab");
Show code cell source
import jwt_decode from "jwt-decode";
Howto offer VC to Holder#
We already know about classical triangle of roles. It is user centric
holder - user that own a VCs
issuer - party that issue a VC
verifier - could aks holder for a VCs to Verify
We need a protocol that could proof the identity and autorship for every role. As we know our identities is our keypairs so we should sign some entities to proof our identity Affinidi SDK offer transport agnostic protocols for excanges based on JWT tokens
Show code cell source
const plantumlEncoder = require('plantuml-encoder')
const tslab = require("tslab");
const diagram = plantumlEncoder.encode(`
@startuml
digraph F {
fontname="Helvetica,Arial,sans-serif"
node [fontname="Helvetica,Arial,sans-serif"]
edge [fontname="Helvetica,Arial,sans-serif"]
node [shape = circle];
holder [lablel="holder" shape = doublecircle]
issuer [lablel="issuer"]
verifier [lablel="verifier"]
verifier -> holder[label = "request for sharing"]
holder -> verifier[label = "request for sharing"]
issuer -> holder [label = "request for offer"];
holder -> issuer [label = "response for offer"];
issuer -> holder [label = "VC"];
}
@enduml
`);
const urldiagram = 'http://www.plantuml.com/plantuml/svg/' + diagram
tslab.display.html(`<img src="${urldiagram}"/>`)
With request/responce for offer holder and issuer could identify each other
Show code cell source
const ShareOfferDiagram = plantumlEncoder.encode(`
@startuml
title Affinidi: Affinidi: Offer VC Flow
actor "SDK (Holder)" as holder
actor "SDK (Issuer)" as client
participant "Affinidi Issuer" as issuer
participant "Affinidi Registry" as registry
client -> issuer: BuildCredentialOffer(offeredCredentials)
issuer -> client : Issuer Service: 200 [credentialOfferRequest]
note over client, issuer: credentialOfferRequest signing and credentialOfferRequestToken generated
issuer -> holder: 200[credentialOfferRequestToken]
note over holder, client
NOTE:
Verification of the Issuer signature on the credentialOfferRequestToken
1. Resolve Issuer DID (get publicKey)
2. Verify Issuer signature (using publicKey)
end note
holder -> registry: resolveDid(IssuerDid)
registry -> holder: 200 [DidDocument]
holder -> client: send back(CredentialOfferResponseToken)
note over client, holder
Verification of the Holder signature on the CredentialOfferResponseToken
1. Resolve Holder DID (get publicKey)
2. Verify Holder signature (using publicKey)
end note
client -> registry: resolveDid(HolderDid)
registry -> client: 200[DidDocument]
client -> issuer: CreateSignedCredential(data, metadata, **requesterDid**)
issuer -> client: 200[signedCredentials]
client -> holder: 200 [Token wirth credentials inside]
@enduml
`);
const ShareOfferDiagramUrl = 'http://www.plantuml.com/plantuml/svg/' + ShareOfferDiagram
tslab.display.html(`<img src="${ShareOfferDiagramUrl}"/>`)
const { createWallet } = require('@affinidi/wallet-node-sdk')
const walletFactory = createWallet('AffinityCore')
Lets setup wallets
const accessApiKey = '<your key>'
const options = {
env: 'prod',
accessApiKey,
}
const issuerWallet = await walletFactory.createWallet(options, 'P@55word!!!')
const holderWallet = await walletFactory.createWallet(options, 'P@55word!!!')
Offer Request#
It is holder agnostic
it help toidentify issuer
it is share information about credentials that we want to issue What we want to offer
const offeredCredentials = [
{
type: 'ContentLike',
renderInfo:{},
}]
const callbackUrl = 'https://vp-service.com/callback'
const credentialOfferRequestToken = await issuerWallet.generateCredentialOfferRequestToken(
offeredCredentials,
{
callbackUrl,
},
)
credentialOfferRequestToken
eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpbnRlcmFjdGlvblRva2VuIjp7ImNhbGxiYWNrVVJMIjoiaHR0cHM6Ly92cC1zZXJ2aWNlLmNvbS9jYWxsYmFjayIsIm9mZmVyZWRDcmVkZW50aWFscyI6W3sidHlwZSI6IkNvbnRlbnRMaWtlIiwicmVuZGVySW5mbyI6e319XX0sImV4cCI6MTY2MjgzNzg5OTQ0NSwidHlwIjoiY3JlZGVudGlhbE9mZmVyUmVxdWVzdCIsImp0aSI6IjNmYTdhN2FkMTFiNWQ0YWMiLCJpc3MiOiJkaWQ6ZWxlbTpFaURVYldBUXNYOVk1S21aOVloYlJ1N0NyNGp5Y2k0WnVmdmVCM0FDUVlONzdBO2VsZW06aW5pdGlhbC1zdGF0ZT1leUp3Y205MFpXTjBaV1FpT2lKbGVVcDJZMGRXZVZsWVVuQmlNalJwVDJsS2FtTnRWbWhrUjFWcFRFTktjbUZYVVdsUGFVbHFZMGhLY0dKWFJubGxVMGx6U1cxR2MxcDVTVFpKYTFaVVRXcFZNbE41U2praUxDSndZWGxzYjJGa0lqb2laWGxLUVZreU9YVmtSMVkwWkVOSk5rbHRhREJrU0VKNlQyazRkbVI2VG5CYVF6VjJZMjFqZG1NeVZtcGtXRXB3WkVocmRtUnFTV2xNUTBwM1pGZEtjMkZYVGt4YVdHdHBUMngwTjBsdGJHdEphbTlwU1ROQ2VXRlhNV2hqYm10cFRFTktNV015Um01YVUwazJTVzVPY0ZveU5YQmliV05wVEVOS01HVllRbXhKYW05cFZUSldhbU5FU1RGT2JYTjRWbTFXZVdGWFduQlpNa1l3WVZjNWRWTXlWalZOYWtGNFQwTkpjMGx1UWpGWmJYaHdXVEIwYkdWVmFHeGxRMGsyU1dwQmVVMUVXWHBPVkdjeFRrZFpNbGxxWkd4UFZGRXlUakpGTlUxWFJURlplbEV6VDBkVk0wNVhSbXRhYlVWM1dsUm5kMXB0V21oTlZGbDZUa1JuZDFsWFdtbFBSRlUxVFhwak5FNXFiRzFPVkZWNlRWUlNhRTE1U2psTVNITnBZVmRSYVU5cFNXcGpiVlpxWWpOYWJHTnVhMmxNUTBveFl6SkdibHBUU1RaSmJrcHNXVEk1TWxwWVNqVkphWGRwWkVoc2QxcFRTVFpKYkU1c1dUTkJlVTVVV25KTlZscHNZMjFzYldGWFRtaGtSMngyWW10MGJHVlVTWGROVkdkcFRFTktkMlJYU25OaFYwNU1XbGhzU1ZwWVoybFBhVWwzVFcxRk5VOUhXWGRPYW1kNVdYcFZkMXBYV21oWmVtczFUbnByZUU1RVNtcE5lbEV4VFRKUk5FNHlSVE5hVkVadFdXMUZlVTlIVVRKUFYwa3hUbnBTYUU1WFZURk5NbFpzVFVSSk0xcEVVWGRhUjBacFRWUkJhV1pXTUhOSmJVWXhaRWRvYkdKdVVuQlpNa1l3WVZjNWRVbHFjR0pKYVU1M1kyMXNkRmxZU2pWSmJEQnpTVzFHZW1NeVZubGtSMngyWW1zeGJHUkhhSFphUTBrMlYzbEphbU5JU25CaVYwWjVaVk5LWkdaUklpd2ljMmxuYm1GMGRYSmxJam9pVmxCRWJrdElSVUp2T1RaRFUwNUJTRnBqTjJGcU5rNWhkbWQwTXpsTlF6QjBjRlowY20xWFprSTFXbU5LV1VsVWVHMVRUREZwUVMwMVFWOVdaVEZmVWpSWU5EUm9SbGg2VEdoWVEzQXdkRmN6ZEhvelJuY2lmUSIsImtpZCI6ImRpZDplbGVtOkVpRFViV0FRc1g5WTVLbVo5WWhiUnU3Q3I0anljaTRadWZ2ZUIzQUNRWU43N0EjcHJpbWFyeSJ9.4d3869db8f7c44c607cbedb9a66314ca68d38e7a894a73cbfe191b0413575c842c38986daef52f2906d01bfc584c8046dd2114cc86038987239a283a07058799
jwt_decode(credentialOfferRequestToken)
{
interactionToken: {
callbackURL: 'https://vp-service.com/callback',
offeredCredentials: [ [Object] ]
},
exp: 1662837899445,
typ: 'credentialOfferRequest',
jti: '3fa7a7ad11b5d4ac',
iss: 'did:elem:EiDUbWAQsX9Y5KmZ9YhbRu7Cr4jyci4ZufveB3ACQYN77A;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBeU1EWXpOVGcxTkdZMllqZGxPVFEyTjJFNU1XRTFZelEzT0dVM05XRmtabUV3WlRnd1ptWmhNVFl6TkRnd1lXWmlPRFU1TXpjNE5qbG1OVFV6TVRSaE15SjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TW1FNU9HWXdOamd5WXpVd1pXWmhZems1TnpreE5ESmpNelExTTJRNE4yRTNaVEZtWW1FeU9HUTJPV0kxTnpSaE5XVTFNMlZsTURJM1pEUXdaR0ZpTVRBaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiVlBEbktIRUJvOTZDU05BSFpjN2FqNk5hdmd0MzlNQzB0cFZ0cm1XZkI1WmNKWUlUeG1TTDFpQS01QV9WZTFfUjRYNDRoRlh6TGhYQ3AwdFczdHozRncifQ',
kid: 'did:elem:EiDUbWAQsX9Y5KmZ9YhbRu7Cr4jyci4ZufveB3ACQYN77A#primary'
}
Offer Response#
Lets holder to send response
const credentialOfferResponseToken = await holderWallet.createCredentialOfferResponseToken(
credentialOfferRequestToken,
)
credentialOfferResponseToken
eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpbnRlcmFjdGlvblRva2VuIjp7ImNhbGxiYWNrVVJMIjoiaHR0cHM6Ly92cC1zZXJ2aWNlLmNvbS9jYWxsYmFjayIsInNlbGVjdGVkQ3JlZGVudGlhbHMiOlt7InR5cGUiOiJDb250ZW50TGlrZSIsInJlbmRlckluZm8iOnt9fV19LCJleHAiOjE2NjI4MzkyMjk2NjcsInR5cCI6ImNyZWRlbnRpYWxPZmZlclJlc3BvbnNlIiwianRpIjoiM2ZhN2E3YWQxMWI1ZDRhYyIsImF1ZCI6ImRpZDplbGVtOkVpRFViV0FRc1g5WTVLbVo5WWhiUnU3Q3I0anljaTRadWZ2ZUIzQUNRWU43N0E7ZWxlbTppbml0aWFsLXN0YXRlPWV5SndjbTkwWldOMFpXUWlPaUpsZVVwMlkwZFdlVmxZVW5CaU1qUnBUMmxLYW1OdFZtaGtSMVZwVEVOS2NtRlhVV2xQYVVscVkwaEtjR0pYUm5sbFUwbHpTVzFHYzFwNVNUWkphMVpVVFdwVk1sTjVTamtpTENKd1lYbHNiMkZrSWpvaVpYbEtRVmt5T1hWa1IxWTBaRU5KTmtsdGFEQmtTRUo2VDJrNGRtUjZUbkJhUXpWMlkyMWpkbU15Vm1wa1dFcHdaRWhyZG1ScVNXbE1RMHAzWkZkS2MyRlhUa3hhV0d0cFQyeDBOMGx0Ykd0SmFtOXBTVE5DZVdGWE1XaGpibXRwVEVOS01XTXlSbTVhVTBrMlNXNU9jRm95TlhCaWJXTnBURU5LTUdWWVFteEphbTlwVlRKV2FtTkVTVEZPYlhONFZtMVdlV0ZYV25CWk1rWXdZVmM1ZFZNeVZqVk5ha0Y0VDBOSmMwbHVRakZaYlhod1dUQjBiR1ZWYUd4bFEwazJTV3BCZVUxRVdYcE9WR2N4VGtkWk1sbHFaR3hQVkZFeVRqSkZOVTFYUlRGWmVsRXpUMGRWTTA1WFJtdGFiVVYzV2xSbmQxcHRXbWhOVkZsNlRrUm5kMWxYV21sUFJGVTFUWHBqTkU1cWJHMU9WRlY2VFZSU2FFMTVTamxNU0hOcFlWZFJhVTlwU1dwamJWWnFZak5hYkdOdWEybE1RMG94WXpKR2JscFRTVFpKYmtwc1dUSTVNbHBZU2pWSmFYZHBaRWhzZDFwVFNUWkpiRTVzV1ROQmVVNVVXbkpOVmxwc1kyMXNiV0ZYVG1oa1IyeDJZbXQwYkdWVVNYZE5WR2RwVEVOS2QyUlhTbk5oVjA1TVdsaHNTVnBZWjJsUGFVbDNUVzFGTlU5SFdYZE9hbWQ1V1hwVmQxcFhXbWhaZW1zMVRucHJlRTVFU21wTmVsRXhUVEpSTkU0eVJUTmFWRVp0V1cxRmVVOUhVVEpQVjBreFRucFNhRTVYVlRGTk1sWnNUVVJKTTFwRVVYZGFSMFpwVFZSQmFXWldNSE5KYlVZeFpFZG9iR0p1VW5CWk1rWXdZVmM1ZFVscWNHSkphVTUzWTIxc2RGbFlTalZKYkRCelNXMUdlbU15Vm5sa1IyeDJZbXN4YkdSSGFIWmFRMGsyVjNsSmFtTklTbkJpVjBaNVpWTktaR1pSSWl3aWMybG5ibUYwZFhKbElqb2lWbEJFYmt0SVJVSnZPVFpEVTA1QlNGcGpOMkZxTms1aGRtZDBNemxOUXpCMGNGWjBjbTFYWmtJMVdtTktXVWxVZUcxVFRERnBRUzAxUVY5V1pURmZValJZTkRSb1JsaDZUR2hZUTNBd2RGY3pkSG96Um5jaWZRIiwiaXNzIjoiZGlkOmVsZW06RWlBdG1Oa3hPaFdPaFRDSXhPUnk2MkxwRnJOWlF0Vk03ZzZvRGF4bUREbHFtQTtlbGVtOmluaXRpYWwtc3RhdGU9ZXlKd2NtOTBaV04wWldRaU9pSmxlVXAyWTBkV2VWbFlVbkJpTWpScFQybEthbU50Vm1oa1IxVnBURU5LY21GWFVXbFBhVWxxWTBoS2NHSlhSbmxsVTBselNXMUdjMXA1U1RaSmExWlVUV3BWTWxONVNqa2lMQ0p3WVhsc2IyRmtJam9pWlhsS1FWa3lPWFZrUjFZMFpFTkpOa2x0YURCa1NFSjZUMms0ZG1SNlRuQmFRelYyWTIxamRtTXlWbXBrV0Vwd1pFaHJkbVJxU1dsTVEwcDNaRmRLYzJGWFRreGFXR3RwVDJ4ME4wbHRiR3RKYW05cFNUTkNlV0ZYTVdoamJtdHBURU5LTVdNeVJtNWFVMGsyU1c1T2NGb3lOWEJpYldOcFRFTktNR1ZZUW14SmFtOXBWVEpXYW1ORVNURk9iWE40Vm0xV2VXRlhXbkJaTWtZd1lWYzVkVk15VmpWTmFrRjRUME5KYzBsdVFqRlpiWGh3V1RCMGJHVlZhR3hsUTBrMlNXcEJlVTVYVlRGTlJFa3pUVzFGTTA5VVFUVlBWMVp0VFZSTk5GcFhSWHBQVkVGNFdXcEplRTVVU1RCT2FrRXdXbGROTVZwRVRYaFpha1pxV1ZkSk5GbHFiR2xhYW10NVdtcFdhazFFWTNoTlZFVjVXbFJSTkUxRFNqbE1TSE5wWVZkUmFVOXBTV3BqYlZacVlqTmFiR051YTJsTVEwb3hZekpHYmxwVFNUWkpia3BzV1RJNU1scFlTalZKYVhkcFpFaHNkMXBUU1RaSmJFNXNXVE5CZVU1VVduSk5WbHBzWTIxc2JXRlhUbWhrUjJ4MlltdDBiR1ZVU1hkTlZHZHBURU5LZDJSWFNuTmhWMDVNV2xoc1NWcFlaMmxQYVVsM1RYcEplRTVYVlhsWlYxWnRXVEpLYkUxcVFtcFpWMUV4V1dwU2JWbDZWbTFQUjFKc1QwUlJkMDFVU1RKT2JVbDNUMGRSZWxsWFdUQk9la3BzVFdwRk5VNUVSWGhaZWtwdFQxUkdhRmxxVlRGWmFtTXlUVmRWYVdaV01ITkpiVVl4WkVkb2JHSnVVbkJaTWtZd1lWYzVkVWxxY0dKSmFVNTNZMjFzZEZsWVNqVkpiREJ6U1cxR2VtTXlWbmxrUjJ4Mlltc3hiR1JIYUhaYVEwazJWM2xKYW1OSVNuQmlWMFo1WlZOS1pHWlJJaXdpYzJsbmJtRjBkWEpsSWpvaWNWbzNjVEY1V2tkZmVsTmtjbUpxWjJGWVpXb3dWVEZCZVZGdVQyTTBZamxYTFZKaE1VSlRSSE4wT1hoSVVFeDJNMXBzTjB3eExWWjNkVVJWWmkxWmJqUmhWSGRpVEY5T1NWTlZWa3BhT0hkVFVVWkVSR2NpZlEiLCJraWQiOiJkaWQ6ZWxlbTpFaUF0bU5reE9oV09oVENJeE9SeTYyTHBGck5aUXRWTTdnNm9EYXhtRERscW1BI3ByaW1hcnkifQ.d91b4a54959469c54afe091fb6316c12f148abb34d8645e2d96fa3e08e7d4b57530af9adadae5419ff99491dea4c3e47c5b418ac3cb5fae1947939d44b313350
jwt_decode(credentialOfferResponseToken)
{
interactionToken: {
callbackURL: 'https://vp-service.com/callback',
selectedCredentials: [ [Object] ]
},
exp: 1662837898338,
typ: 'credentialOfferResponse',
jti: '3fa7a7ad11b5d4ac',
aud: 'did:elem:EiDUbWAQsX9Y5KmZ9YhbRu7Cr4jyci4ZufveB3ACQYN77A;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBeU1EWXpOVGcxTkdZMllqZGxPVFEyTjJFNU1XRTFZelEzT0dVM05XRmtabUV3WlRnd1ptWmhNVFl6TkRnd1lXWmlPRFU1TXpjNE5qbG1OVFV6TVRSaE15SjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TW1FNU9HWXdOamd5WXpVd1pXWmhZems1TnpreE5ESmpNelExTTJRNE4yRTNaVEZtWW1FeU9HUTJPV0kxTnpSaE5XVTFNMlZsTURJM1pEUXdaR0ZpTVRBaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiVlBEbktIRUJvOTZDU05BSFpjN2FqNk5hdmd0MzlNQzB0cFZ0cm1XZkI1WmNKWUlUeG1TTDFpQS01QV9WZTFfUjRYNDRoRlh6TGhYQ3AwdFczdHozRncifQ',
iss: 'did:elem:EiAtmNkxOhWOhTCIxORy62LpFrNZQtVM7g6oDaxmDDlqmA;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBeU5XVTFNREkzTW1FM09UQTVPV1ZtTVRNNFpXRXpPVEF4WWpJeE5USTBOakEwWldNMVpETXhZakZqWVdJNFlqbGlaamt5WmpWak1EY3hNVEV5WlRRNE1DSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TXpJeE5XVXlZV1ZtWTJKbE1qQmpZV1ExWWpSbVl6Vm1PR1JsT0RRd01USTJObUl3T0dRellXWTBOekpsTWpFNU5ERXhZekptT1RGaFlqVTFZamMyTVdVaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoicVo3cTF5WkdfelNkcmJqZ2FYZWowVTFBeVFuT2M0YjlXLVJhMUJTRHN0OXhIUEx2M1psN0wxLVZ3dURVZi1ZbjRhVHdiTF9OSVNVVkpaOHdTUUZERGcifQ',
kid: 'did:elem:EiAtmNkxOhWOhTCIxORy62LpFrNZQtVM7g6oDaxmDDlqmA#primary'
}
Verification of Response#
Now issuer could validate a holder
const result = await issuerWallet.verifyCredentialOfferResponseToken(
credentialOfferResponseToken,
credentialOfferRequestToken,
)
result
{
isValid: true,
did: 'did:elem:EiAtmNkxOhWOhTCIxORy62LpFrNZQtVM7g6oDaxmDDlqmA;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBeU5XVTFNREkzTW1FM09UQTVPV1ZtTVRNNFpXRXpPVEF4WWpJeE5USTBOakEwWldNMVpETXhZakZqWVdJNFlqbGlaamt5WmpWak1EY3hNVEV5WlRRNE1DSjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TXpJeE5XVXlZV1ZtWTJKbE1qQmpZV1ExWWpSbVl6Vm1PR1JsT0RRd01USTJObUl3T0dRellXWTBOekpsTWpFNU5ERXhZekptT1RGaFlqVTFZamMyTVdVaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoicVo3cTF5WkdfelNkcmJqZ2FYZWowVTFBeVFuT2M0YjlXLVJhMUJTRHN0OXhIUEx2M1psN0wxLVZ3dURVZi1ZbjRhVHdiTF9OSVNVVkpaOHdTUUZERGcifQ',
nonce: '3fa7a7ad11b5d4ac',
selectedCredentials: [ { type: 'ContentLike', renderInfo: {} } ],
errors: []
}
Issue VC for Holder#
Now we could issue a credential for holder
const jsonSchema = 'https://schema.affinidi.com/ContentLikeV1-0.json'
const jsonContext = 'https://schema.affinidi.com/ContentLikeV1-0.jsonld'
const id = `claimId:${(Math.random() + 1).toString(36).substring(2)}`
const unsignedVC = {
'@context': ['https://www.w3.org/2018/credentials/v1', jsonContext],
id,
type: ['VerifiableCredential', 'ContentLike'],
holder: {
id: 'placeholder'
},
credentialSubject: {
data: {
'@type': ['VerifiableCredential', 'ContentLike'],
url: 'https://www.youtube.com/watch?v=owbkzvLhblk',
date: new Date().toISOString(),
like: true,
score: 10
},
},
credentialSchema: {
id: jsonSchema,
type: 'JsonSchemaValidator2018',
},
issuanceDate: new Date().toISOString(),
expirationDate: '2065-09-10T00:00:00.000Z',
}
const signedCredentials = await issuerWallet.signCredentials(
credentialOfferResponseToken,
[unsignedVC],
)
signedCredentials
[
{
'@context': [
'https://www.w3.org/2018/credentials/v1',
'https://schema.affinidi.com/ContentLikeV1-0.jsonld'
],
id: 'claimId:3b1426be69d03bc1',
type: [ 'VerifiableCredential', 'ContentLike' ],
holder: { id: 'did:elem:EiAtmNkxOhWOhTCIxORy62LpFrNZQtVM7g6oDaxmDDlqmA' },
credentialSubject: { data: [Object] },
issuanceDate: '2022-09-10T19:21:57.743Z',
expirationDate: '2065-09-10T00:00:00.000Z',
issuer: 'did:elem:EiDUbWAQsX9Y5KmZ9YhbRu7Cr4jyci4ZufveB3ACQYN77A;elem:initial-state=eyJwcm90ZWN0ZWQiOiJleUp2Y0dWeVlYUnBiMjRpT2lKamNtVmhkR1VpTENKcmFXUWlPaUlqY0hKcGJXRnllU0lzSW1Gc1p5STZJa1ZUTWpVMlN5SjkiLCJwYXlsb2FkIjoiZXlKQVkyOXVkR1Y0ZENJNkltaDBkSEJ6T2k4dmR6TnBaQzV2Y21jdmMyVmpkWEpwZEhrdmRqSWlMQ0p3ZFdKc2FXTkxaWGtpT2x0N0ltbGtJam9pSTNCeWFXMWhjbmtpTENKMWMyRm5aU0k2SW5OcFoyNXBibWNpTENKMGVYQmxJam9pVTJWamNESTFObXN4Vm1WeWFXWnBZMkYwYVc5dVMyVjVNakF4T0NJc0luQjFZbXhwWTB0bGVVaGxlQ0k2SWpBeU1EWXpOVGcxTkdZMllqZGxPVFEyTjJFNU1XRTFZelEzT0dVM05XRmtabUV3WlRnd1ptWmhNVFl6TkRnd1lXWmlPRFU1TXpjNE5qbG1OVFV6TVRSaE15SjlMSHNpYVdRaU9pSWpjbVZqYjNabGNua2lMQ0oxYzJGblpTSTZJbkpsWTI5MlpYSjVJaXdpZEhsd1pTSTZJbE5sWTNBeU5UWnJNVlpsY21sbWFXTmhkR2x2Ymt0bGVUSXdNVGdpTENKd2RXSnNhV05MWlhsSVpYZ2lPaUl3TW1FNU9HWXdOamd5WXpVd1pXWmhZems1TnpreE5ESmpNelExTTJRNE4yRTNaVEZtWW1FeU9HUTJPV0kxTnpSaE5XVTFNMlZsTURJM1pEUXdaR0ZpTVRBaWZWMHNJbUYxZEdobGJuUnBZMkYwYVc5dUlqcGJJaU53Y21sdFlYSjVJbDBzSW1GemMyVnlkR2x2YmsxbGRHaHZaQ0k2V3lJamNISnBiV0Z5ZVNKZGZRIiwic2lnbmF0dXJlIjoiVlBEbktIRUJvOTZDU05BSFpjN2FqNk5hdmd0MzlNQzB0cFZ0cm1XZkI1WmNKWUlUeG1TTDFpQS01QV9WZTFfUjRYNDRoRlh6TGhYQ3AwdFczdHozRncifQ',
proof: {
type: 'EcdsaSecp256k1Signature2019',
created: '2022-09-10T19:21:57Z',
verificationMethod: 'did:elem:EiDUbWAQsX9Y5KmZ9YhbRu7Cr4jyci4ZufveB3ACQYN77A#primary',
proofPurpose: 'assertionMethod',
jws: 'eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdfQ..XwB9-DL6CxMfjFUX_ItFduAUafvf-gECiNmBmqSCjA1WJJoZCFKGC1RMxf0GWV8YPpDUra7CJNItf5ZrAdqSGQ'
}
}
]