Ejemplo n.º 1
0
        public async Task IssueCredentialThrowsExceptionUnableToSendA2AMessage()
        {
            //Establish a connection between the two parties
            var(issuerConnection, holderConnection) = await Scenarios.EstablishConnectionAsync(
                _connectionService, _messages, _issuerWallet, _holderWallet);

            // Create an issuer DID/VK. Can also be created during provisioning
            var issuer = await Did.CreateAndStoreMyDidAsync(_issuerWallet.Wallet,
                                                            new { seed = "000000000000000000000000Steward1" }.ToJson());

            // Creata a schema and credential definition for this issuer
            (var definitionId, _) = await Scenarios.CreateDummySchemaAndNonRevokableCredDef(_issuerWallet, _schemaService, issuer.Did,
                                                                                            new[] { "dummy_attr" });

            var offerConfig = new OfferConfiguration()
            {
                IssuerDid = issuer.Did,
                CredentialDefinitionId = definitionId
            };

            // Send an offer to the holder using the established connection channel
            await _credentialService.SendOfferAsync(_issuerWallet, issuerConnection.Id, offerConfig);

            // Holder retrives message from their cloud agent
            var credentialOffer = FindContentMessage <CredentialOfferMessage>(_messages);

            // Holder processes the credential offer by storing it
            var holderCredentialId =
                await _credentialService.ProcessOfferAsync(_holderWallet, credentialOffer, holderConnection);

            // Holder creates master secret. Will also be created during wallet agent provisioning
            await AnonCreds.ProverCreateMasterSecretAsync(_holderWallet.Wallet, MasterSecretId);

            // Holder accepts the credential offer and sends a credential request
            await _credentialService.AcceptOfferAsync(_holderWallet, holderCredentialId,
                                                      new Dictionary <string, string>
            {
                { "dummy_attr", "dummyVal" }
            });

            // Issuer retrieves credential request from cloud agent
            var credentialRequest = FindContentMessage <CredentialRequestMessage>(_messages);

            Assert.NotNull(credentialRequest);

            // Issuer processes the credential request by storing it
            var issuerCredentialId =
                await _credentialService.ProcessCredentialRequestAsync(_issuerWallet, credentialRequest, issuerConnection);

            //Try issue the credential with a credential service that has a bad routing service

            _routeMessage = false;
            var ex = await Assert.ThrowsAsync <AgentFrameworkException>(async() => await _credentialService.IssueCredentialAsync(_issuerWallet, issuer.Did, issuerCredentialId));

            Assert.True(ex.ErrorCode == ErrorCode.A2AMessageTransmissionError);
            _routeMessage = true;
        }
Ejemplo n.º 2
0
        public async Task RejectCredentialRequestThrowsExceptionCredentialInvalidState()
        {
            //Establish a connection between the two parties
            var(issuerConnection, holderConnection) = await Scenarios.EstablishConnectionAsync(
                _connectionService, _messages, _issuerWallet, _holderWallet);

            // Create an issuer DID/VK. Can also be created during provisioning
            var issuer = await Did.CreateAndStoreMyDidAsync(_issuerWallet.Wallet,
                                                            new { seed = TestConstants.StewartDid }.ToJson());

            // Create a schema and credential definition for this issuer
            var(definitionId, _) = await Scenarios.CreateDummySchemaAndNonRevokableCredDef(_issuerWallet, _schemaService, issuer.Did,
                                                                                           new[] { "dummy_attr" });

            var offerConfig = new OfferConfiguration
            {
                IssuerDid = issuer.Did,
                CredentialDefinitionId = definitionId
            };

            // Send an offer to the holder using the established connection channel
            var(offerMessage, _) = await _credentialService.CreateOfferAsync(_issuerWallet, offerConfig, issuerConnection.Id);

            _messages.Add(offerMessage);

            // Holder retrieves message from their cloud agent
            var credentialOffer = FindContentMessage <CredentialOfferMessage>(_messages);

            // Holder processes the credential offer by storing it
            var holderCredentialId =
                await _credentialService.ProcessOfferAsync(_holderWallet, credentialOffer, holderConnection);

            // Holder creates master secret. Will also be created during wallet agent provisioning
            await AnonCreds.ProverCreateMasterSecretAsync(_holderWallet.Wallet, TestConstants.DefaultMasterSecret);

            // Holder accepts the credential offer and sends a credential request
            (var request, var _) = await _credentialService.CreateRequestAsync(_holderWallet, holderCredentialId);

            _messages.Add(request);

            // Issuer retrieves credential request from cloud agent
            var credentialRequest = FindContentMessage <CredentialRequestMessage>(_messages);

            Assert.NotNull(credentialRequest);

            // Issuer processes the credential request by storing it
            var issuerCredentialId =
                await _credentialService.ProcessCredentialRequestAsync(_issuerWallet, credentialRequest, issuerConnection);

            await _credentialService.RejectCredentialRequestAsync(_issuerWallet, issuerCredentialId);

            //Try reject the credential request again
            var ex = await Assert.ThrowsAsync <AriesFrameworkException>(async() => await _credentialService.RejectCredentialRequestAsync(_issuerWallet, issuerCredentialId));

            Assert.True(ex.ErrorCode == ErrorCode.RecordInInvalidState);
        }
Ejemplo n.º 3
0
        public async Task <IActionResult> SendOfferCredential(string connectionId, string credDefId)
        {
            var agentContext = await _agentContextProvider.GetContextAsync();

            var connectionRecord = await _connectionService.GetAsync(agentContext, connectionId);

            //{ "type", "passportNumber", "issuerCountryCode", "firstname", "familyname", "birthdate", "citizenship", "sex", "placeOfBirth", "issuingDate", "expiryDate" }
            var offerConfig = new OfferConfiguration
            {
                CredentialDefinitionId = credDefId,
                IssuerDid = "Th7MpTaRZVRYnPiabds81Y",
                CredentialAttributeValues = new []
                {
                    new CredentialPreviewAttribute("type", "passport"),
                    new CredentialPreviewAttribute("passportNumber", $"{Guid.NewGuid().ToString("N")}"),
                    new CredentialPreviewAttribute("issuerCountryCode", "CH"),
                    new CredentialPreviewAttribute("firstname", "John"),
                    new CredentialPreviewAttribute("familyname", "Doe"),
                    new CredentialPreviewAttribute("birthdate", "1968-02-12T:15:00:00Z"),
                    new CredentialPreviewAttribute("citizenship", "CH"),
                    new CredentialPreviewAttribute("sex", "M"),
                    new CredentialPreviewAttribute("placeOfBirth", "Paris"),
                    new CredentialPreviewAttribute("issuingDate", "20-01-2020"),
                    new CredentialPreviewAttribute("expiryDate", "20-01-2030")
                }
            };

            /*var offerConfig = new OfferConfiguration
             * {
             *  CredentialDefinitionId = credDefId,
             *  IssuerDid = "Th7MpTaRZVRYnPiabds81Y",
             *  CredentialAttributeValues = new[] { new CredentialPreviewAttribute("first_name", "Test"), new CredentialPreviewAttribute("last_name", "Holder") }
             * };*/

            (var credOfferMsg, _) = await _credentialService.CreateOfferAsync(agentContext, offerConfig, connectionId);

            await _messageService.SendAsync(agentContext.Wallet, credOfferMsg, connectionRecord);

            return(RedirectToAction("Details", "Connections", new { id = connectionId }));
        }
Ejemplo n.º 4
0
        public async Task RejectOfferAsyncThrowsExeceptionCredentialOfferInvalidState()
        {
            //Establish a connection between the two parties
            var(issuerConnection, holderConnection) = await Scenarios.EstablishConnectionAsync(
                _connectionService, _messages, _issuerWallet, _holderWallet);

            // Create an issuer DID/VK. Can also be created during provisioning
            var issuer = await Did.CreateAndStoreMyDidAsync(_issuerWallet.Wallet,
                                                            new { seed = "000000000000000000000000Steward1" }.ToJson());

            // Creata a schema and credential definition for this issuer
            (var definitionId, _) = await Scenarios.CreateDummySchemaAndNonRevokableCredDef(_issuerWallet, _schemaService, issuer.Did,
                                                                                            new[] { "dummy_attr" });

            var offerConfig = new OfferConfiguration()
            {
                IssuerDid = issuer.Did,
                CredentialDefinitionId = definitionId
            };

            // Send an offer to the holder using the established connection channel
            await _credentialService.SendOfferAsync(_issuerWallet, issuerConnection.Id, offerConfig);

            // Holder retrives message from their cloud agent
            var credentialOffer = FindContentMessage <CredentialOfferMessage>(_messages);

            // Holder processes the credential offer by storing it
            var holderCredentialId =
                await _credentialService.ProcessOfferAsync(_holderWallet, credentialOffer, holderConnection);

            //Reject the offer
            await _credentialService.RejectOfferAsync(_holderWallet, holderCredentialId);

            //Try reject the offer again
            var ex = await Assert.ThrowsAsync <AgentFrameworkException>(async() => await _credentialService.RejectOfferAsync(_holderWallet, holderCredentialId));

            Assert.True(ex.ErrorCode == ErrorCode.RecordInInvalidState);
        }
Ejemplo n.º 5
0
        public async Task <(CredentialOfferMessage, CredentialRecord)> CreateOfferV1Async(IAgentContext agentContext, OfferConfiguration config, string connectionId = null)
        {
            Logger.LogInformation(LoggingEvents.CreateCredentialOffer, "DefinitionId {0}, IssuerDid {1}",
                                  config.CredentialDefinitionId, config.IssuerDid);

            var threadId = Guid.NewGuid().ToString();

            if (!string.IsNullOrEmpty(connectionId))
            {
                var connection = await ConnectionService.GetAsync(agentContext, connectionId);

                if (connection.State != ConnectionState.Connected)
                {
                    throw new AgentFrameworkException(ErrorCode.RecordInInvalidState,
                                                      $"Connection state was invalid. Expected '{ConnectionState.Connected}', found '{connection.State}'");
                }
            }

            if (config.CredentialAttributeValues != null && config.CredentialAttributeValues.Any())
            {
                CredentialUtils.ValidateCredentialPreviewAttributes(config.CredentialAttributeValues);
            }

            var offerJson = await AnonCreds.IssuerCreateCredentialOfferAsync(
                agentContext.Wallet, config.CredentialDefinitionId);

            var offerJobj = JObject.Parse(offerJson);
            var schemaId  = offerJobj["schema_id"].ToObject <string>();

            // Write offer record to local wallet
            var credentialRecord = new CredentialRecord
            {
                Id = Guid.NewGuid().ToString(),
                CredentialDefinitionId = config.CredentialDefinitionId,
                OfferJson    = offerJson,
                ConnectionId = connectionId,
                SchemaId     = schemaId,
                CredentialAttributesValues = config.CredentialAttributeValues,
                State = CredentialState.Offered,
            };

            credentialRecord.SetTag(TagConstants.LastThreadId, threadId);
            credentialRecord.SetTag(TagConstants.Role, TagConstants.Issuer);

            if (!string.IsNullOrEmpty(config.IssuerDid))
            {
                credentialRecord.SetTag(TagConstants.IssuerDid, config.IssuerDid);
            }

            if (config.Tags != null)
            {
                foreach (var tag in config.Tags)
                {
                    if (!credentialRecord.Tags.Keys.Contains(tag.Key))
                    {
                        credentialRecord.Tags.Add(tag.Key, tag.Value);
                    }
                }
            }

            await RecordService.AddAsync(agentContext.Wallet, credentialRecord);

            return(new CredentialOfferMessage
            {
                Id = threadId,
                Offers = new Attachment[]
                {
                    new Attachment
                    {
                        Id = "libindy-cred-offer-0",
                        MimeType = CredentialMimeTypes.ApplicationJsonMimeType,
                        Data = new AttachmentContent
                        {
                            Base64 = offerJson.GetUTF8Bytes().ToBase64String()
                        }
                    }
                },
                CredentialPreview = credentialRecord.CredentialAttributesValues != null ? new CredentialPreviewMessage
                {
                    Attributes = credentialRecord.CredentialAttributesValues.Select(x => new CredentialPreviewAttriubute
                    {
                        Name = x.Name,
                        MimeType = x.MimeType,
                        Value = x.Value?.ToString()
                    }).ToArray()
                } : null
            }, credentialRecord);
        }
Ejemplo n.º 6
0
        public static async Task <(CredentialRecord issuerCredential, CredentialRecord holderCredential)> IssueCredentialAsync(
            ISchemaService schemaService, ICredentialService credentialService,
            IProducerConsumerCollection <AgentMessage> messages,
            ConnectionRecord issuerConnection, ConnectionRecord holderConnection,
            IAgentContext issuerContext,
            IAgentContext holderContext,
            Pool pool, string proverMasterSecretId, bool revocable, List <CredentialPreviewAttribute> credentialAttributes, OfferConfiguration offerConfiguration = null)
        {
            // Create an issuer DID/VK. Can also be created during provisioning
            var issuer = await Did.CreateAndStoreMyDidAsync(issuerContext.Wallet,
                                                            new { seed = TestConstants.StewartDid }.ToJson());

            // Create a schema and credential definition for this issuer
            var(definitionId, _) = await CreateDummySchemaAndNonRevokableCredDef(issuerContext, schemaService,
                                                                                 issuer.Did, credentialAttributes.Select(_ => _.Name).ToArray());

            var offerConfig = offerConfiguration ?? new OfferConfiguration
            {
                IssuerDid = issuer.Did,
                CredentialDefinitionId = definitionId
            };

            // Send an offer to the holder using the established connection channel
            var(offerMessage, _) = await credentialService.CreateOfferAsync(issuerContext, offerConfig, issuerConnection.Id);

            messages.TryAdd(offerMessage);

            // Holder retrieves message from their cloud agent
            var credentialOffer = FindContentMessage <CredentialOfferMessage>(messages);

            // Holder processes the credential offer by storing it
            var holderCredentialId =
                await credentialService.ProcessOfferAsync(holderContext, credentialOffer, holderConnection);

            // Holder creates master secret. Will also be created during wallet agent provisioning
            await AnonCreds.ProverCreateMasterSecretAsync(holderContext.Wallet, proverMasterSecretId);

            // Holder accepts the credential offer and sends a credential request
            var(request, _) = await credentialService.CreateCredentialRequestAsync(holderContext, holderCredentialId);

            messages.TryAdd(request);

            // Issuer retrieves credential request from cloud agent
            var credentialRequest = FindContentMessage <CredentialRequestMessage>(messages);

            Assert.NotNull(credentialRequest);

            // Issuer processes the credential request by storing it
            var issuerCredentialId =
                await credentialService.ProcessCredentialRequestAsync(issuerContext, credentialRequest, issuerConnection);

            // Issuer accepts the credential requests and issues a credential
            var(credentialMessage, _) = await credentialService.CreateCredentialAsync(issuerContext, issuer.Did,
                                                                                      issuerCredentialId,
                                                                                      credentialAttributes);

            messages.TryAdd(credentialMessage);

            // Holder retrieves the credential from their cloud agent
            var credential = FindContentMessage <CredentialMessage>(messages);

            Assert.NotNull(credential);

            // Holder processes the credential by storing it in their wallet
            await credentialService.ProcessCredentialAsync(holderContext, credential, holderConnection);

            // Verify states of both credential records are set to 'Issued'
            var issuerCredential = await credentialService.GetAsync(issuerContext, issuerCredentialId);

            var holderCredential = await credentialService.GetAsync(holderContext, holderCredentialId);

            return(issuerCredential, holderCredential);
        }
Ejemplo n.º 7
0
        /// <inheritdoc />
        public virtual async Task <(TransactionRecord transaction, ConnectionRecord connection, ConnectionInvitationMessage message)> CreateOrUpadteTransactionAsync(
            IAgentContext agentContext,
            string transactionId = null,
            string connectionId  = null,
            OfferConfiguration offerConfiguration = null,
            ProofRequest proofRequest             = null,
            InviteConfiguration connectionConfig  = null,
            string CredentialComment = "",
            string ProofComment      = "")
        {
            Logger.LogInformation(CustomLoggingEvents.CreateTransaction, "For {1}", transactionId);

            (ConnectionInvitationMessage message, ConnectionRecord record)connection;
            TransactionRecord transactionRecord;

            if (string.IsNullOrEmpty(connectionId))
            {
                connectionConfig = connectionConfig ?? new InviteConfiguration()
                {
                    AutoAcceptConnection = true,
                    MultiPartyInvitation = true
                };

                connection = (await ConnectionService.CreateInvitationAsync(agentContext, connectionConfig));
                connection.record.SetTag("InvitationMessage", JObject.FromObject(connection.message).ToString());
                await RecordService.UpdateAsync(agentContext.Wallet, connection.record);
            }
            else
            {
                if ((await ConnectionService.GetAsync(agentContext, connectionId)) != null)
                {
                    connection.record = await RecordService.GetAsync <ConnectionRecord>(agentContext.Wallet, connectionId);

                    var message = connection.record.GetTag("InvitationMessage");
                    connection.message = JObject.Parse(message).ToObject <ConnectionInvitationMessage>();
                }
                else
                {
                    throw new AriesFrameworkException(ErrorCode.RecordNotFound,
                                                      $"Connection '{connectionId}' not found.");
                }
            }

            transactionId = !string.IsNullOrEmpty(transactionId)
            ? transactionId
            : Guid.NewGuid().ToString();

            if ((await RecordService.GetAsync <TransactionRecord>(agentContext.Wallet, transactionId)) == null)
            {
                transactionRecord = new TransactionRecord
                {
                    Id                 = transactionId,
                    ConnectionId       = connection.record.Id,
                    OfferConfiguration = offerConfiguration,
                    ProofRequest       = proofRequest,
                    Used               = false,
                    CredentialComment  = CredentialComment,
                    ProofComment       = ProofComment
                };

                await RecordService.AddAsync(agentContext.Wallet, transactionRecord);
            }
            else
            {
                transactionRecord = await RecordService.GetAsync <TransactionRecord>(agentContext.Wallet, transactionId);

                transactionRecord.ConnectionId       = connection.record.Id;
                transactionRecord.OfferConfiguration = offerConfiguration;
                transactionRecord.ProofRequest       = proofRequest;

                await RecordService.UpdateAsync(agentContext.Wallet, transactionRecord);
            }

            return(transactionRecord, connection.record, connection.message);
        }
        /// <inheritdoc />
        public virtual async Task <string> SendOfferAsync(IAgentContext agentContext, string connectionId, OfferConfiguration config)
        {
            Logger.LogInformation(LoggingEvents.SendCredentialOffer, "DefinitionId {0}, ConnectionId {1}, IssuerDid {2}",
                                  config.CredentialDefinitionId, connectionId, config.IssuerDid);

            var connection = await ConnectionService.GetAsync(agentContext, connectionId);

            if (connection.State != ConnectionState.Connected)
            {
                throw new AgentFrameworkException(ErrorCode.RecordInInvalidState,
                                                  $"Connection state was invalid. Expected '{ConnectionState.Connected}', found '{connection.State}'");
            }

            (var offer, string id) = await CreateOfferAsync(agentContext, config);

            try
            {
                await MessageService.SendAsync(agentContext.Wallet, offer, connection);
            }
            catch (Exception e)
            {
                await RecordService.DeleteAsync <CredentialRecord>(agentContext.Wallet, id);

                throw new AgentFrameworkException(ErrorCode.A2AMessageTransmissionError, "Failed to send credential offer message", e);
            }

            return(id);
        }
        /// <inheritdoc />
        public virtual async Task <(CredentialOfferMessage, string)> CreateOfferAsync(IAgentContext agentContext, OfferConfiguration config, string connectionId = null)
        {
            Logger.LogInformation(LoggingEvents.CreateCredentialOffer, "DefinitionId {0}, ConnectionId {1}, IssuerDid {2}",
                                  config.CredentialDefinitionId, config.IssuerDid);

            if (!config.MultiPartyOffer && !string.IsNullOrEmpty(connectionId))
            {
                var connection = await ConnectionService.GetAsync(agentContext, connectionId);

                if (connection.State != ConnectionState.Connected)
                {
                    throw new AgentFrameworkException(ErrorCode.RecordInInvalidState,
                                                      $"Connection state was invalid. Expected '{ConnectionState.Connected}', found '{connection.State}'");
                }
            }

            var offerJson = await AnonCreds.IssuerCreateCredentialOfferAsync(agentContext.Wallet, config.CredentialDefinitionId);

            var nonce = JObject.Parse(offerJson)["nonce"].ToObject <string>();

            // Write offer record to local wallet
            var credentialRecord = new CredentialRecord
            {
                Id = Guid.NewGuid().ToString(),
                CredentialDefinitionId = config.CredentialDefinitionId,
                OfferJson       = offerJson,
                MultiPartyOffer = config.MultiPartyOffer,
                ValuesJson      = CredentialUtils.FormatCredentialValues(config.CredentialAttributeValues),
                State           = CredentialState.Offered,
            };

            if (!config.MultiPartyOffer)
            {
                credentialRecord.ConnectionId = connectionId;
            }

            credentialRecord.SetTag(TagConstants.Nonce, nonce);
            credentialRecord.SetTag(TagConstants.Role, TagConstants.Issuer);

            if (!string.IsNullOrEmpty(config.IssuerDid))
            {
                credentialRecord.Tags.Add(TagConstants.IssuerDid, config.IssuerDid);
            }

            if (config.Tags != null)
            {
                foreach (var tag in config.Tags)
                {
                    if (!credentialRecord.Tags.Keys.Contains(tag.Key))
                    {
                        credentialRecord.Tags.Add(tag.Key, tag.Value);
                    }
                }
            }

            await RecordService.AddAsync(agentContext.Wallet, credentialRecord);

            return(new CredentialOfferMessage {
                OfferJson = offerJson
            }, credentialRecord.Id);
        }
Ejemplo n.º 10
0
        internal static async Task <(CredentialRecord issuerCredential, CredentialRecord holderCredential)> IssueCredentialAsync(
            ISchemaService schemaService, ICredentialService credentialService,
            IProducerConsumerCollection <IAgentMessage> messages,
            ConnectionRecord issuerConnection, ConnectionRecord holderConnection,
            IAgentContext issuerContext,
            IAgentContext holderContext,
            Pool pool, string proverMasterSecretId, bool revocable, OfferConfiguration offerConfiguration = null)
        {
            // Create an issuer DID/VK. Can also be created during provisioning
            var issuer = await Did.CreateAndStoreMyDidAsync(issuerContext.Wallet,
                                                            new { seed = "000000000000000000000000Steward1" }.ToJson());

            // Creata a schema and credential definition for this issuer
            (string definitionId, _) = await CreateDummySchemaAndNonRevokableCredDef(issuerContext, schemaService, issuer.Did, new[] { "first_name", "last_name" });

            var offerConfig = offerConfiguration ?? new OfferConfiguration
            {
                IssuerDid = issuer.Did,
                CredentialDefinitionId = definitionId
            };

            // Send an offer to the holder using the established connection channel
            await credentialService.SendOfferAsync(issuerContext, issuerConnection.Id, offerConfig);

            // Holder retrives message from their cloud agent
            var credentialOffer = FindContentMessage <CredentialOfferMessage>(messages);

            // Holder processes the credential offer by storing it
            var holderCredentialId =
                await credentialService.ProcessOfferAsync(holderContext, credentialOffer, holderConnection);

            // Holder creates master secret. Will also be created during wallet agent provisioning
            await AnonCreds.ProverCreateMasterSecretAsync(holderContext.Wallet, proverMasterSecretId);

            // Holder accepts the credential offer and sends a credential request
            await credentialService.AcceptOfferAsync(holderContext, holderCredentialId,
                                                     new Dictionary <string, string>
            {
                { "first_name", "Jane" },
                { "last_name", "Doe" }
            });

            // Issuer retrieves credential request from cloud agent
            var credentialRequest = FindContentMessage <CredentialRequestMessage>(messages);

            Assert.NotNull(credentialRequest);

            // Issuer processes the credential request by storing it
            var issuerCredentialId =
                await credentialService.ProcessCredentialRequestAsync(issuerContext, credentialRequest, issuerConnection);

            // Issuer accepts the credential requests and issues a credential
            await credentialService.IssueCredentialAsync(issuerContext, issuer.Did, issuerCredentialId);

            // Holder retrieves the credential from their cloud agent
            var credential = FindContentMessage <CredentialMessage>(messages);

            Assert.NotNull(credential);

            // Holder processes the credential by storing it in their wallet
            await credentialService.ProcessCredentialAsync(holderContext, credential, holderConnection);

            // Verify states of both credential records are set to 'Issued'
            var issuerCredential = await credentialService.GetAsync(issuerContext, issuerCredentialId);

            var holderCredential = await credentialService.GetAsync(holderContext, holderCredentialId);

            return(issuerCredential, holderCredential);
        }