Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Identity RFC & Research #15

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Changes from 9 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
193 changes: 193 additions & 0 deletions docs/rfc-identity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# RFC Peer-Star-Identity

This is a proposal for an identity management system for Peer-Star, named Peer-Star-Identity. It's built upon standards to provide a good foundation for Peer-Star applications to authenticate and identify users.

*Authors*: André Cruz, João Santos, Pedro Teixeira

1. [Standards & foundations](#standards--foundations)
1. [Decentralized identifiers](#decentralized-identifiers-dids)
1. [Self-signed Verifiable Claims](#self-signed-verifiable-claims)
1. [DID Delegates & devices](#did-delegates--devices)
1. [Using DID-Auth to prove control of the DID](#using-did-auth-to-prove-control-of-the-did)
1. [Proposal: The IdentityManager](#proposal-the-identitymanager)
satazor marked this conversation as resolved.
Show resolved Hide resolved
1. [What is it?](#what-is-it)
1. [Managing identities](#managing-identities)
1. [Managing Verifiable Claims](#managing-verifiable-claims)
1. [Authenticating on applications](#authentication-on-applications)
1. [Signing artifacts on applications](#signing-artifacts-on-applications)
1. [Managing application sessions](#managing-application-sessions)
1. [Revoking a device](#revoking-a-device)
1. [Diagrams & mockups](#diagrams--mockups)
1. [Glossary](#glossary)

## Standards & foundations

### Decentralized identifiers (DIDs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonnycrunch, @b5, @ianopolous would love your review on this RFC, I know that you have been thinking about Identity on the Decentralized Web a ton :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lanzafame just read up ipfs/notes#292, you should review this one too! :)


A Decentralized Identifier (DID) is a string that uniquely maps to an identity, e.g. `did:btcr:123-445-333`. This standard is fully described in the [W3C DID spec](https://w3c-ccg.github.io/did-spec/) and is being widely adopted to create digital identities.

There are already several DID methods, such as uPort and Sovrin, which are listed in the [DID Method Registry](https://w3c-ccg.github.io/did-method-registry/). Each method has its own way to resolve a DID to a DID-Document. A DID-Document obeys a specified schema and it contains, among other things, a set of public keys that entities can use to establish communication (encrypt, verify digital signatures) with the DID owner.

The owner of a DID can use the DID's private keys to digitally sign artifacts. Any party can retrieve the DID-Document and verify the digital signature against the public keys listed in the DID-Document.

### Self-signed Verifiable Claims

A Verifiable Claim is a qualification, achievement, quality, or piece of information about an entity's background such as a name, government ID, payment provider, home address, or university degree. This standard is described in detail in the [W3C Verifiable Claims spec](https://www.w3.org/TR/verifiable-claims-data-model).

By issuing Verifiable Claims about an entity's identity, we are strengthening the credibility of the identity itself. Those claims may be issued by the owners themselves or by other identities.

We will start off by leveraging self-issued and self-signed Verifiable Claims based on social networks, similar to [Keybase](https://keybase.io/) claims. They are easy to setup and they deliver a good base for trusting identities. Later on, we can expand to other types of Verifiable Claims as well, like claims emitted by third-parties.

### DID Delegates & devices

In a simple configuration, there's only a key that owns the DID, called the Master Key. That key could be used to sign artifacts and to cipher communication. However, that solution is sub-optimal for the following reasons:

1. Does not offer Perfect Forward Secrecy: If an attacker manages to gain access to the Master Key, he/she is able to decipher all previous communications made to, and from, that entity's DID. This happens because no session keys are generated, the Master key, acts as the session key.
2. Over exposes the private key: A Master Key should be used as few times as possible. Using it a lot makes it easier for an attacker to gain access to it.
3. If the Master Key is compromised, the attacker is able to completely impersonate the real DID owner.

The DID spec states that DID methods must provide a way for the owner to rotate keys, which solves `2`. The DID spec also states that DID methods must provide a way to recover the DID (e.g.: in case of theft), which solves `3`.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must provide a way to recover the DID (e.g.: in case of theft)

revocation is MUST, whereas recovery is optional, see here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are correct, thanks for pointing that out.


Nevertheless, the [DID specification](https://w3c-ccg.github.io/did-spec/) advises DID methods to support adding [delegate keys](https://w3c-ccg.github.io/did-spec/#authorization-and-delegation) that can act on behalf of the identity, but with granular capabilities. As an example, the [erc725](https://github.com/ethereum/EIPs/issues/725) DID method has such feature via adding keys with the `action` type, allowing such keys to perform signing or authentication.
Delegate public keys will be listed in the DID-Document as well, which improves interoperability and compatibility with many other specs in the ecosystem, such as the [DID Auth](https://github.com/WebOfTrustInfo/rebooting-the-web-of-trust-spring2018/blob/master/draft-documents/did_auth_draft.md) and [Identity Hubs](https://github.com/decentralized-identity/hubs/blob/master/explainer.md).

It's expected that the same entity will use Peer-Star applications from different devices, such as a desktop, laptop, smart-phone, or others. For the DID methods that support delegate keys, each device should have its own key added as a delegate. In case the DID method does not support delegate keys, the Master Key is used instead. In both cases, from now on, we will call these keys _Device Keys_.

#### Revocation

As previously stated, the entity in control of the DID may revoke a Device Key. Similarly to how non-revoked Public Device Keys keys are publicly listed in DID-Documents, revoked Public Device Keys should also be public. This is because a relying party must be able to verify signatures made in the past and, as such, must be able to assert that the public key is associated to the DID, even if it's revoked.

As of now, the DID spec does not specify how and where the revoked keys can be obtained. There's an [open issue](https://github.com/w3c-ccg/did-spec/issues/63) on the DID spec that brings this topic into the discussion and the W3C CCG working group is keen in listing revoked keys in the DID-Document.

### Using DID-Auth to prove control of the DID

Typical DApps flows require a relying party to trust another. We can leverage DIDs and self-signed Verifiable Claims in a "handshake" ceremony. The ceremony should follow the [DID-Auth spec](https://github.com/WebOfTrustInfo/rebooting-the-web-of-trust-spring2018/blob/master/draft-documents/did_auth_draft.md).

To illustrate how [DID-Auth](https://github.com/WebOfTrustInfo/rebooting-the-web-of-trust-spring2018/blob/master/draft-documents/did_auth_draft.md) works, consider the following example: Alice wants to share a secret with Bob.

After agreeing on a transport, Alice presents herself with a DID, a Device Public Key, and a set of self-signed Verifiable Claims. Alice does this by encrypting all this material, along with a nonce, with Bob's public key and signing with her `authentication` key (a key present in the DID-Document under the `authentication` property). To trust Alice, Bob must:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alice presents herself with a DID, a Device Public Key, and a set of self-signed Verifiable Claims

This sentence sounds like Alice has given herself a present containing a DID, device key and claims. I could be incorrect, but I am guessing the gist of it is that Alice presents herself as herself to Bob with these things.

Long way to say that the sentence could be made clearer, whichever way it is meant to be.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed presents to introduces to avoid confusion.


1. Decrypt Alice's message
2. Resolve Alice's DID to a DID-Document
3. Check if Alice's Device Public Key is listed in `authentication` property of the DID-Document
4. Verify the message signature against her Device Public Key using the correct algorithm
5. Verify the signatures of the self-signed Verifiable Claims against the public keys listed in the `publicKey` property of the DID-Document.
6. Manually verify Alice's Verifiable Claims to see if they are credible.

Please note that certain aspects of point `6.` can be done automatically by crawling the proofs and verifying the signatures against Alice's Public Keys. Still, Bob must explicitly verify the proofs as an attacker might be trying to impersonate the real Alice with fake social profiles.

If all went good, Bob is pretty confident that Alice is the real Alice. For future "handshake" ceremonies to be faster, Bob can store Alice's DID and Device Public Key somewhere, like a contacts list.

## Proposal: The IdentityManager

Usability is a crucial aspect of this proposal as it played a very important role in its concept.

On one hand, the experience for end-users should be intuitive, simple and familiar. Ideally, users should have little contact with private keys and most of the cryptographic operations should happen behind the scenes. On the other hand, developers building DApps should have an easy way to authenticate users.

The IdentityManager packages emerging [Standards & foundations](#standards--foundations) into an intuitive and easy to use interface for end-users.

### What is it?

The IdentityManager is a web-page hosted on IPFS and reachable via a specific URL, e.g.: https://peer-identity.io. The application will work completely offline thanks to the installation of a ServiceWorker. By using the application, users will be able to:
satazor marked this conversation as resolved.
Show resolved Hide resolved

- Create identities on several DID methods
- Import identities created on other devices
- Manage Verifiable Claims of identities
- Authenticate to dApps (sessions)

Because it runs on its own domain, it provides a sandboxed environment where access to functionality and data is completely controlled. More specifically, all interactions made with the IdentityManager it will be made via [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) where control and data segmentation is made via the messages' origin.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is communicating with an IdentityManager from something other than a browser within scope of this document?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I've mentioned that briefly in the IdentityManager introduction:

  • Has a wide support among devices. If we make it a Progressive Web App (PWA), users may install the application in the OS itself, further enhancing the user experience. Later on, we can develop native mobile apps to support OS's that don't yet allow PWAs to be installed natively.

Copy link
Author

@satazor satazor Jun 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't explored situations where the user wants to authenticate to a dApp, via another device. Were you mentioning that?

Copy link

@lanzafame lanzafame Jul 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was more referring to something you addressed above:

It seems that you are referring to situations where a person authorizes a application, similar to oAuth, and then the application may initiate actions on the person's behalf without the user being interacting with the app. This is out of the scope of this RFC for now.

That answers my question. 👍

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interactions made with the IdentityManager it will be
                                           ^^

there is an extra it in the sentence.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍


All private keys, such as Device Private Keys and Session Private Keys, will be safely stored in the IdentityManager local storage. Applications must interact with the IdentityManager to sign or decypher payload that uses such keys.

Using the `postMessage` API to directly communicate with the IdentityManager is a bit clunky. Instead, developers will use a library called IdentityManagerClient that abstracts all the communication layer with an intuitive API.

Moreover, any meaningful event on the IdentityManager, such as the removal of an identity, will be broadcasted to interested parties. This allows applications to immediately react to certain events by subscribing to them on the IdentityManager.

Among others, the most important advantages of this solution are:

- Embraces several DID methods instead of being tied to a specific method.
- Uses DID best practices, such as using delegate keys to associate devices.
- Doesn't require any extensions, scanning of QRCodes, or any other unfriendly processes for daily use.
- Acts like a "server" in the sense that sensitive information may be safely stored in it. Many DID methods require a secret for certain actions, e.g.: uPort requires an app secret to request normal and verified credentials.
- Has a wide support among devices. If we make it a Progressive Web App (PWA), users may install the application in the OS itself, further enhancing the user experience. Later on, we can develop native mobile apps to support OS's that don't yet allow PWAs to be installed natively.
- Allows the user to choose between several identities when authenticating, useful for people that manage companies, organizations or similar.

### Managing identities

Users will be able to create identities using their preferred DID method or associate existing ones. They will be guided throughout the process according to the chosen DID method. Once they complete it, they will have successfully created a Device Key.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Associate existing keys" implies duplicate use of keys across services? It's worth considering the attack vector of app developers knowing both a secret and where to use it as part of the key association process.

If keys aren't moving / duplicating, then we lose the underlying assumption that the private keys live withing IdentityManager, which'll drive implementation complexity up a bunch if one intends to keep the experience for app developers smooth.

Some of this may be better covered in the verifiable claims spec, apologies if this is out of scope / covered elsewhere 😄. Seems like derivative keys are once again the answer, but worth calling out explicitly if so.

Copy link
Author

@satazor satazor Jun 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Associate existing keys" implies duplicate use of keys across services? It's worth considering the attack vector of app developers knowing both a secret and where to use it as part of the key association process.

Depending on the DID method, associate existing ones means one of:

  1. Create a new key (pair) and add it as the delegate. The DID method must support delegates, as explained here: DID Delegates & devices. This new key becomes the Device Key.
  2. In case the DID method does not support delegates, import the Master Private Key that controls the DID. In this scenario, the Master Key is the same as the Device Key.

1 is preferable but 2 is the only viable option for some DID methods. You may read more on https://w3c-ccg.github.io/did-spec/#authorization-and-delegation.

If keys aren't moving / duplicating, then we lose the underlying assumption that the private keys live withing IdentityManager, which'll drive implementation complexity up a bunch if one intends to keep the experience for app developers smooth.
Some of this may be better covered in the verifiable claims spec, apologies if this is out of scope / covered elsewhere 😄. Seems like derivative keys are once again the answer, but worth calling out explicitly if so.

The Device & Session private keys live within the IdentityManager and dApps must use the IdentityManagerClient to sign/decipher payload. I didn't understand why is this related with the verifiable claims, is it because of the signatures?


All the Device Private Keys will be locked to improve security. One such locking method is using a passphrase to encrypt the Device Private Key. Other methods, such as [biometric signatures](https://en.wikipedia.org/wiki/Electronic_signature#Biometric_signature), can be used instead if they prove to be effective and are available in the user's device.

Even if a device gets stolen, the robber won't be able to use most features without unlocking the Device Private Key as all the information stored locally will be encrypted with the Device Public Key. This gives time for the owner of the Identity to revoke the compromised device in the IdentityManager of another device.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how this would work: all of the private keys are encrypted with the Device Public Key. I think all of the key wrapping will have to work via a symmetric PBKDF2 key as you are wrapping the private keys (needed to decrypt the private key material) with a public key. Won't one need the wrapped private keys to do the decryption?
(Luckily, mobile devices have the excellent UX of fingerprint and face-unlock that can extract the symmetric wrapping key from the device's secure enclave, on desktop, this is less tidy. I hope I am not getting too deep into implementation here).


Because the identity was linked to this device at setup time, and depending on the DID method, profile information and verifiable claims might become stale. For this reason, users will be able to sync up with their identity to update any stale data.

### Managing Verifiable Claims

Users will be able to add claims to their identities. Initially, we will focus on adding self-signed claims linked to some of the most popular social networks. The process of adding those claims (and proofs) will work similarly to [Keybase](https://keybase.io/) in the sense that users will be guided throughout the process.

The exact way in how the claims will be stored is dependent on the DID method. For instance, uPort already provides a way to store these claims via attestations.

### Authentication on applications

Peer-Star applications will use the IdentityManagerClient to manage the user's session via Session Keys.

When bootstrapped, the IdentityManagerClient will attempt to read the Session Public Key from the local storage of the applications' origin. The IdentityManagerClient then takes the Session Public Key and queries the IdentityManager to retrieve the session data associated to it. If the IdentityManager responds back with the session data, the user is authenticated and, as such, there's an Authenticated Session. If the IdentityManager doesn't recognize that Session Public Key or if there's no Session Public Key in the first place, there's no Authenticated Session, meaning that no user is authenticated. In such cases, the application may request the Identity Manager to authenticate the user, typically via a login button.

When the application requests the IdentityManagerClient to authenticate the user, a popup pointing to the IdentityManager authenticate screen is open (via `window.open`). In this screen, the user is asked to choose an identity and to disclose some information, such as its name, its photo and a set of claims & proofs. If the user consented to the disclosure of this information and entered the Device Private Key passphrase correctly, a new session for this application will be created and stored. The session data, including the Session Public Key and its signature signed by the Device Private Key, is sent back to the application. If the user denied the disclosure of the information, the operation will fail.
In both scenarios, the popup is closed and the outcome is made available to the application.

Applications might choose the TTL of a session depending on the degree of security they want to have.
satazor marked this conversation as resolved.
Show resolved Hide resolved

### Signing artifacts on applications

Applications may want to sign artifacts, such as regular data or Ephemeral Keys. This will be possible in two different ways:

1. Sign with the Session Private Key
2. Sign with the Device Private Key
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could a third option be to issue a one-time-use key? I've used json web tokens in the past for such a purpose back when they were considered a good idea.

For this to work one would need to scope the capabilities of such a key, or place a reasonably-short TTL on the key.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will answer below as it is related.


The first method is less intrusive and happens transparently to the user, but is less secure. More specifically, a robber who stole a device may still sign Ephemeral Keys with the Session Private Key as long as a session is valid (not expired). Relying parties will still see those signatures as valid until the DID owner revokes the stolen device.

The second method provides more security as the user is prompted for the Device Private Key passphrase, but it's more intrusive. The interaction is similar to the Authentication process, where a popup pointing to the sign screen gets open. The user either allows or denies the signing and the result gets back into the application. Please note that the passphrase might be stored in memory in the IdentityManager during a certain amount of time, which in turn makes this process less intrusive for subsequent signings.

Ultimately, the application may choose between both methods for different situations depending on the security degree they want to have.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I'm secretly hoping for a parallel document for defining d.app capabilities, which in this context would be classified as an artifact, but intersect at the point of permissions.

This document seems to carry forward the assumption that I want to orient my experience of d.apps around the present model of sign-up-for-service-and-stay-signed-up. As a user I want to live in a world where if I stop using a service after a while, it's capacity to act on my behalf (sessions) is reduced without my intervention.

This will greatly frustrate app developers if presented directly, but a smooth-enough cross-app authentication interface coupled with a well-defined capabilities spec would make it possible for app developers to build upon each-other's features. Github & Continuous Integration feels like the prototype for this, where two app developers have a strong mutual interest to build on each-other's work because continuous integration is a big problem, and code management is a big problem.

I want to live in a world where authentication & capability definition is so well defined I don't have to build a chat feature into my app, instead I can just rely on some other app's implementation. For that to work we need uniform identity management & a common method for defining the capabilities of a d.app. The IPFS project is a bold step for common infrastructure that makes much of this conversation possible, if only a dream at this point 😉.

Amazon Temporary Security Credentials and it's STS service come to mind as non-oAuth prior art.

Copy link
Author

@satazor satazor Jun 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I'm secretly hoping for a parallel document for defining d.app capabilities, which in this context would be classified as an artifact, but intersect at the point of permissions.

Me, @joaosantos15 and @pgte were also working on a Authorization RFC that would be built on top of this document.

This document seems to carry forward the assumption that I want to orient my experience of d.apps around the present model of sign-up-for-service-and-stay-signed-up. As a user I want to live in a world where if I stop using a service after a while, it's capacity to act on my behalf (sessions) is reduced without my intervention.

That's right. As of now, the only way for the application to act on your behalf is to sign artifacts that are meaningful in the context of it, like creating a comment in a discussion and sign it. But because this all happens in the browser environment, if you just do not use the app, the app code won't be acting on your behalf without you noticing it. There's an exception, which is if an app tries to sign stuff within ServiceWorkers, but we can handle that gracefully by notifying the user if the app is doing it regularly in the background.

It seems that you are referring to situations where a person authorizes a application, similar to oAuth, and then the application may initiate actions on the person's behalf without the user being interacting with the app. This is out of the scope of this RFC for now. If you are indeed referring to this kind of situation, there's some overlapping with identity hubs's actions & permissions. We could study it and mention it in this RFC for such situations.


### Managing application sessions

Users will be able to revoke any session listed on the identity's Authenticated Session list at any time. Revoking a session will essentially delete the application session from the IdentityManager local storage.
Additionally, each session has a TTL that limits its lifespan and states when they expire. Expired sessions are automatically revoked.

Applications will be unable to sign artifacts or decypher payload if their sessions are revoked or non-existent. This is guaranteed by declining such requests made by applications to the IdentityManager.

### Revoking a device

Users must be able to revoke a device associated with an identity. To do so, users may see the list of devices associated with an identity and revoke any device of that list, including the device from which they are interacting. This will require interacting with the DID method (Master Private Key) to publish the device being revoked.

If a device becomes aware that it was revoked, it will trigger a wipe-out process where all the identity data stored locally will be deleted, including the Device Key and Authenticated Sessions.

### Diagrams & mockups

**IdentityManager authentication flow diagram**

![Authentication flow](https://i.imgur.com/uMAi2be.png)

**IdentityManager authenticate screen diagram**

![Authenticate screen](https://i.imgur.com/kyvkrZE.png)

**IdentityManager application mockups**

![IdentityManager authenticate screen mockup](https://i.imgur.com/fZ7VYfi.png)

## Glossary

- **Entity:** A person, company, organization or equivalent that controls an identity.
- **DID:** An identity identifier, which resolves to a DID-Document.
- **DID-Document:** A JSON-LD document which contains information about an identity, such as public keys to be used to communicate with the entity that controls the identity.
- **Master Keys:** A pair of public and private keys that owns the identity (owns the DID).
- **Device Keys:** A pair of public and private keys of a device that can act on behalf of the identity owner.
- **Ephemeral Keys:** A temporary pair of public and private keys, signed by the Device Private Key or the Session Private Key.
- **Session**: A unique public key stored locally by the IdentityManagerClient that identifies a visitor.
- **Authenticated Session:** A Session that was signed by the entity controlling the Device Key. The Session Private Key lives securely on the IdentityManager local storage.
- **IdentityManager**: An application that provides identification and authentication to the Peer-Star ecosystem.
- **IdentityManagerClient**: A library used by Peer-Star applications that makes it easier to interact with the IdentityManager.