/// <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);
            }
        }
Esempio n. 2
0
        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);
        }
Esempio n. 7
0
        /// <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());
        }