/// <inheritdoc /> public virtual async Task AcceptOfferAsync(IAgentContext agentContext, string credentialId, Dictionary <string, string> attributeValues = null) { var credential = await GetAsync(agentContext, credentialId); if (credential.State != CredentialState.Offered) { throw new AgentFrameworkException(ErrorCode.RecordInInvalidState, $"Credential state was invalid. Expected '{CredentialState.Offered}', found '{credential.State}'"); } var credentialCopy = credential.DeepCopy(); var connection = await ConnectionService.GetAsync(agentContext, credential.ConnectionId); var definition = await LedgerService.LookupDefinitionAsync(agentContext.Pool, credential.CredentialDefinitionId); var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet); var request = await AnonCreds.ProverCreateCredentialReqAsync(agentContext.Wallet, connection.MyDid, credential.OfferJson, definition.ObjectJson, provisioning.MasterSecretId); // Update local credential record with new info credential.CredentialRequestMetadataJson = request.CredentialRequestMetadataJson; await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.UpdateAsync(agentContext.Wallet, credential); var msg = new CredentialRequestMessage { OfferJson = credential.OfferJson, CredentialRequestJson = request.CredentialRequestJson, CredentialValuesJson = CredentialUtils.FormatCredentialValues(attributeValues) }; try { await MessageService.SendAsync(agentContext.Wallet, msg, connection); } catch (Exception e) { await RecordService.UpdateAsync(agentContext.Wallet, credentialCopy); throw new AgentFrameworkException(ErrorCode.A2AMessageTransmissionError, "Failed to send credential request message", e); } }
public async Task <(CredentialRequestMessage, CredentialRecord)> CreateRequestAsync(IAgentContext agentContext, string credentialId) { var credential = await GetAsync(agentContext, credentialId); if (credential.State != CredentialState.Offered) { throw new AgentFrameworkException(ErrorCode.RecordInInvalidState, $"Credential state was invalid. Expected '{CredentialState.Offered}', found '{credential.State}'"); } var connection = await ConnectionService.GetAsync(agentContext, credential.ConnectionId); var definition = await LedgerService.LookupDefinitionAsync(await agentContext.Pool, credential.CredentialDefinitionId); var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet); var request = await AnonCreds.ProverCreateCredentialReqAsync(agentContext.Wallet, connection.MyDid, credential.OfferJson, definition.ObjectJson, provisioning.MasterSecretId); // Update local credential record with new info credential.CredentialRequestMetadataJson = request.CredentialRequestMetadataJson; await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.UpdateAsync(agentContext.Wallet, credential); var threadId = credential.GetTag(TagConstants.LastThreadId); var response = new CredentialRequestMessage { Requests = new[] { new Attachment { Id = "libindy-cred-request-0", MimeType = CredentialMimeTypes.ApplicationJsonMimeType, Data = new AttachmentContent { Base64 = request.CredentialRequestJson.GetUTF8Bytes().ToBase64String() } } } }; response.ThreadFrom(threadId); return(response, credential); }
/// <inheritdoc /> public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var item = JObject.Load(reader); var(_, messageType) = MessageUtils.ParseMessageType(item["@type"].ToObject <string>()); IContentMessage message; switch (messageType) { case MessageTypes.ConnectionRequest: message = new ConnectionRequestMessage(); break; case MessageTypes.ConnectionResponse: message = new ConnectionResponseMessage(); break; case MessageTypes.CredentialOffer: message = new CredentialOfferMessage(); break; case MessageTypes.CredentialRequest: message = new CredentialRequestMessage(); break; case MessageTypes.Credential: message = new CredentialMessage(); break; case MessageTypes.ProofRequest: message = new ProofRequestMessage(); break; case MessageTypes.DisclosedProof: message = new ProofMessage(); break; default: throw new TypeLoadException("Unsupported serialization type."); } serializer.Populate(item.CreateReader(), message); return(message); }
/// <inheritdoc /> public virtual async Task <(CredentialRequestMessage, CredentialRecord)> CreateCredentialRequestAsync( IAgentContext agentContext, string offerId) { var credential = await GetAsync(agentContext, offerId); if (credential.State != CredentialState.Offered) { throw new AgentFrameworkException(ErrorCode.RecordInInvalidState, $"Credential state was invalid. Expected '{CredentialState.Offered}', found '{credential.State}'"); } var connection = await ConnectionService.GetAsync(agentContext, credential.ConnectionId); var definition = await LedgerService.LookupDefinitionAsync(await agentContext.Pool, credential.CredentialDefinitionId); var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet); var request = await AnonCreds.ProverCreateCredentialReqAsync(agentContext.Wallet, connection.MyDid, credential.OfferJson, definition.ObjectJson, provisioning.MasterSecretId); // Update local credential record with new info credential.CredentialRequestMetadataJson = request.CredentialRequestMetadataJson; await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.UpdateAsync(agentContext.Wallet, credential); var threadId = credential.GetTag(TagConstants.LastThreadId); var response = new CredentialRequestMessage { CredentialRequestJson = request.CredentialRequestJson }; response.ThreadFrom(threadId); return(response, credential); }
/// <inheritdoc /> public virtual async Task <string> ProcessCredentialRequestAsync(IAgentContext agentContext, CredentialRequestMessage credentialRequest, ConnectionRecord connection) { Logger.LogInformation(LoggingEvents.StoreCredentialRequest, "Type {0},", credentialRequest.Type); var request = JObject.Parse(credentialRequest.OfferJson); var nonce = request["nonce"].ToObject <string>(); var query = SearchQuery.Equal(TagConstants.Nonce, nonce); var credentialSearch = await RecordService.SearchAsync <CredentialRecord>(agentContext.Wallet, query, null, 5); if (credentialSearch.Count == 0) { throw new AgentFrameworkException(ErrorCode.RecordNotFound, "Credential record not found"); } var credential = credentialSearch.Single(); // TODO: Use threading if (credential.State != CredentialState.Offered) { throw new AgentFrameworkException(ErrorCode.RecordInInvalidState, $"Credential state was invalid. Expected '{CredentialState.Offered}', found '{credential.State}'"); } if (!string.IsNullOrEmpty(credentialRequest.CredentialValuesJson) && JObject.Parse(credentialRequest.CredentialValuesJson).Count != 0) { credential.ValuesJson = credentialRequest.CredentialValuesJson; } credential.RequestJson = credentialRequest.CredentialRequestJson; credential.ConnectionId = connection.Id; if (!credential.MultiPartyOffer) { await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.UpdateAsync(agentContext.Wallet, credential); EventAggregator.Publish(new ServiceMessageProcessingEvent { RecordId = credential.Id, MessageType = credentialRequest.Type, }); return(credential.Id); } var newCredential = credential.DeepCopy(); newCredential.Id = Guid.NewGuid().ToString(); await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.AddAsync(agentContext.Wallet, newCredential); EventAggregator.Publish(new ServiceMessageProcessingEvent { RecordId = newCredential.Id, MessageType = credentialRequest.Type, }); return(newCredential.Id); }
/// <inheritdoc /> public virtual async Task <string> ProcessCredentialRequestAsync(IAgentContext agentContext, CredentialRequestMessage credentialRequest, ConnectionRecord connection) { Logger.LogInformation(LoggingEvents.StoreCredentialRequest, "Type {0},", credentialRequest.Type); var credential = await this.GetByThreadIdAsync(agentContext, credentialRequest.GetThreadId()); if (credential.State != CredentialState.Offered) { throw new AgentFrameworkException(ErrorCode.RecordInInvalidState, $"Credential state was invalid. Expected '{CredentialState.Offered}', found '{credential.State}'"); } credential.RequestJson = credentialRequest.CredentialRequestJson; credential.ConnectionId = connection.Id; await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.UpdateAsync(agentContext.Wallet, credential); EventAggregator.Publish(new ServiceMessageProcessingEvent { RecordId = credential.Id, MessageType = credentialRequest.Type, ThreadId = credentialRequest.GetThreadId() }); return(credential.Id); }
/// <inheritdoc /> public virtual async Task <string> ProcessCredentialRequestAsync(Wallet wallet, CredentialRequestMessage credentialRequest) { Logger.LogInformation(LoggingEvents.StoreCredentialRequest, "Type {0},", credentialRequest.Type); var(didOrKey, _) = MessageUtils.ParseMessageType(credentialRequest.Type); var connectionSearch = await ConnectionService.ListAsync(wallet, new SearchRecordQuery { { TagConstants.MyDid, didOrKey } }); if (!connectionSearch.Any()) { throw new Exception($"Can't find connection record for type {credentialRequest.Type}"); } var connection = connectionSearch.First(); var(details, _) = await MessageSerializer.UnpackSealedAsync <CredentialRequestDetails>( credentialRequest.Content, wallet, connection.MyVk); var request = JObject.Parse(details.OfferJson); var nonce = request["nonce"].ToObject <string>(); var query = new SearchRecordQuery { { TagConstants.Nonce, nonce } }; var credentialSearch = await RecordService.SearchAsync <CredentialRecord>(wallet, query, null, 1); var credential = credentialSearch.Single(); // Offer should already be present // credential.OfferJson = details.OfferJson; if (!string.IsNullOrEmpty(details.CredentialValuesJson) && JObject.Parse(details.CredentialValuesJson).Count != 0) { credential.ValuesJson = details.CredentialValuesJson; } credential.RequestJson = details.CredentialRequestJson; await credential.TriggerAsync(CredentialTrigger.Request); await RecordService.UpdateAsync(wallet, credential); return(credential.GetId()); }