/// <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); }
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()); }
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); }
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); } }
/// <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); }
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); }
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)); }
/// <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)}"; }
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); }
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); }
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 })); }
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); } } }
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); }
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); }
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); } }
/// <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"); }