Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/trusona/trusona-server-sdk-dotnet


https://github.com/trusona/trusona-server-sdk-dotnet

Last synced: about 13 hours ago
JSON representation

Awesome Lists containing this project

README

        

# Trusona Server SDK

The Trusona Server SDK allows simplified interaction with the Trusona API.

## Table of Contents

1. [Prerequisites](#prerequisites)
1. [Server SDK API Credentials](#server-sdk-api-credentials)
1. [NuGet Artifactory Setup](#nuget-artifactory-setup)
1. [Adding the Trusona repository](#adding-the-trusona-repository)
1. [Installing the Trusona Package](#installing-the-trusona-package)
1. [Integrating the API into a project](#integrating-the-api-into-a-project)
1. [Creating a Trusona object](#creating-a-trusona-object)
1. [Registering devices with Trusona](#registering-devices-with-trusona)
1. [Binding a device to a user](#binding-a-device-to-a-user)
1. [Activating a device](#activating-a-device)
1. [Registering users using the Trusona app](#registering-users-using-the-trusona-app)
1. [Creating Trusonafications](#creating-trusonafications)
1. [Creating an Essential Trusonafication](#creating-an-essential-trusonafication)
1. [Creating an Essential Trusonafication, without user presence or a prompt](#creating-an-essential-trusonafication-without-user-presence-or-a-prompt)
1. [Creating an Essential Trusonafication, with a TruCode](#creating-an-essential-trusonafication-with-a-trucode)
1. [Creating an Essential Trusonafication, with the user's identifier](#creating-an-essential-trusonafication-with-the-users-identifier)
1. [Creating an Essential Trusonafication, with the user's email](#creating-an-essential-trusonafication-with-the-users-email)
1. [Adding custom fields to a Trusonafication](#adding-custom-fields-to-a-trusonafication)
1. [Creating an Executive Trusonafication](#creating-an-executive-trusonafication)
1. [Canceling a Trusonafication](#canceling-a-trusonafication)
1. [Using TruCode for device discovery](#using-trucode-for-device-discovery)
1. [Retrieving identity documents](#retrieving-identity-documents)
1. [Retrieving all identity documents for a user](#retrieving-all-identity-documents-for-a-user)
1. [Retrieving a specific identity document](#retrieving-a-specific-identity-document)
1. [Identity document verification statuses](#identity-document-verification-statuses)
1. [Identity document types](#identity-document-types)
1. [Retrieving a device](#retrieving-a-device)
1. [Handling errors](#handling-errors)
1. [Using a specific Trusona region](#using-a-specific-trusona-region)

## Prerequisites

### Minimum versions
The Trusona SDK targets .NET Standard 2.0. For a comprehensive list of framework compatabilty, please reference the [.NET Standard Compatability Matrix](https://docs.microsoft.com/en-us/dotnet/standard/net-standard)

### Server SDK API Credentials

The Server SDK requires API credentials that are used by the SDK to identify and authenticate requests from your application to the Trusona APIs.

The two credentials required by the SDK include a `token` and `secret`. Both are strings generated and distributed by Trusona.

**NOTE:** The `token` and `secret` should not be shared with anyone. They are how you authenticate to the Trusona services, and you should not check them into source control.

## NuGet Artifactory Setup

The Trusona SDK packages are hosted on the Trusona Artifactory server. Artifactory acts as a NuGet repository that requires credentials to access it. In order to access the Trusona Server SDK, you will need to add the Trusona NuGet repository to your project and configure it to use the Artifactory username and password provided by Trusona. Here is an example of how to configure NuGet to talk to Artifactory.

### Adding the Trusona repository

To configure NuGet to use the Trusona repository, run the following commands. For use in CI envrionments, you may want to configure these as envrioment variables and provide them to your build script at runtime.

```
nuget sources Add -Name Trusona -Source https://trusona.jfrog.io/trusona/api/nuget/nuget-local
```

Alternatively, you may configure NuGet using Visual Studio. To configure the NuGet Visual Studio Extension to use the Trusona repository, you need to add another Package Source under NuGet Package Manager.

1. Access the corresponding repositories in the "Options" window (Options | Tools) and select to add another Package Source.
1. Provide a name for the repository (i.e. Trusona)
1. Paste in https://trusona.jfrog.io/trusona/api/nuget/nuget-local for the URL

### Installing the Trusona Package

In your project, run the following command to install the latest version of the Trusona SDK.

```
nuget install Trusona.SDK
```

Alternatively, you may also search for the NuGet package using Visual Studio. Be sure to select `All Sources` when using the NuGet extension.

## Integrating the API into a project

### Creating a Trusona object

The `Trusona` class is the main class you will interact with to talk to the Trusona APIs. It can be created with the `token` and `secret` provided by [Trusona](#server-sdk-api-credentials).

**NOTE:** The `token` and `secret` should not be shared with anyone. They are how you authenticate to the Trusona services, and you should not check them into source control.

```csharp
var trusona = new Trusona(
token: "token",
secret: "secret"
);
```

You'll also want to make sure the `token` and `secret` values aren't checked in to your project.

### Registering devices with Trusona

To get a device ready to be used with Trusona, there are three main steps:

1. Create a device
1. Bind the device to a user
1. Activate the device

The first step, creating a device, will be handled by the Trusona mobile SDKs on the client. Once a device is created, the Trusona `deviceIdentifier` will need to be sent to your backend which can use the Trusona Server SDK to complete the next steps.

#### Binding a device to a user

When the backend determines which user owns the `deviceIdentifier`, it can bind the `userIdentifier` to the device in Trusona. The `userIdentifier` can be any `String` that allows you to uniquely identify the user in your system. To bind a device to a user, call the `CreateUserDevice` method.

```csharp
var userDevice = await trusona.CreateUserDevice(
userIdentifier: user.Id,
deviceIdentifier: "deviceIdentifier"
);
var activationCode = userDevice.ActivationCode;
```

More than one device can be bound to a user and later, when you Trusonafy them, any device bound to that user may accept the Trusonafication. Once the device is bound the user, you'll receive an activation code that can be used later to active the device.

##### Exceptions

| Exception | Reason |
| :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------- |
| `DeviceNotFoundException` | Indicates that the request to bind the user to the device failed because the device could not be found. |
| `DeviceAlreadyBoundException` | Indicates that the request to bind the user to the device failed because the device is already bound to a different user. |
| `ValidationException` | Indicates that the request to bind the user to the device failed because either the `deviceIdentifier` or `userIdentifier` were blank. |
| `TrusonaException` | Indicates that the request to bind the user to the device failed, check the message to determine the reason. |

#### Activating a device

When the device is ready to be activated, call the `ActivateUserDevice` method with the activation code.

```csharp
var result = await trusona.ActivateUserDevice(activationCode);
```

If the request is successful, the device is ready to be Trusonafied.

##### Exceptions

| Exception | Reason |
| :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------- |
| `DeviceNotFoundException` | Indicates that the request to activate the device failed because the device could not be found, most likely due to an invalid `activationCode`. |
| `ValidationException` | Indicates that the request to activate the device failed because the `activationCode` was blank. |
| `TrusonaException` | Indicates that the request to activate the device failed, check the message to determine the reason. |

### Registering users using the Trusona app

If your users are using the Trusona app, but the user identifier you use is not an email address, you can register their user identifiers with their Trusona account by creating a user binding. To create a user binding, you will need to:

1. Have the user login to your system using their normal method.
1. Once authenticated, use the Trusona Web SDK to display a secure QR code for them to scan.
1. After they have scanned the secure QR code, you can send the scanned `truCodeId` to your backend system.
1. Then use the server SDK to create a binding using the authenticated user's `userIdentifier` and the `truCodeId` that was scanned.
1. After the binding is successful, create a Trusonafication to finalize the process with the user.

The final step can be accomplished in the .NET SDK using the example code below:

```csharp
var trusona = new Trusona(
token: "token",
secret: "secret"
);

var userIdentifier = "";
var truCodeId = "";

await trusona.CreateUserBinding(userIdentifier: userIdentifier, truCodeId: truCodeId);
```

**NOTE:** Send a Trusonafication after binding the user identifier to confirm the `BoundUserIdentifier` matches what you expect and to avoid the user getting stuck on the spinner that appears after scanning a secure QR code.

### Creating Trusonafications

Once a device is bound to a user, that user can be Trusonafied using the device identifier obtained from the Trusona Mobile SDK. The `userIdentifier` that was used to bind the user to the device will be returned in the `BoundUserIdentifier` field if the authentication request is successfully accepted by the user.

**NOTE:** if the user is using the Trusona mobile app and attempts to authenticate with your system prior to being registered, the `BoundUserIdentifier` field will be `null`. The user's identifier will need to be regiserted in this case.

#### Creating an Essential Trusonafication

```csharp
var trusona = new Trusona(
token: "token",
secret: "secret"
);

var request = Trusonafication.Essential()
.DeviceIdentifier("PBanKaajTmz_Cq1pDkrRzyeISBSBoGjExzp5r6-UjcI")
.Action("login")
.Resource("Acme Bank")
.Build();

var trusonafication = await trusona.CreateTrusonafication(request);

var result = await trusona.GetTrusonaficationResult(trusonafication.Id);

if(result.IsSuccessful)
{
var userIdentifier = result.BoundUserIdentifier;
// handle successful authentication
}
```

By default, Essential Trusonafications are built such that the user's presence is required and a prompt asking the user to "Accept" or "Reject" the Trusonafication is presented by the Trusona Mobile SDK. A user's presence is determined by their ability to interact with the device's OS Security, usually by using a biometric or entering the device passcode.

#### Creating an Essential Trusonafication, without user presence or a prompt

```csharp
var trusona = new Trusona(
token: "token",
secret: "secret"
);

var request = Trusonafication.Essential()
.DeviceIdentifier("PBanKaajTmz_Cq1pDkrRzyeISBSBoGjExzp5r6-UjcI")
.Action("login")
.Resource("Acme Bank")
.WithoutUserPresence()
.WithoutPrompt()
.Build();

var trusonafication = await trusona.CreateTrusonafication(request);

var result = await trusona.GetTrusonaficationResult(trusonafication.Id);

if(result.IsSuccessful)
{
// handle successful authentication
}
```

In the above example, the addition of `WithoutUserPresence()` and `WithoutPrompt()` on the builder will result in a Trusonafication that can be accepted solely with possession of the device.

#### Creating an Essential Trusonafication, with a TruCode

```csharp
var trusona = new Trusona(
token: "token",
secret: "secret"
);

var request = Trusonafication.Essential()
.TruCode(Guid.Parse("37086D01-9EF6-4B57-8592-1276C58B1C4D"))
.Action("login")
.Resource("Acme Bank")
.Build();

var trusonafication = await trusona.CreateTrusonafication(request);

var result = await trusona.GetTrusonaficationResult(trusonafication.Id);

if(result.IsSuccessful)
{
// handle successful authentication
}
```

In this example, instead of specifying a device identifier, you can provide an ID for a TruCode that was scanned by the Trusona Mobile SDK. This will create a Trusonafication for the device that scanned the TruCode. See [Using TruCode for device discovery](#using-trucode-for-device-discovery) below for more information on using TruCodes.

#### Creating an Essential Trusonafication, with the user's identifier

```csharp
var trusona = new Trusona(
token: "token",
secret: "secret"
);

var request = Trusonafication.Essential()
.UserIdentifier("73CC202D-F866-4C72-9B43-9FCF5AF149BD")
.Action("login")
.Resource("Acme Bank")
.Build();

var trusonafication = await trusona.CreateTrusonafication(request);

var result = await trusona.GetTrusonaficationResult(trusonafication.Id);

if(result.IsSuccessful)
{
// handle successful authentication
}
```

In some cases you may already know the user's identifier (i.e. in a multi-factor or step-up authentication scenario). This example shows how to issue a Trusonafication using the user's identifier.

#### Creating an Essential Trusonafication, with the user's email

```csharp
var trusona = new Trusona(
token: "token",
secret: "secret"
);

var request = Trusonafication.Essential()
.EmailAddress("[email protected]")
.Action("login")
.Resource("Acme Bank")
.Build();

var trusonafication = await trusona.CreateTrusonafication(request);

var result = await trusona.GetTrusonaficationResult(trusonafication.Id);

if(result.IsSuccessful)
{
// handle successful authentication
}
```

In some cases you may be able to send a Trusonafication to a user
by specifying their email address. This is the case if one of the following is true:

- You have verified ownership of a domain through the Trusona Developer's site
- You have an agreement with Trusona allowing you to send Trusonafications to any email address.

Creating a Trusonafication with an email address is similar to the other use cases, except you use the `EmailAddress()` method rather than `UserIdentifier()` or `DeviceIdentifier()`.

#### Adding custom fields to a Trusonafication

```csharp
var request = Trusonafication.Essential()
.EmailAddress("[email protected]")
.Action("login")
.Resource("Acme Bank")
.WithCustomFields(new Dictionary { { "greeting", "hello!" }, { "last-login", false } })
.Build();
```

If you are using the mobile SDK to build a custom app that integrates with Trusona, you have the option of including additional data on the Trusonafication which the app can use to affect its behavior.

For example, you may want to include additional context on the Trusonafication prompt, per the example above.

You can add these custom fields by passing a `Dictionary` into the `WithCustomFields` builder method. The data will then be available in the Trusonafication received by the SDK.

Note that the custom fields are not used in the case that the Trusonafication is being handled by the Trusona app.

#### Creating an Executive Trusonafication

To create an Executive Trusonafication, call the `Executive` method initially instead of `Essential`.

```csharp
var trusona = new Trusona(
token: "token",
secret: "secret"
);

var request = Trusonafication.Executive()
.DeviceIdentifier("PBanKaajTmz_Cq1pDkrRzyeISBSBoGjExzp5r6-UjcI")
.Action("login")
.Resource("Acme Bank")
.Build();

var trusonafication = await trusona.CreateTrusonafication(request);

var result = await trusona.GetTrusonaficationResult(trusonafication.Id);

if(result.IsSuccessful)
{
// handle successful authentication
}
```

Executive Trusonafications require the user to scan an identity document to authenticate. An identity document needs to be registered with the user's account using the Trusona Mobile SDKs before the user can accept an Executive Trusonafication, and they must scan the same document they registered at the time of Trusonafication. Like Essential, both the prompt and user presence features can be used and are enabled by default, but they can be turned off independently by calling `withoutPrompt` or `withoutUserPresence`, respectively.

##### Trusonafication Builder Options

| Name | Required | Default | Description |
| :-------------------- | :------: | :-----: | :----------------------------------------------------------------------------------------------- |
| `DeviceIdentifier` | N[^1] | none | The identifier as generated by the Trusona Mobile SDK. |
| `TruCode` | N[^1] | none | The ID for a Trucode scanned by the Trusona Mobile SDK. |
| `UserIdentifier` | N[^1] | none | The identifier of the user that was registered to a device. |
| `EmailAddress` | N[^1] | none | The email address of the user that was registered to a device. |
| `Action` | Y | none | The action being verified by the Trusonafication. (e.g. 'login', 'verify') |
| `Resource` | Y | none | The resource being acted upon by the user. (e.g. 'website', 'account') |
| `ExpiresAt` | N | null | An ISO-8601 UTC date that sets the expiration time of the Trusonafication. |
| `WithoutUserPresence` | N | false | Removes the requirement for the user to demonstrate presence when accepting the Trusonafication. |
| `WithoutPrompt` | N | false | Removes the requirement for the user to explicityly "Accept" or "Reject" the Trusonafication. |
| `WithCustomFields` | N | null | Arbitrary key-value data fields made available to the Trusonafication. Amount of data in the hash is limited to 1MB |
| `CallbackUrl` | N | null | A HTTPS URL to POST to when the trusonafication has been completed (accepted, rejected, or expired).

**NOTE:** The URL should include a randomized segment so it cannot be guessed and abused by third-parties e.g. https://your.domain.com/completed_authentications/f8abe61d-4e51-493f-97b1-464c157624f2. |

[^1]: You must provide at least one field that would allow Trusona to determine which user to authenticate. The identifier fields are `DeviceIdentifier`, `TruCode`, `UserIdentifier`, and `EmailAddress`.

### Canceling a Trusonafication

If a trusonafication is created and its purpose is no longer required, it may be necessary to cancel it to avoid having a indefinite `IN_PROGRESS` status.

Any trusonafication that is `IN_PROGRESS` can be cancelled.

Once successfully cancelled, a trusonafication can no longer be acted upon and its status is set as `CANCELLED`.

```csharp
var trusona = new Trusona(
token: "token",
secret: "secret"
);

var request = Trusonafication.Essential()
.UserIdentifier("73CC202D-F866-4C72-9B43-9FCF5AF149BD")
.Action("login")
.Resource("Acme Bank")
.Build();

var trusonafication = await trusona.CreateTrusonafication(request);

// if still IN_PROGRESS after some predetermined time, you may cancel it

await trusona.CancelTrusonafication(trusonafication.id);
```

If the trusonafication cannot be successfully cancelled based on its status at the point the request is received, or if the trusonafication does not exist, an exception will be thrown.

### Using TruCode for device discovery

In the previous section, we demonstrated how to issue a Trusonafication to a specific device using it's `DeviceIdentifier`, but what if the user is trying to login to your website from their desktop computer and you don't know what the user's `DeviceIdentifier` is? That's where TruCode comes in.

#### What is a TruCode?

A TruCode is a short-lived token that can be rendered in the form of a QR code. A Trusona enabled device can scan the QR code and send it's `DeviceIdentifier` to Trusona. Your backend server can then fetch the `DeviceIdentifier` from Trusona and perform a Trusonafication on the device.

#### Rendering a TruCode

To render a TruCode, you can use the Trusona Web SDK. Because TruCodes are short-lived, they need to be refreshed periodically. The Trusona Web SDK will handle the fetching of TruCodes, polling the status to see if they've been paired, refreshing them before they expire, and, when finally paired, return the `TruCodeId` that the backend can use to look up the device identifier.

First get the Web SDK Config for your system from the Server SDK. The Web SDK will need this configuration later when rendering TruCode.

```csharp
var trusona = new Trusona(
token: "token",
secret: "secret"
);

var webSdkConfig = trusona.GetWebSdkConfig(); // {"truCodeUrl": "https://example.net", "relyingPartyId": "C97A800D-75E8-43B5-87A5-3282B0DD8576" }
```

Include the trucode.js script tag before the `