Skip to content
This repository has been archived by the owner on Aug 25, 2019. It is now read-only.

Commit

Permalink
Documentation update (#88)
Browse files Browse the repository at this point in the history
* Provisioning and configuration docs

* More docs

* Update sample. Remove project references

* Add custom launch uri for invitation

* Code comments

* Updated documentation in quickstart
  • Loading branch information
tmarkovski authored Jan 15, 2019
1 parent 2253c36 commit f502667
Show file tree
Hide file tree
Showing 32 changed files with 581 additions and 195 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Agent Framework - .NET Core library for Sovrin agents
# Agent Framework

## .NET Core library for building Sovrin agents

[![Build Status](https://dev.azure.com/streetcred/Agent%20Framework/_apis/build/status/Agent%20Framework%20-%20Build?branchName=master)](https://dev.azure.com/streetcred/Agent%20Framework/_build/latest?definitionId=10?branchName=master)
[![Build Status](https://travis-ci.com/streetcred-id/agent-framework.svg?branch=master)](https://travis-ci.com/streetcred-id/agent-framework)
Expand All @@ -8,7 +10,7 @@ Agent Framework is a .NET Core library for building Sovrin interoperable agent s
It is an abstraction on top of Indy SDK that provides a set of API's for managing agent workflows.
The framework runs .NET Standard (2.0+), including ASP.NET Core and Xamarin.

## Documentation
### Documentation

- [Installation and configuration](https://agent-framework.readthedocs.io/en/latest/installation.html)
- [Agent Workflows](https://agent-framework.readthedocs.io/en/latest/quickstart.html)
Expand All @@ -17,7 +19,7 @@ The framework runs .NET Standard (2.0+), including ASP.NET Core and Xamarin.
- [Hosting agents in docker containers](https://agent-framework.readthedocs.io/en/latest/docker.html)
- [Samples and demos](https://agent-framework.readthedocs.io/en/latest/samples.html)

## A very quick demo
### A very quick demo

With [Docker](https://www.docker.com) installed, run

Expand Down
27 changes: 20 additions & 7 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@ Installation and configuration
Using NuGet
===========

To use the agent framework in your project, add the nuget packages.

.. code-block:: bash
Install-Package AgentFramework.Core -Source https://www.myget.org/F/agent-framework/api/v3/index.json
Available packages:

- ``AgentFramework.Core`` - core framework package
- ``AgentFramework.AspNetCore`` - simple middleware and service extensions to easily configure and run an agent
- ``AgentFramework.Core.Handlers`` - provides a framework for registering custom message handlers and extending the agent functionality


The framework will be moved to nuget.org soon. For the time being, stable and pre-release packages are available at ``https://www.myget.org/F/agent-framework/api/v3/index.json``.
You can add `nuget.config
Expand All @@ -29,28 +37,33 @@ Setting up development environment
==================================

Agent Framework uses Indy SDK wrapper for .NET which requires platform specific native libraries of libindy to be available in the running environment.
Check the [Indy SDK project page](https://github.com/hyperledger/indy-sdk) for details on installing libindy for different platforms or read the brief instructions below.
Check the `Indy SDK project page
<https://github.com/hyperledger/indy-sdk>`_ for details on installing libindy for different platforms or read the brief instructions below.

Make sure you have [.NET Core SDK](https://dotnet.microsoft.com/download) installed for your platform.
Make sure you have `.NET Core SDK
<https://dotnet.microsoft.com/download>`_ installed for your platform.

Windows
-------

You can download binaries of libindy and all dependencies from the [Sovrin repo](https://repo.sovrin.org/windows/libindy/). The dependcies are under `deps` folder and `libindy` under one of streams (rc, master, stable). There are two options to link the DLLs
You can download binaries of libindy and all dependencies from the `Sovrin repo
<https://repo.sovrin.org/windows/libindy/>`_. The dependcies are under ``deps`` folder and ``libindy`` under one of streams (rc, master, stable). There are two options to link the DLLs

- Unzip all files in a directory and add that to your PATH variable (recommended for development)
- Or copy all DLL files in the publish directory (recommended for published deployments)

More details at the [Indy documentation for setting up Windows environment](https://github.com/hyperledger/indy-sdk/blob/master/doc/windows-build.md)
More details at the `Indy documentation for setting up Windows environment
<https://github.com/hyperledger/indy-sdk/blob/master/doc/windows-build.md>`_.

MacOS
-----

Check `Setup Indy SDK build environment for MacOS
<https://github.com/hyperledger/indy-sdk/blob/master/doc/mac-build.md>`_
<https://github.com/hyperledger/indy-sdk/blob/master/doc/mac-build.md>`_.

Linux
-----

Build instructions for [Ubuntu based distros](https://github.com/hyperledger/indy-sdk/blob/master/doc/ubuntu-build.md) and [RHEL
based distros](https://github.com/hyperledger/indy-sdk/blob/master/doc/rhel-build.md).
Build instructions for `Ubuntu based distros
<https://github.com/hyperledger/indy-sdk/blob/master/doc/ubuntu-build.md>`_ and `RHEL based distros
<https://github.com/hyperledger/indy-sdk/blob/master/doc/rhel-build.md>`_.
189 changes: 186 additions & 3 deletions docs/quickstart.rst
Original file line number Diff line number Diff line change
@@ -1,24 +1,207 @@
******************************
Configuration and provisioning
******************************

Services overview
=================

- ``IProvisioningService`` - used to provision new agents and access the provisioning configuration that contains endpoint data, ownerhip info, service endpoints, etc.
- ``IConnectionService`` - manage connection records, create and accept invitations
- ``ICredentialService`` - manage credential records, create offer, issue, revoke and store credentials
- ``IProofService`` - send proof requests, provide and verify proofs
- ``IWalletRecordService`` - utility service used to manage custom application records that are stored in the wallet
- ``ISchemaService`` - create and manage schemas and credential definitions

Dependency injection
====================

When using ASP.NET Core, you can use the extension methods to configure the agent. This will add all required dependencies to the service provider.
Additionaly, the AgentFramework depends on the Logging extensions. These need to be added as well.

If using other tool, you will have to add each required service or message handler manually.

Example if using Autofac

.. code-block:: csharp
// .NET Core dependency collection
var services = new ServiceCollection();
services.AddLogging();
// Autofac builder
var builder = new ContainerBuilder();
// Register all required services
builder.RegisterAssemblyTypes(typeof(IProvisioningService).Assembly)
.Where(x => x.Namespace.StartsWith("AgentFramework.Core.Runtime",
StringComparison.InvariantCulture))
.AsImplementedInterfaces()
.SingleInstance();
// If using message handler package, you can add all handlers
builder.RegisterAssemblyTypes(typeof(IMessageHandler).Assembly)
.Where(x => x.IsClass && x is IMessageHandler)
.AsSelf()
.SingleInstance();
builder.Populate(services);
Check the `Xamarin Sample
<https://github.com/streetcred-id/agent-framework/blob/master/samples/xamarin-forms/AFMobileSample/App.xaml.cs>`_ for example registration.

Provisioning an Agent
=====================

The process of provisioning agents will create and configure an agent wallet and initialize the agent configuration.
The framework will generate a random Did and Verkey, unless you specify ``AgentSeed`` which is used if you need determinism.
Length of seed must be 32 characters.

.. code-block:: csharp
await _provisioningService.ProvisionAgentAsync(
new ProvisioningConfiguration
{
EndpointUri = "http://localhost:5000",
OwnerName = "My Agent"
});
Check the `ProvisioningConfiguration.cs
<https://github.com/streetcred-id/agent-framework/blob/master/src/AgentFramework.Core/Models/Wallets/ProvisioningConfiguration.cs>`_
for full configuration details. You can retrieve the generated details like agent Did and Verkey using

.. code-block:: csharp
var provisioning = await _provisioningService.GetProvisioningAsync(wallet);
Trust Anchor requirement
------------------------

If an agent is intended to act as an issuer, i.e. be able to issue credentials, their DID must be registered on the ledger with the `TRUST_ANCHOR` role.
Additionally, when provisioning the agent, set the ``ProvisioningConfiguration.CreateIssuer`` propety to true. If you already have a seed for creating the issuer DID
set the ``ProvisioningConfiguration.IssuerSeed`` to that value. Otherwise, a random DID will be generated. This DID must be added to the ledger as `TRUST_ANCHOR`.

.. tip:: If you are using the development indy node docker image, use ``000000000000000000000000Steward1`` as issuer seed. This will create a DID that has all required permissions.

***************
Agent Workflows
***************

Before you begin reading any of the topics below, please familiarize youself with the core idea behind Hyperledger Indy.
Before you begin reading any of the topics below, please familiarize youself with the core principles behind Hyperledger Indy.
We suggest that you go over the `Indy SDK Getting Started Guide
<https://github.com/hyperledger/indy-sdk/blob/master/doc/getting-started/getting-started.md>`_.

Roles and players
Models and states
=================

The framework abstracts the main workflows of Indy into a state machine model.
The following models and states are defined:

Connections
-----------

Represented with a ``ConnectionRecord``, this entity describes the pairwise relationship with another party.
The states for this record are:

- ``Invited`` - initially, when creating invitations to connect, the record will be set to this state.
- ``Negotating`` - set after accepting an invitation and sending a request to connect
- ``Connected`` - set when both parties have acknowledged the connection and have a pairwise record of each others DID's

Credentials
-----------

Represented wih a ``CredentialRecord``, this entity holds a reference to issued credential.
While only the party to whom this credential was issued will have the actual credential in their wallet, both the issuer and the holder will
have a CredentialRecord with the associated status for their reference. Credential states:

- ``Offered`` - initial state, when an offer is sent to the holder
- ``Requested`` - the holder has sent a credential request to the issuer
- ``Issued`` - the issuer accepted the credential request and issued a credential
- ``Rejected`` - the issuer rejected the credential request
- ``Revoked`` - the issuer revoked a previously issued credential

Proofs
------

Represented with a ``ProofRecord``, this entity references a proof flow between the holder and verifier. The ``ProofRecord`` contains
information about the proof request as well as the disclosed proof by the holder. Proof states:

- ``Requested`` - initial state when the verifier sends a proof request
- ``Accepted`` - the holder has provided a proof
- ``Rejected`` - the holder rejected providing proof for the request

Schemas and definitions
=======================

Before an issuer can create credentials, they need to register a credential definition for them on the ledger.
Credential definition requires a schema, which can also be registered by the same issuer or it can already be
present on the ledger.

.. code-block:: csharp
// creates new schema and registers the schema on the ledger
var schemaId = await _schemaService.CreateSchemaAsync(
_pool, _wallet, "My-Schema", "1.0", new[] { "FirstName", "LastName", "Email" });
// to lookup an existing schema on the ledger
var schemaJson = await _schemaService.LookupSchemaAsync(_pool, schemaId);
Once a ``schemaId`` has been established, an issuer can send their credential definition on the ledger.

.. code-block:: csharp
var definitionId = await _schemaService.CreateCredentialDefinitionAsync(_pool, _wallet,
schemaId, supportsRevocation: true, maxCredentialCount: 100);
The above code will create ``SchemaRecord`` and ``DefinitionRecord`` in the issuer wallet that can be looked up using the
``ISchemaService``.

.. warning:: Creating schemas and definition requires an issuer. See the `Trust Anchor requirement`_ above.

To retrieve all schemas or definitions registered with this agent, use:

.. code-block:: csharp
var schemas = await _schemaService.ListSchemasAsync(_wallet);
var definitions = await _schemaService.ListCredentialDefinitionsAsync(_wallet);
// To get a single record
var definition = await _schemaService.GetCredentialDefinitionAsync(wallet, definitionId);
Establishing secure connection
==============================

Before two parties can exchange agent messages, a secure connection must be established between them. The agent connection workflow defines this handshake process by exchanging a connection request/response message.

Sending invitations
-------------------

Connection invitations are exchanged over a previously established trusted protocol such as email, QR code, deep link, etc. When Alice wants to establish a connection to Bob, she can create an invitation:

.. code-block:: csharp
// Alice creates an invitation
var invitation = await connectionService.CreateInvitationAsync(aliceWallet);
She sends this invitation to Bob using the above described methods.

Negotating connection
---------------------

Credential issuence
Once Bob received the invitation from Alice, they can accept that invitation and initiate the negotiation process

.. code-block:: csharp
// Bob accepts invitation and sends a message request
await connectionService.AcceptInvitationAsync(bobWallet, invitation);
If you are using the default message handlers, no other step in needed - connection between Alice and Bob has been established. Use ``IConnectionService.ListAsync`` to fetch the connection records.
Established connections will have the ``State`` property set to ``Connected``.

.. tip:: If you decide to use custom handlers and want more control over the negotiation process, the connection service provides methods to work with the connections message flows, such as processing and accepting requests/responses.
A full step by step code is available in the `unit tests project
<https://github.com/streetcred-id/agent-framework/blob/master/test/AgentFramework.Core.Tests/Scenarios.cs>`_ in ``EstablishConnectionAsync``.

Credential issuance
===================

Issuing credential
Expand Down
8 changes: 8 additions & 0 deletions samples/aspnetcore/Controllers/ConnectionsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ public async Task<IActionResult> Details(string id)
[HttpPost]
public async Task<IActionResult> SendMessage(string connectionId, string text)
{
if (string.IsNullOrEmpty(text)) return RedirectToAction("Details", new { id = connectionId });

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

var messageRecord = new PrivateMessageRecord
Expand All @@ -116,6 +118,12 @@ public async Task<IActionResult> SendMessage(string connectionId, string text)
return RedirectToAction("Details", new {id = connectionId});
}

[HttpPost]
public IActionResult LaunchApp(LaunchAppViewModel model)
{
return Redirect($"{model.UriSchema}{Uri.EscapeDataString(model.InvitationDetails)}");
}

/// <summary>
/// Encodes the invitation to a base64 string which can be presented to the user as QR code or a deep link Url
/// </summary>
Expand Down
10 changes: 10 additions & 0 deletions samples/aspnetcore/Models/LaunchAppViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System;
namespace WebAgent.Models
{
public class LaunchAppViewModel
{
public string UriSchema { get; set; }

public string InvitationDetails { get; set; }
}
}
6 changes: 0 additions & 6 deletions samples/aspnetcore/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,9 @@
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"AF_OWNER_NAME": "Local Joe",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5000/"
},
"Docker": {
"commandName": "Docker",
"launchBrowser": true,
"launchUrl": "{Scheme}://localhost:{ServicePort}"
}
}
}
44 changes: 24 additions & 20 deletions samples/aspnetcore/Views/Connections/CreateInvitation.cshtml
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
<h1>
Create Invitation
</h1>
<p>
Copy the connection invitation details
</p>
<hr />
<div class="row">
<div class="col-md-8">
<form class="form-inline">
<div class="form-group">
<label class="sr-only" for="exampleInputAmount">Invitation Details</label>
<div class="input-group">
<input type="text" class="form-control" readonly="readonly" id="exampleInputAmount" placeholder="Amount" value="@ViewData["Invitation"]" />
</div>
</div>
<button class="btn btn-primary" onclick="copyToCliboard(document.getElementById('exampleInputAmount')); return false;">Copy to Clipboard</button>
</form>
</div>
</div>
@{
var invitation = (string)ViewData["Invitation"];
var qrUri = $"https://chart.googleapis.com/chart?cht=qr&chs=300x300&chld=L|0&chl={Uri.EscapeDataString(invitation)}";
}

<div class="card text-center mt-2" style="width: 18rem">
<div class="card-header">
Invitation Details
</div>
<img class="card-img" src="@qrUri" />
<div class="card-body">
<p>
<a href="#" data-toggle="modal" data-target="#exampleModalCenter">Open in app</a>
</p>
<form class="input-group mb-3">
<input readonly="readonly" type="text" id="invitationDetails" autocomplete="off" class="form-control" value="@invitation" aria-label="Recipient's username" aria-describedby="basic-addon2">
<div class="input-group-append">
<button class="btn btn-info" onclick="copyToCliboard(document.getElementById('invitationDetails'));return false;">Copy</button>
</div>
</form>
</div>
</div>

@await Html.PartialAsync("_LaunchApp", invitation)
Loading

0 comments on commit f502667

Please sign in to comment.