Part 4: Proving your identity

In part 2, we improved our process that track changes to TODO lists. In this tutorial, we’ll add identity. More specifically, we’ll implement functionality so that:

  1. A TODO list has an admin user
  2. The admin user, but no one else, can add new items to the list
  3. Only an employee can complete an item of the list

The full code for the project is available here: https://github.com/stratumn/todo-tutorials/tree/part4-v0.3.0

Signatures

Public key cryptography

We will make use of cryptographic signatures to ensure our users can only execute actions they are permitted to. Each user will have a pair of cryptographic keys:

  1. A public key, which can be shared with the world
  2. A private key, which only the user knows

Using their secret key, a user can sign a message, resulting in a cryptographic signature. Anyone who has the public key of said user can check that the signature is valid without knowing the private key. In other words, the private key is required for signing, while the public key is used for verifying the signature. It goes without saying that you can’t derive the private key from the public one, so the public counterpart is safe to share.

Within our process, we’ll only save public keys. Our process will be able to verify signatures using these public keys. However, only the users can create signatures for their public key since the process doesn’t know the private one. They will have to send signatures to the actions to prove that they are indeed the owner of a public key.

Generating keys and signatures

Use the strat CLI to generate your own key pair with strat keygen. You will be asked for the kind of key you want to create, chose ED25519 (this is the only algorithm handled to sign a chainscript segment at the moment).

➜  strat keygen
Use the arrow keys to navigate: ↓ ↑ → ←
? Which type of key would you like to generate ?:
  ▸ ED25519
    RSA
    ECDSA

You current directory should now contain two files containing your key pair: stratumn_key.pem (private key) and stratumn_key.pub.pem (public key):

A private key looks like this:

-----BEGIN ED25519 PRIVATE KEY-----
BEAcoqoGR5iEt3rtHs7vOxr+j8nWOdWnbjDsHb79feup9ezamNYXZmYIhE1Cgvtp
PIGhQkibXw+8gVCZI6kNsOGH
-----END ED25519 PRIVATE KEY-----

Throughout this tutorial we’ll refer to these keys:

Username Role Public Key Private key
alice admin —–BEGIN ED25519 PUBLIC KEY—–\nMCowBQYDK2VwAyEAO0U2B1DjM7k+AWLUBl9oK+ZhX/gpwrx5Z7RxCUgccDo=\n—–END ED25519 PUBLIC KEY—– —–BEGIN ED25519 PRIVATE KEY—–\nBEBKYlfsWzOXfAyRjIGm/KT46x2KSXaM/tQ9BCf0gOsXFqubc4wzuO/HxhxgfnGQ\nDqSIIVZvqbOrFjJ9wB9lAzNi\n—–END ED25519 PRIVATE KEY—–
bob employee —–BEGIN ED25519 PUBLIC KEY—–\nMCowBQYDK2VwAyEAL8sIcla39/vbZA+Ezpl4KvFVovB594keBDPaPVGvmrs=\n—–END ED25519 PUBLIC KEY—– —–BEGIN ED25519 PRIVATE KEY—–\nBEDbM/hjPt7Kijh+xaJaXs8vLeO0yqVpQOMj37M80D2aKlDvhmbhPPbXC3MQTVJa\nAy5ODvQV0wpFSANLVqAG9DXV\n—–END ED25519 PRIVATE KEY—–

Since the private keys are revealed in this document, they are for testing only. Do not use them for any other purpose! I suggest you copy these keys (or ones you’ve generated yourself for a couple of test users) into a text document. It will become handy when you need to copy and paste them.

Importing a key

Assuming your project is still running (if not, run strat up again), open http://localhost:4000 in your web browser. Navigate to the main page and drag & drop the newly created key file to the designated area (you also may click on the area and select a file from your filesystem). On success, the public key should appear on the right. You’re all set!

Uploading a key

Adding the “who” to our process

In order to add authentication in our process, we need to define identities that will take part in this process. In our example, we introduce:

  • alice, the administrator who is able to create new lists and add items to it.
  • bob, the employee that can complete them.

We will edit validation/rules.json to reflect the new requirements of our TODO list process. To do this, you must add a pki field to our process’ rules to bind our users to their public key(s) and their role(s). The pki should look like this:

{
  "TODO list": {
    "pki": {
      "alice": {
        "keys": ["-----BEGIN ED25519 PUBLIC KEY-----\nMCowBQYDK2VwAyEAq5tzjDO478fGHGB+cZAOpIghVm+ps6sWMn3AH2UDM2I=\n-----END ED25519 PUBLIC KEY-----"],
        "roles": ["employee", "manager"]
      },
      "bob": {
        "keys": ["-----BEGIN ED25519 PUBLIC KEY-----\nMCowBQYDK2VwAyEAL8sIcla39/vbZA+Ezpl4KvFVovB594keBDPaPVGvmrs=\n-----END ED25519 PUBLIC KEY-----"],
        "roles": ["employee"]
      }
    },
    "types": {...}
  }
}

(Note that as a manager, alice is also entitled to complete items on her own, and therefore has two roles: employee and manager.)

Defining permissions

We now want to prevent users other than the manager from creating new TODO lists as well as adding new items to the list. Furthermore, we want to make sure that only employees can complete items.

Extending the rules.json file:

{
  "TODO list": {
    "pki": {...},
    "types": {
      "init": {
        "schema": {
          "type": "object",
          "properties": {
            "title": {
              "type": "string"
            }
          },
          "required": ["title"]
        },
        "signatures": ["manager"]
      },
      "addItem": {
        "schema": {...},
        "signatures": ["manager"]
      },
      "completeItem": {
        "signatures": ["employee"]
      }
    }
  }
}

(Remember that validation rules are updated on-the-fly every time you save the rules.json file, you don’t need to restart the app)

Let’s make sure we have a correct setup!

Creating a new TODO list

First, make sure you imported your key correctly in the UI.

Now navigate to the maps section of your TODO list process. Try creating a new one while switching on Sign button, this screen should appear:

Alice creates a map

Then press Create and the map should be created successfully. You can try creating a new map without switching on the Sign option and an error saying a signature from a manager is required should be displayed.

Notice that when switching on the Sign option, you can actually chose which data you sign. Here we can sign:

  • inputs: these are the arguments you send to instantiate the map (“my permissioned TODO list” in this case).
  • refs: as seen in the previous tutorial, these are the referenced segments you can add when creating a map.

At least one signed property is required for the signature to be valid

Adding items to a list

Now that whe have a list, we’ll try and add an item to it. Navigate to the explorer for the map that was previously created. Select the first segment and open the Append dialog:

Select addItem as the action. Enter the new item you want to add, then press Append. You can also make sure that it doesn’t work if the signature is invalid.

Alice adds an item

Here we have more signing options, since we specify the action we execute (hereaddItem) and the parent (prevLinkHash) on which we apply the transition (in this case, the first segment of the map).

When selecting the newly created segment, its details are displayed on top of the map. We can check that the segment has been signed in the Link section. You can verify that the Signed by field matches the public key of Alice:

Alice has signed the segment

Completing items

The last thing we need to do is update our completeItem action so that it verifies a signature from an employee:

Alice completes an item

It works similarly to our addItem action, but it checks that the signature matches an employee instead of an admin.

To make sure it works, go back to the homepage of the UI, delete your current key (corresponding to Alice’s) and import the second one (belonging to Bob the employee).

Now go back to the map explorer, then select the item we previously created. Select completeItem as the action, add your signature, then press Submit. If you followed the instructions carefully a new segment will be appended.

It should work similarly with Alice’s key since she’s both an employee and a manager, but if you modify her roles in validation/rules.json and remove the employee role, her signature won’t be considered as valid when completing an item.

Congratulations on making it this far! Our process is now secured.

Updating test cases

Since we did not even modify the code of our actions in agent/lib/actions/action-todo.js, we don’t even need to update our test suite! Isn’t that sweet?

Exercises

  1. Add a user without any role and assign him a new key. Only this new user should be able to create new TODO lists.
  2. Add an action that marks an item as incomplete, that can only append after an item has been completed. Only users with the moderator role can execute this action.