Example #1
0
        /// <inheritdoc />
        public virtual async Task <ProofMessage> CreateProofAsync(IAgentContext agentContext, string proofRequestId,
                                                                  RequestedCredentials requestedCredentials)
        {
            var record = await GetAsync(agentContext, proofRequestId);

            if (record.State != ProofState.Requested)
            {
                throw new AgentFrameworkException(ErrorCode.RecordInInvalidState,
                                                  $"Proof state was invalid. Expected '{ProofState.Requested}', found '{record.State}'");
            }

            var provisioningRecord = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet);

            var credentialObjects = new List <CredentialInfo>();

            foreach (var credId in requestedCredentials.GetCredentialIdentifiers())
            {
                credentialObjects.Add(
                    JsonConvert.DeserializeObject <CredentialInfo>(
                        await AnonCreds.ProverGetCredentialAsync(agentContext.Wallet, credId)));
            }

            var schemas = await BuildSchemasAsync(agentContext.Pool,
                                                  credentialObjects
                                                  .Select(x => x.SchemaId)
                                                  .Distinct());

            var definitions = await BuildCredentialDefinitionsAsync(agentContext.Pool,
                                                                    credentialObjects
                                                                    .Select(x => x.CredentialDefinitionId)
                                                                    .Distinct());

            var revocationStates = await BuildRevocationStatesAsync(agentContext.Pool,
                                                                    credentialObjects,
                                                                    requestedCredentials);

            var proofJson = await AnonCreds.ProverCreateProofAsync(agentContext.Wallet, record.RequestJson,
                                                                   requestedCredentials.ToJson(), provisioningRecord.MasterSecretId, schemas, definitions,
                                                                   revocationStates);

            record.ProofJson = proofJson;
            await record.TriggerAsync(ProofTrigger.Accept);

            await RecordService.UpdateAsync(agentContext.Wallet, record);

            return(new ProofMessage
            {
                ProofJson = proofJson,
                RequestNonce = JsonConvert.DeserializeObject <ProofRequest>(record.RequestJson).Nonce
            });
        }
        protected async Task FundDefaultAccountAsync(ulong amount)
        {
            var record = await provisioningService.GetProvisioningAsync(Context.Wallet);

            var addressRecord = await recordService.GetAsync <PaymentAddressRecord>(Context.Wallet, record.DefaultPaymentAddressId);

            // Mint tokens to the address to fund initially
            var request = await IndyPayments.BuildMintRequestAsync(Context.Wallet, Trustee.Did,
                                                                   new[] { new { recipient = addressRecord.Address, amount = amount } }.ToJson(), null);

            await TrusteeMultiSignAndSubmitRequestAsync(request.Result);

            await paymentService.RefreshBalanceAsync(Context, addressRecord);
        }
Example #3
0
        public async Task <IActionResult> CreateInvitation()
        {
            var context = new AgentContext
            {
                Wallet = await _walletService.GetWalletAsync(_walletOptions.WalletConfiguration,
                                                             _walletOptions.WalletCredentials)
            };

            var invitation = await _connectionService.CreateInvitationAsync(context, new InviteConfiguration { AutoAcceptConnection = true });

            ViewData["Invitation"] = EncodeInvitation(invitation.Invitation);
            ViewData["DefaultUri"] = $"{(await _provisioningService.GetProvisioningAsync(context.Wallet)).Endpoint.Uri}?c_i=";
            return(View());
        }
Example #4
0
        private async Task CreateConnection(IAgentContext context, ConnectionInvitationMessage invite)
        {
            var provisioningRecord = await _provisioningService.GetProvisioningAsync(context.Wallet);

            var isEndpointUriAbsent = provisioningRecord.Endpoint.Uri == null;

            var(msg, rec) = await _connectionService.CreateRequestAsync(context, _invite);

            var rsp = await _messageService.SendAsync(context.Wallet, msg, rec, _invite.RecipientKeys.First(), isEndpointUriAbsent);

            if (isEndpointUriAbsent)
            {
                await _connectionService.ProcessResponseAsync(context, rsp.GetMessage <ConnectionResponseMessage>(), rec);
            }
        }
        public async Task <GetWalletResponse> Handle
        (
            GetWalletRequest aGetWalletRequest,
            CancellationToken aCancellationToken
        )
        {
            Wallet wallet =
                await WalletService.GetWalletAsync(AgentOptions.WalletConfiguration, AgentOptions.WalletCredentials);

            ProvisioningRecord provisioningRecord = await ProvisioningService.GetProvisioningAsync(wallet);

            var getWalletResponse = new GetWalletResponse(aGetWalletRequest.CorrelationId, provisioningRecord);

            return(getWalletResponse);
        }
Example #6
0
        public async Task InitializeAgentInfo()
        {
            var context = await _agentContextProvider.GetContextAsync();

            _provisioningRecord = await _provisioningService.GetProvisioningAsync(context.Wallet);

            AgentName           = _provisioningRecord.Owner.Name;
            AgentImageSource    = Base64StringToImageSource.Base64StringToImage(_provisioningRecord.Owner.ImageUrl);
            MediatorEndpointUrl = _provisioningRecord.Endpoint.Uri;
            if (Preferences.ContainsKey(AppConstant.MediatorConnectionIdTagName))
            {
                var mediatorConnection = await _walletRecordService.GetAsync <ConnectionRecord>(context.Wallet, Preferences.Get(AppConstant.MediatorConnectionIdTagName, string.Empty));

                MediatorConnectionState = mediatorConnection.State.ToString();
            }
        }
        /// <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);
            }
        }
Example #8
0
        /// <inheritdoc />
        public virtual async Task <(EphemeralChallengeMessage, EphemeralChallengeRecord)> CreateChallengeAsync(IAgentContext agentContext,
                                                                                                               string challengeConfigId)
        {
            var config = await GetChallengeConfigAsync(agentContext, challengeConfigId);

            EphemeralChallengeRecord challengeRecord = new EphemeralChallengeRecord
            {
                Id = Guid.NewGuid().ToString()
            };
            EphemeralChallengeMessage challengeMessage = new EphemeralChallengeMessage();

            var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet);

            challengeMessage.ChallengerName     = provisioning.Owner?.Name;
            challengeMessage.ChallengerImageUrl = provisioning.Owner?.ImageUrl;

            challengeMessage.ServiceEndpoint = provisioning.Endpoint.Uri;
            challengeMessage.RecipientKeys   = new[] { provisioning.Endpoint.Verkey };

            if (config.Type == ChallengeType.Proof)
            {
                var proofRequestConfig = config.Contents.ToObject <ProofRequestConfiguration>();
                (var proofRequest, var _) = await ProofService.CreateProofRequestAsync(agentContext, new ProofRequest
                {
                    Name                = config.Name,
                    Version             = "1.0",
                    Nonce               = $"0{Guid.NewGuid().ToString("N")}",
                    RequestedAttributes = proofRequestConfig.RequestedAttributes,
                    RequestedPredicates = proofRequestConfig.RequestedPredicates,
                    NonRevoked          = proofRequestConfig.NonRevoked
                });

                challengeRecord.Challenge = new EphemeralChallengeContents
                {
                    Type     = ChallengeType.Proof,
                    Contents = JsonConvert.DeserializeObject <JObject>(proofRequest.ProofRequestJson)
                };
                challengeMessage.Challenge = challengeRecord.Challenge;
            }

            challengeRecord.SetTag(TagConstants.Role, TagConstants.Requestor);
            challengeRecord.SetTag(TagConstants.LastThreadId, challengeMessage.Id);
            await RecordService.AddAsync(agentContext.Wallet, challengeRecord);

            return(challengeMessage,
                   challengeRecord);
        }
Example #9
0
        private async void AcceptTxnAuthorAgreement()
        {
            var context = await _agentProvider.GetContextAsync(nameof(TxnAuthorAcceptanceService));

            var taa = await _poolService.GetTaaAsync(_agentOptions.PoolName);

            if (taa != null)
            {
                var digest       = GetDigest(taa);
                var provisioning = await _provisioningService.GetProvisioningAsync(context.Wallet);

                if (provisioning.TaaAcceptance == null || provisioning.TaaAcceptance.Digest != digest)
                {
                    await _provisioningService.AcceptTxnAuthorAgreementAsync(context, taa);
                }
            }
        }
        private async Task CreateConnection(IAgentContext context, ConnectionInvitationMessage invite)
        {
            var provisioningRecord = await _provisioningService.GetProvisioningAsync(context.Wallet);

            var isEndpointUriAbsent = provisioningRecord.Endpoint.Uri == null;

            var(msg, rec) = await _connectionService.CreateRequestAsync(context, _invite);

            //await _edgeClientService.AddRouteAsync(context, rec.MyVk);

            //var rsp = await _messageService.SendReceiveAsync<ConnectionResponseMessage>(context.Wallet, msg, rec);
            //if (isEndpointUriAbsent)
            //{
            //    await _connectionService.ProcessResponseAsync(context, rsp, rec);
            //}
            await _messageService.SendAsync(context.Wallet, msg, rec);
        }
        public async Task ProvisionAsync(AgentOptions options, CancellationToken cancellationToken = default)
        {
            var discovery = await edgeClientService.DiscoverConfigurationAsync(options.EndpointUri);

            try
            {
                options.AgentKey    = discovery.RoutingKey;
                options.EndpointUri = discovery.ServiceEndpoint;

                await provisioningService.ProvisionAgentAsync(options);
            }
            catch (WalletStorageException)
            {
                // OK
            }
            catch (WalletExistsException)
            {
                // OK
            }
            var agentContext = await agentProvider.GetContextAsync();

            var provisioning = await provisioningService.GetProvisioningAsync(agentContext.Wallet);

            // Check if connection has been established with mediator agent
            if (provisioning.GetTag(MediatorConnectionIdTagName) == null)
            {
                var(request, record) = await connectionService.CreateRequestAsync(agentContext, discovery.Invitation);

                var response = await messageService.SendReceiveAsync <ConnectionResponseMessage>(agentContext, request, record);

                await connectionService.ProcessResponseAsync(agentContext, response, record);

                // Remove the routing key explicitly as it won't ever be needed.
                // Messages will always be sent directly with return routing enabled
                record = await connectionService.GetAsync(agentContext, record.Id);

                record.Endpoint = new AgentEndpoint(record.Endpoint.Uri, null, null);
                await recordService.UpdateAsync(agentContext.Wallet, record);

                provisioning.SetTag(MediatorConnectionIdTagName, record.Id);
                await recordService.UpdateAsync(agentContext.Wallet, provisioning);
            }

            await edgeClientService.CreateInboxAsync(agentContext, options.MetaData);
        }
Example #12
0
        public async Task <IActionResult> CreateInvitation()
        {
            var wallet = await _walletService.GetWalletAsync(_walletOptions.WalletConfiguration, _walletOptions.WalletCredentials);

            var provisioning = await _provisioningService.GetProvisioningAsync(wallet);

            var invitation = await _connectionService.CreateInvitationAsync(wallet,
                                                                            new DefaultCreateInviteConfiguration
            {
                AutoAcceptConnection = true,
                MyAlias = new ConnectionAlias {
                    Name = provisioning.Owner.Name
                }
            });

            ViewData["Invitation"] = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(invitation)));
            return(View());
        }
        /// <inheritdoc />
        public async Task <string> SignRequestAsync(IAgentContext context, string submitterDid, string requestJson)
        {
            try
            {
                var provisioning = await provisioningService.GetProvisioningAsync(context.Wallet);

                if (provisioning?.TaaAcceptance != null)
                {
                    requestJson = await IndyLedger.AppendTxnAuthorAgreementAcceptanceToRequestAsync(requestJson, provisioning.TaaAcceptance.Text,
                                                                                                    provisioning.TaaAcceptance.Version, provisioning.TaaAcceptance.Digest, provisioning.TaaAcceptance.AcceptanceMechanism, (ulong)DateTimeOffset.Now.ToUnixTimeSeconds());
                }
            }
            catch (AriesFrameworkException ex) when(ex.ErrorCode == ErrorCode.RecordNotFound)
            {
                // OK, used in unit tests and scenarios when we want to simply send ledger commands
            }
            return(await SignRequestAsync(context.Wallet, submitterDid, requestJson));
        }
Example #14
0
        /// <inheritdoc />
        public virtual async Task AcceptOfferAsync(Wallet wallet, Pool pool, string credentialId,
                                                   Dictionary <string, string> attributeValues = null)
        {
            var credential = await RecordService.GetAsync <CredentialRecord>(wallet, credentialId);

            var connection = await ConnectionService.GetAsync(wallet, credential.ConnectionId);

            var definition =
                await LedgerService.LookupDefinitionAsync(pool, connection.MyDid, credential.CredentialDefinitionId);

            var provisioning = await ProvisioningService.GetProvisioningAsync(wallet);

            var request = await AnonCreds.ProverCreateCredentialReqAsync(wallet, connection.MyDid, credential.OfferJson,
                                                                         definition.ObjectJson, provisioning.MasterSecretId);

            // Update local credential record with new info
            credential.CredentialRequestMetadataJson = request.CredentialRequestMetadataJson;

            var details = new CredentialRequestDetails
            {
                OfferJson             = credential.OfferJson,
                CredentialRequestJson = request.CredentialRequestJson,
                CredentialValuesJson  = CredentialUtils.FormatCredentialValues(attributeValues)
            };

            var requestMessage =
                await MessageSerializer.PackSealedAsync <CredentialRequestMessage>(details, wallet, connection.MyVk,
                                                                                   connection.TheirVk);

            requestMessage.Type =
                MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.CredentialRequest);

            await credential.TriggerAsync(CredentialTrigger.Request);

            await RecordService.UpdateAsync(wallet, credential);

            //TODO we need roll back, i.e if we fail to send the A2A message the credential record should revert to Offer phase
            //so the user can resend
            await RouterService.ForwardAsync(new ForwardEnvelopeMessage
            {
                Content = requestMessage.ToJson(),
                Type    = MessageUtils.FormatDidMessageType(connection.TheirDid, MessageTypes.Forward)
            }, connection.Endpoint);
        }
        public async Task OnGetAsync()
        {
            var context = await _agentContextProvider.GetContextAsync();

            var provisioning = await _provisioningService.GetProvisioningAsync(context.Wallet);

            var config = new InviteConfiguration {
                AutoAcceptConnection = true,
                MyAlias = new ConnectionAlias {
                    Name = provisioning.Owner.Name, ImageUrl = provisioning.Owner.ImageUrl
                }
            };

            var(invitation, connectionRecord) = await _connectionService.CreateInvitationAsync(context, config);

            Invitation = $"{provisioning.Endpoint.Uri}?c_i={invitation.ToJson().ToBase64()}";

            QRCode = $"https://chart.googleapis.com/chart?cht=qr&chs=300x300&chld=L|0&chl={Uri.EscapeDataString(Invitation)}";
        }
Example #16
0
        private async Task <DialogTurnResult> CreateInvitationAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var state = await _accessors.AgentState.GetAsync(stepContext.Context, () => new AgentState(), cancellationToken);

            if (state.WalletId == null)
            {
                await stepContext.Context.SendActivityAsync("Sorry, I couldn't find information about your agent");

                return(await stepContext.EndDialogAsync());
            }
            await stepContext.Context.SendTypingAsync();

            var context = await _contextProvider.GetContextAsync(state.WalletId);

            var provisioning = await _provisioningService.GetProvisioningAsync(context.Wallet);

            var(invitation, record) = await _connectionService.CreateInvitationAsync(context,
                                                                                     new InviteConfiguration { AutoAcceptConnection = true });

            var invitationDetails = $"{provisioning.Endpoint.Uri}?c_i={invitation.ToByteArray().ToBase64String()}";

            var reply = stepContext.Context.Activity.CreateReply("Here are the invitation details");

            reply.Attachments = new List <Attachment>
            {
                new HeroCard
                {
                    Images = new List <CardImage>
                    {
                        new CardImage {
                            Url = $"https://chart.googleapis.com/chart?cht=qr&chs=300x300&chld=M|0&chl={Uri.EscapeDataString(invitationDetails)}"
                        }
                    }
                }.ToAttachment()
            };

            await stepContext.Context.SendActivityAsync(reply);

            await stepContext.Context.SendActivityAsync(invitationDetails);

            return(await stepContext.NextAsync(record.Id));
        }
        /// <inheritdoc />
        public virtual async Task <string> CreateProofAsync(IAgentContext agentContext,
                                                            ProofRequest proofRequest, RequestedCredentials requestedCredentials)
        {
            var provisioningRecord = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet);

            var credentialObjects = new List <CredentialInfo>();

            foreach (var credId in requestedCredentials.GetCredentialIdentifiers())
            {
                var credentialInfo = JsonConvert.DeserializeObject <CredentialInfo>(
                    await AnonCreds.ProverGetCredentialAsync(agentContext.Wallet, credId));

                credentialObjects.Add(credentialInfo);
            }

            var schemas = await BuildSchemasAsync(
                agentContext : agentContext,
                schemaIds : credentialObjects.Select(x => x.SchemaId).Distinct());

            var definitions = await BuildCredentialDefinitionsAsync(
                agentContext : agentContext,
                credentialDefIds : credentialObjects.Select(x => x.CredentialDefinitionId).Distinct());

            var revocationStates = await BuildRevocationStatesAsync(
                agentContext : agentContext,
                credentialObjects : credentialObjects,
                proofRequest : proofRequest,
                requestedCredentials : requestedCredentials);

            var proofJson = await AnonCreds.ProverCreateProofAsync(
                wallet : agentContext.Wallet,
                proofRequest : proofRequest.ToJson(),
                requestedCredentials : requestedCredentials.ToJson(),
                masterSecret : provisioningRecord.MasterSecretId,
                schemas : schemas,
                credentialDefs : definitions,
                revStates : revocationStates);

            return(proofJson);
        }
        /// <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);
        }
Example #19
0
        public async Task StartAsync(CancellationToken cancellationToken)
        {
            try
            {
                await provisioningService.ProvisionAgentAsync();
            }
            catch (WalletStorageException)
            {
                // OK
            }
            catch (WalletExistsException)
            {
                // OK
            }

            var agentContext = await agentProvider.GetContextAsync();

            var provsioningRecord = await provisioningService.GetProvisioningAsync(agentContext.Wallet);

            if (provsioningRecord.GetTag(EdgeInvitationTagName) != null)
            {
                return;
            }

            var(invitation, record) = await connectionService.CreateInvitationAsync(
                agentContext : agentContext,
                config : new InviteConfiguration {
                MultiPartyInvitation = true, AutoAcceptConnection = true
            });

            invitation.RoutingKeys = null;

            record.SetTag(InvitationTagName, invitation.ToJson());
            provsioningRecord.SetTag(EdgeInvitationTagName, record.Id);
            await recordService.UpdateAsync(agentContext.Wallet, provsioningRecord);

            await recordService.UpdateAsync(agentContext.Wallet, record);
        }
Example #20
0
        public async Task <IActionResult> CreateCredentialDefinitionAsync(OperationBody body)
        {
            var context = await _agentContextProvider.GetContextAsync();

            var issuer = await _provisionService.GetProvisioningAsync(context.Wallet);

            var credentialDefinition = body.Data;
            var schemaId             = (string)credentialDefinition["schema_id"];
            var tag = (string)credentialDefinition["tag"];
            var supportRevocation = (bool)credentialDefinition["support_revocation"];

            // Needed to construct credential definition id
            var schema        = JObject.Parse(await _schemaService.LookupSchemaAsync(context, schemaId));
            var schemaSeqNo   = (string)schema["seqNo"];
            var signatureType = "CL"; // TODO: can we make this variable?

            // The test client sends multiple create credential definition requests with
            // the same parameters. First check whether the credential definition already exists.
            var credentialDefinitionId     = $"{issuer.IssuerDid}:3:{signatureType}:{schemaSeqNo}:{tag}";
            var credentialDefinitionString = await this.LookupCredentialDefinitionByIdAsync(credentialDefinitionId);

            // If the credential defintion doesn't already exists, create it
            if (credentialDefinitionString == null)
            {
                await _schemaService.CreateCredentialDefinitionAsync(context, new CredentialDefinitionConfiguration
                {
                    SchemaId         = schemaId,
                    Tag              = tag,
                    EnableRevocation = supportRevocation,
                    IssuerDid        = issuer.IssuerDid
                });
            }

            return(Ok(new
            {
                credential_definition_id = credentialDefinitionId
            }));
        }
Example #21
0
        private async Task <bool> CreateConnection(IAgentContext context, ConnectionInvitationMessage invite)
        {
            var provisioningRecord = await _provisioningService.GetProvisioningAsync(context.Wallet);

            if (provisioningRecord.Endpoint.Uri != null)
            {
                try
                {
                    var(msg, rec) = await _connectionService.CreateRequestAsync(context, _invite);

                    await _messageService.SendAsync(context.Wallet, msg, rec, _invite.RecipientKeys.First());

                    return(true);
                }
                catch (Exception) //TODO more granular error protection
                {
                    return(false);
                }
            }
            else
            {
                try
                {
                    var(msg, rec) = await _connectionService.CreateRequestAsync(context, _invite);

                    var rsp = await _messageService.SendAsync(context.Wallet, msg, rec, _invite.RecipientKeys.First(), true);

                    await _connectionService.ProcessResponseAsync(context, rsp.GetMessage <ConnectionResponseMessage>(), rec);

                    return(true);
                }
                catch (Exception) //TODO more granular error protection
                {
                    return(false);
                }
            }
        }
Example #22
0
        public async Task <AgentPublicConfiguration> GetConfigurationAsync()
        {
            var agentContext = await agentProvider.GetContextAsync();

            var provisioningRecord = await provisioningService.GetProvisioningAsync(agentContext.Wallet);

            var connectionId = provisioningRecord.GetTag(MediatorProvisioningService.EdgeInvitationTagName);

            if (connectionId == null)
            {
                throw new Exception("This agent hasn't been provisioned as mediator agent");
            }
            var inviation = await connectionService.GetAsync(agentContext, connectionId);

            var agentConfiguration = new AgentPublicConfiguration
            {
                ServiceEndpoint = provisioningRecord.Endpoint.Uri,
                RoutingKey      = provisioningRecord.Endpoint.Verkey.First(),
                Invitation      = inviation.GetTag(MediatorProvisioningService.InvitationTagName)
                                  .ToObject <ConnectionInvitationMessage>()
            };

            return(agentConfiguration);
        }
        public async Task <CreateInvitationResponse> Handle
        (
            CreateInvitationRequest aCreateInvitationRequest,
            CancellationToken aCancellationToken
        )
        {
            IAgentContext agentContext = await AgentProvider.GetContextAsync();

            (ConnectionInvitationMessage connectionInvitationMessage, ConnectionRecord connectionRecord) =
                await ConnectionService.CreateInvitationAsync(agentContext, aCreateInvitationRequest.InviteConfiguration);

            string endpointUri       = (await ProvisioningService.GetProvisioningAsync(agentContext.Wallet)).Endpoint.Uri;
            string encodedInvitation = connectionInvitationMessage.ToJson().ToBase64();
            var    response          =
                new CreateInvitationResponse
                (
                    aCreateInvitationRequest.CorrelationId,
                    connectionInvitationMessage,
                    connectionRecord,
                    aInvitationUrl: $"{endpointUri}?c_i={encodedInvitation}"
                );

            return(response);
        }
Example #24
0
        public async Task <CreateSchemaResponse> Handle
        (
            CreateSchemaRequest aCreateSchemaRequest,
            CancellationToken aCancellationToken
        )
        {
            IAgentContext agentContext = await AgentProvider.GetContextAsync();

            ProvisioningRecord issuerProvisioningRecord = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet);

            string schemaId =
                await SchemaService.CreateSchemaAsync
                (
                    agentContext,
                    issuerDid : issuerProvisioningRecord.IssuerDid,
                    aCreateSchemaRequest.Name,
                    aCreateSchemaRequest.Version,
                    aCreateSchemaRequest.AttributeNames.ToArray()
                );

            var response = new CreateSchemaResponse(aCreateSchemaRequest.CorrelationId, schemaId);

            return(response);
        }
Example #25
0
        private async Task CreateConnection(IAgentContext context, ConnectionInvitationMessage invite)
        {
            var provisioningRecord = await _provisioningService.GetProvisioningAsync(context.Wallet);

            var isEndpointUriAbsent = provisioningRecord.Endpoint.Uri == null;

            var(msg, connection) = await _connectionService.CreateRequestAsync(context, invite);

            msg.Label = msg.Label == null ? "OsmaAgent" : msg.Label;

            var recipientKey = invite.RecipientKeys.First()
                               ?? connection.TheirVk
                               ?? throw new AriesFrameworkException(
                                         ErrorCode.A2AMessageTransmissionError, "Cannot find encryption key");

            var routingKeys = connection.Endpoint?.Verkey != null ? new[] { connection.Endpoint.Verkey } : new string[0];

            if (connection.Endpoint?.Uri == null)
            {
                throw new AriesFrameworkException(ErrorCode.A2AMessageTransmissionError, "Cannot send to connection that does not have endpoint information specified");
            }


            if (isEndpointUriAbsent)
            {
                var rsp = await _messageService.SendReceiveAsync(context.Wallet, msg, recipientKey, connection.Endpoint.Uri, routingKeys, connection.MyVk);

                var unpackedRsp = (UnpackedMessageContext)rsp;

                await _connectionService.ProcessResponseAsync(context, unpackedRsp.GetMessage <ConnectionResponseMessage>(), connection);
            }
            else
            {
                await _messageService.SendAsync(context.Wallet, msg, recipientKey, connection.Endpoint.Uri, routingKeys, connection.MyVk);
            }
        }
Example #26
0
        /// <inheritdoc />
        public virtual async Task <ConnectionInvitationMessage> CreateInvitationAsync(Wallet wallet,
                                                                                      DefaultCreateInviteConfiguration config = null)
        {
            var connectionId = !string.IsNullOrEmpty(config?.ConnectionId)
                ? config.ConnectionId
                : Guid.NewGuid().ToString();

            Logger.LogInformation(LoggingEvents.CreateInvitation, "ConnectionId {0}", connectionId);

            var connectionKey = await Crypto.CreateKeyAsync(wallet, "{}");

            var connection = new ConnectionRecord();

            connection.ConnectionId = connectionId;
            connection.Tags.Add(TagConstants.ConnectionKey, connectionKey);

            if (config != null && config.AutoAcceptConnection)
            {
                connection.Tags.Add(TagConstants.AutoAcceptConnection, "true");
            }

            if (config?.TheirAlias != null)
            {
                connection.Alias = config.TheirAlias;
                if (!string.IsNullOrEmpty(config.TheirAlias.Name))
                {
                    connection.Tags.Add(TagConstants.Alias, config.TheirAlias.Name);
                }
            }

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

            await RecordService.AddAsync(wallet, connection);

            var provisioning = await ProvisioningService.GetProvisioningAsync(wallet);

            var invite = new ConnectionInvitationMessage
            {
                Endpoint      = provisioning.Endpoint,
                ConnectionKey = connectionKey
            };

            if (!string.IsNullOrEmpty(provisioning.Owner?.Name))
            {
                invite.Name = provisioning.Owner.Name;
            }
            if (!string.IsNullOrEmpty(provisioning.Owner?.ImageUrl))
            {
                invite.ImageUrl = provisioning.Owner.ImageUrl;
            }

            if (!string.IsNullOrEmpty(config?.MyAlias?.Name))
            {
                invite.Name = config.MyAlias.Name;
            }
            if (!string.IsNullOrEmpty(config?.MyAlias?.ImageUrl))
            {
                invite.ImageUrl = config.MyAlias.ImageUrl;
            }

            return(invite);
        }
        /// <inheritdoc />
        public virtual async Task <(ConnectionInvitationMessage, ConnectionRecord)> CreateInvitationAsync(IAgentContext agentContext,
                                                                                                          InviteConfiguration config = null)
        {
            config = config ?? new InviteConfiguration();
            var connection = new ConnectionRecord {
                Role = ConnectionRole.Inviter
            };

            connection.Id = config.ConnectionId ?? connection.Id;

            Logger.LogInformation(LoggingEvents.CreateInvitation, "ConnectionId {0}", connection.Id);

            var connectionKey = await Crypto.CreateKeyAsync(agentContext.Wallet, "{}");

            connection.SetTag(TagConstants.ConnectionKey, connectionKey);

            if (config.AutoAcceptConnection)
            {
                connection.SetTag(TagConstants.AutoAcceptConnection, "true");
            }

            connection.MultiPartyInvitation = config.MultiPartyInvitation;

            if (!config.MultiPartyInvitation)
            {
                connection.Alias = config.TheirAlias;
                if (!string.IsNullOrEmpty(config.TheirAlias.Name))
                {
                    connection.SetTag(TagConstants.Alias, config.TheirAlias.Name);
                }
            }

            foreach (var tag in config.Tags)
            {
                connection.SetTag(tag.Key, tag.Value);
            }

            var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet);

            if (string.IsNullOrEmpty(provisioning.Endpoint.Uri))
            {
                throw new AriesFrameworkException(ErrorCode.RecordInInvalidState, "Provision record has no endpoint information specified");
            }

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

            IList <string> routingKeys = null;

            if (provisioning.Endpoint.Verkey != null)
            {
                routingKeys = (config.UseDidKeyFormat
                    ? provisioning.Endpoint.Verkey
                               .Where(DidUtils.IsFullVerkey)
                               .Select(DidUtils.ConvertVerkeyToDidKey)
                    : provisioning.Endpoint.Verkey).ToList();
            }
            string recipientKey = config.UseDidKeyFormat ? DidUtils.ConvertVerkeyToDidKey(connectionKey) : connectionKey;

            return(new ConnectionInvitationMessage(agentContext.UseMessageTypesHttps)
            {
                ServiceEndpoint = provisioning.Endpoint.Uri,
                RoutingKeys = routingKeys,
                RecipientKeys = new[] { recipientKey },
                Label = config.MyAlias.Name ?? provisioning.Owner.Name,
                ImageUrl = config.MyAlias.ImageUrl ?? provisioning.Owner.ImageUrl
            }, connection);
        }
        public async Task <IActionResult> SendCredentialOfferAsync(OperationBody body)
        {
            var context = await _agentContextProvider.GetContextAsync();

            var issuer = await _provisionService.GetProvisioningAsync(context.Wallet);

            var threadId = body.Id;

            string connectionId;
            TestHarnessCredentialExchange THCredentialExchange;
            CredentialOfferMessage        credentialOffer;
            CredentialRecord credentialRecord;

            // Adding a delay here. It seems that with the removal of the state checks in the tests,
            // Some agents are not yet in the appropriate state for this call.
            // TODO There may be a better way to do this but adding the wait is a quick fix to get the tests
            // running again.
            await Task.Delay(5000);

            // Send offer in response to proposal
            if (threadId != null)
            {
                THCredentialExchange = _credentialCache.Get <TestHarnessCredentialExchange>(threadId);

                credentialRecord = await _credentialService.GetAsync(context, THCredentialExchange.RecordId);

                connectionId = credentialRecord.ConnectionId;

                var offerJson = await AnonCreds.IssuerCreateCredentialOfferAsync(context.Wallet, credentialRecord.CredentialDefinitionId);

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

                // Update credential record
                credentialRecord.SchemaId  = schemaId;
                credentialRecord.OfferJson = offerJson;
                credentialRecord.State     = CredentialState.Offered;
                credentialRecord.SetTag(TagConstants.IssuerDid, issuer.IssuerDid);
                await _recordService.UpdateAsync(context.Wallet, credentialRecord);

                credentialOffer = new CredentialOfferMessage
                {
                    CredentialPreview = new CredentialPreviewMessage
                    {
                        Attributes = CleanCredentialPreviewAttributes(credentialRecord.CredentialAttributesValues.ToArray())
                    },
                    Comment = "credential-offer", // ACA-Py requires comment
                    Offers  = new Attachment[]
                    {
                        new Attachment
                        {
                            Id       = "libindy-cred-offer-0",
                            MimeType = CredentialMimeTypes.ApplicationJsonMimeType,
                            Data     = new AttachmentContent
                            {
                                Base64 = offerJson.GetUTF8Bytes().ToBase64String()
                            }
                        }
                    }
                };

                credentialOffer.ThreadFrom(threadId);

                THCredentialExchange.State = TestHarnessCredentialExchangeState.OfferSent;
            }
            // Send Offer to start credential issuance flow
            else
            {
                var offer = body.Data;
                connectionId = (string)offer["connection_id"];
                var credentialPreview      = offer["credential_preview"].ToObject <CustomCredentialPreviewMessage>();
                var credentialDefinitionId = (string)offer["cred_def_id"];

                credentialPreview.Attributes = CleanCredentialPreviewAttributes(credentialPreview.Attributes);

                (credentialOffer, credentialRecord) = await _credentialService.CreateOfferAsync(context, new OfferConfiguration
                {
                    CredentialAttributeValues = credentialPreview.Attributes,
                    CredentialDefinitionId    = credentialDefinitionId,
                    IssuerDid = issuer.IssuerDid
                }, connectionId);

                THCredentialExchange = new TestHarnessCredentialExchange
                {
                    RecordId = credentialRecord.Id,
                    ThreadId = credentialRecord.GetTag(TagConstants.LastThreadId),
                    State    = TestHarnessCredentialExchangeState.OfferSent
                };
                _credentialCache.Set(THCredentialExchange.ThreadId, THCredentialExchange);
            }

            var connection = await _connectionService.GetAsync(context, connectionId);

            // Listen for credential request to update the state
            UpdateStateOnMessage(THCredentialExchange, TestHarnessCredentialExchangeState.RequestReceived, _ => new[] { MessageTypes.IssueCredentialNames.RequestCredential, MessageTypesHttps.IssueCredentialNames.RequestCredential, }.Contains(_.MessageType) && _.ThreadId == THCredentialExchange.ThreadId);

            await _messageService.SendAsync(context, credentialOffer, connection);

            return(Ok(THCredentialExchange));
        }
        /// <inheritdoc />
        public virtual async Task <(ConnectionInvitationMessage, ConnectionRecord)> CreateInvitationAsync(IAgentContext agentContext,
                                                                                                          InviteConfiguration config = null)
        {
            var connectionId = !string.IsNullOrEmpty(config?.ConnectionId)
                ? config.ConnectionId
                : Guid.NewGuid().ToString();

            config = config ?? new InviteConfiguration();

            Logger.LogInformation(LoggingEvents.CreateInvitation, "ConnectionId {0}", connectionId);

            var connectionKey = await Crypto.CreateKeyAsync(agentContext.Wallet, "{}");

            var connection = new ConnectionRecord {
                Id = connectionId
            };

            connection.SetTag(TagConstants.ConnectionKey, connectionKey);

            //if (config.AutoAcceptConnection)
            connection.SetTag(TagConstants.AutoAcceptConnection, "true");

            connection.MultiPartyInvitation = config.MultiPartyInvitation;

            if (!config.MultiPartyInvitation)
            {
                connection.Alias = config.TheirAlias;
                if (!string.IsNullOrEmpty(config.TheirAlias.Name))
                {
                    connection.SetTag(TagConstants.Alias, config.TheirAlias.Name);
                }
            }

            foreach (var tag in config.Tags)
            {
                connection.SetTag(tag.Key, tag.Value);
            }

            var provisioning = await ProvisioningService.GetProvisioningAsync(agentContext.Wallet);

            string uri = "";

            if (string.IsNullOrEmpty(provisioning.Endpoint.Uri))
            {
                var records = await CloudAgentRegistrationService.GetAllCloudAgentAsync(agentContext.Wallet);

                if (records.Count > 0)
                {
                    var record = CloudAgentRegistrationService.getRandomCloudAgent(records);
                    uri = record.Endpoint.ResponseEndpoint + "/" + record.MyConsumerId;
                }
                else
                {
                    throw new AgentFrameworkException(ErrorCode.RecordInInvalidState, "No Cloud Agent Registered");
                }
            }

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

            return(new ConnectionInvitationMessage
            {
                ServiceEndpoint = uri,
                RoutingKeys = null,        //provisioning.Endpoint.Verkey != null ? new[] {provisioning.Endpoint.Verkey} : null,
                RecipientKeys = new[] { connectionKey },
                Label = config.MyAlias.Name ?? provisioning.Owner.Name,
                ImageUrl = config.MyAlias.ImageUrl ?? provisioning.Owner.ImageUrl
            }, connection);
        }
        public async Task InvokeAsync(HttpContext context)
        {
            if (!context.Request.Method.Equals("POST", StringComparison.OrdinalIgnoreCase))
            {
                await _next(context);

                return;
            }

            var wallet = await _walletService.GetWalletAsync(_walletOptions.WalletConfiguration,
                                                             _walletOptions.WalletCredentials);

            var endpoint = await _provisioningService.GetProvisioningAsync(wallet);

            if (context.Request.ContentLength != null)
            {
                var body = new byte[(int)context.Request.ContentLength];

                await context.Request.Body.ReadAsync(body, 0, body.Length);

                var decrypted =
                    await _messageSerializer.UnpackAsync <IEnvelopeMessage>(body, wallet, endpoint.Endpoint.Verkey);

                var decoded = JsonConvert.DeserializeObject <IContentMessage>(decrypted.Content);

                switch (decoded)
                {
                case ConnectionRequestMessage request:
                    await _connectionService.ProcessRequestAsync(wallet, request);

                    break;

                case ConnectionResponseMessage response:
                    await _connectionService.ProcessResponseAsync(wallet, response);

                    break;

                case CredentialOfferMessage offer:
                    await _credentialService.ProcessOfferAsync(wallet, offer);

                    break;

                case CredentialRequestMessage request:
                    await _credentialService.ProcessCredentialRequestAsync(wallet, request);

                    break;

                case CredentialMessage credential:
                    var pool = await _poolService.GetPoolAsync(_poolOptions.PoolName, _poolOptions.ProtocolVersion);

                    await _credentialService.ProcessCredentialAsync(pool, wallet, credential);

                    break;

                case ProofMessage _:
                    break;
                }

                context.Response.StatusCode = 200;
                await context.Response.WriteAsync(string.Empty);

                return;
            }

            throw new Exception("Empty content length");
        }