New authentication flow + Granular permission control

safe_launcher
routing
safe_core
safe_vault

#1

Today, we are presenting the RFCs related to the new authentication flow that was first explained in the topic about the future of SAFE Launcher.

New authentication flow

The current authentication and permissions handling flow relies on SAFE Launcher, a stateful intermediate between any particular app and the network. While this allows for fine-grained control over the access flow and user setup, it has the drawback of requiring the process to always run, keep a local state and proxy all network requests. This is particularly cumbersome on embedded devices and mobile, where we cannot provide this pattern reliably.

RFC 46 – New Auth Flow proposes to replace SAFE Launcher with SAFE Authenticator (a stateless alternative).

This RFC outlines a new process to give applications authorised access to act on the SAFE Network with the user’s credentials. In particular, it is designed for the mobile and embedded use case in mind.

Highlights

At the core stands a rethinking of the data flow and authentication responsibility. Rather than requiring every app to go through the launcher to use the user’s credentials, in this approach, the user creates “sub-credentials” per app and assigns them to the app. The app can then access the network with these credentials independently from any other process running. We call these credentials appKeys (as they are a public-private-key-pair attached to a user’s maidsafe keys), which an app can interact with the network directly with.


Apps will have to directly interact with the network. We will restructure safe_core to provide all needed facility for that, as well as the proposed authentication flow against the authenticator. That means that each App has to bundle their own safe_core and link to that library. The library will expose all necessary functionality also through FFI to allow for binding in other environments than rust.


The root container is the main entry point for the user and most apps to interact with. It is a locally encrypted container stored at a random location on the network known only to the user, that generally only the authenticator has write access to. It reference will be stored in the user’s session packet on account creation. Keys starting with an underscore (_) are reserved for internal usage by the authenticator, while the authenticator may also allow the creation of other keys later.


When creating a user account the authenticator will create the following minimal set of containers within the root container, each one with its own random network address:

  • _apps/net.maidsafe.authenticator/
  • _documents
  • _downloads
  • _music
  • _pictures
  • _videos
  • _public
  • _publicNames

It is recommended that apps should only request the rights read and insert - which we will refer to as the BASIC-access. To promote the usage of this, APIs should provide a short-hand for this. Furthermore, the Authenticator may require a multi-step authorization from the user if it encounters an app that asks for more permissions than these and may allow the user to disable specific permissions asked for.

Discussion topic for RFC 46 – New Auth Flow


Granular permission control

Existing data types don’t support granular access control which is required for mobile platforms where access to the network through an intermediary like SAFE Launcher is complicated: each app would have to receive full permissions to modify and fetch data on a user’s behalf and private keys to sign it. This compromises security and allows malicious apps to get full access to the user’s data.

To mitigate that, MutableData provides fine-grained access control and more narrow-scoped data operations. This data type is an evolved version of AppendableData. It combines StructuredData and AppendableData features and improves the network efficiency, saves bandwidth, and provides a standardised approach for apps to fetch and mutate data in the network.

RFC 47 – MutableData proposes to combine StructuredData and AppendableData into a new single data type, MutableData, similar to HashMap.

pub struct MutableData {
    /// Network address
    name: XorName,
    /// Type tag
    tag: u64,
    // ---- owner and vault access only ----
    /// Maps an arbitrary key to a (version, data) tuple value
    data: BTreeMap<Vec<u8>, Value>,
    /// Maps an application key to a list of allowed or forbidden actions
    permissions: BTreeMap<User, BTreeSet<Permission>>,
    /// Version should be increased for every change in MutableData fields
    /// except for data
    version: u64,
    /// Contains a set of owners which are allowed to mutate permissions.
    /// Currently limited to one owner to disallow multisig.
    owners: BTreeSet<sign::PublicKey>,
}

The current features of Appendable Data will be covered by Mutable Data, but rather than just append, Mutable Data will support many discrete actions (e.g. “List entries”, “List keys”, "List values”, “Get value”, “Insert”, “Update”, “Delete”, etc.). These discrete actions will mutate specific key-value pairs directly on the network, rather than having to replace the entire content. Consistency and permissions will be enforced by the vaults. Mutable Data will also allow to create multiple type tags (just like Structured Data).

The reason for this change is that we want to provide granular permission control over data changes within the network (rather than on the client side). Many things, that so far happened in the launcher (so we can develop faster) but should be done by the network (like stronger enforcement of permissions), will finally move into vaults.

Secondly, we propose to introduce a new paradigm on the data type itself to handle permissions. Expanding from the owner-or-public-model, we propose to have field on the data type (called “permissions”) which maps signing keys to a list of actions that a key is allowed to perform on a particular data object. Every discrete action is checked by the vaults against the permissions assigned to that key and will only succeed when the required permissions are present.

Highlights

The proposed data type defines discrete actions on data that doesn’t require a user to replace or fetch the entire structure contents. This is enabled by functionality similar to this of the HashMap data structure or a key-value database such as Redis.


Permissions can be modified granularly by issuing actions similar to those used to update data. Only owners and apps having the ManagePermission permission must be allowed to issue such requests.


Pending writes must support granular changes in data or permissions. Ownership transfer and encrypt key changes also must be represented by separate pending writes.

Limits

The MutableData data type imposes the following limits:

  • Maximum size for a serialised MutableData structure MUST be 1 MiB;
  • Maximum entries per MutableData MUST be 100;
  • Not more than 5 simultaneous mutation requests are allowed for different keys;
  • Only 1 mutation request is allowed for a single key.

These numbers were picked as a starting point. They will be profiled and updated via testnets as the performance of the network improves.

Discussion topic for RFC 47 – MutableData


Authorize apps on behalf of the owner to mutate data

If the requests made by the permitted apps need to be charged these must all go through the Maid-Managers and they should know about the owner that an app is associated with so that they can charge the correct account.

RFC 48 – Authorise apps on behalf of the owner to mutate data details how apps route their mutation requests to Data-Managers and how revocation works.

Highlights

We require all mutations to go via the owner’s Maid-Managers. Maid-Managers will keep a list of sign::PublicKey which is the representation of the apps the owner has allowed to mutate the network on their behalf. Maid-Managers will then forward the request to the appropriate Data-Managers. The type MutableData thus does not need to store any signatures and Data-Managers will use the group authority to trust the requester of the mutation. Then they will use the permissions field to allow or disallow the mutation itself.


Ownership transfers are a special case. The apps are not allowed to do this operation. They will need to ask the Authenticator to do this. Maid-Managers shall enforce that change_mdata_owner only comes from the owner. Data-Managers shall enforce that current owner of the data matches the incoming Maid-Manager group.


Once the owner decides to revoke permission of an app to mutate network on their behalf, they will go to the Maid-Managers and delete sign_pk for the app. Hence the app can no longer perform any mutating operations on behalf of the owner now as the owner’s Maid-Managers will reject it not finding it in the list.

Discussion topic for RFC 48 – Authorise apps on behalf of the owner to mutate data


Transfer of Data Ownership
#2

Hey @frabrunelle, just a suggestion, to make it easier to comment on a RFC maybe you could copy their content on the first post of each discussion thread instead of just the link to github. This way when a quote is made we’ll be able to expand it to see it in context.


#3

This sounds pretty nice :thumbsup: And could vastly simplify a lot of app data storage activity.

Even for the browser right now using redux you have to cover a lot of these bases, and after that sync this data to the network at some point. If this is performant enough to actively store to the network this could potentially simplify a lot of app data storage. Very cool.


I wonder is there already an established pattern for when you’d go over the SDlimit? Say if you’re storing your browser history for a loooong time, you’re likely at some juncture to go over 1mb. I haven’t had chance to scope out the new data structures proper as yet, but it’s very much on my to do list. So if you you have a reference point there, @frabrunelle that would be suuper.


#4

Edit: Oops… I see for MutableData the limit is 1MiB, so I’m wrong here, apologies:

@joshuef The SD limit is 100k not 1MB unless this has changed recently.


#5

That will change with this RFC (for Mutable Data):


#6

RFCs might change so it’s easier to just include a link to GitHub :slight_smile:

see this topic for more details:


#7

Finally got some time to read through this and I like what I see! These sound like real positive steps towards a more secure and usable system.

Having both the security model and the mutation actions at the network kills two birds with one stone, IMO. Both are very desirable.

I am looking forward to seeing the fruits of this labour!


#8

So just let me see if I understood this correctly. Each app will have to import their languages version of safe-core to get bindings to the api in their language? Kind of like a safe-js does now but for whatever language they are writing their app in?

And if so, is that for webapps and regular apps?

I’m asking because I’m toying around with elm right now, and was thinking “wouldnt it be nice to have a package in elm I could import that has all the API bindings” and at first read this seem to be opening up for that. Please correct me if I’m way out field here though.


#9

That is correct.

At the beginning we will provide FFI-bindings which should allows easy including into any number of other languages.

For the browser we will have a safe-js-like DOM that directly allows you to interact with the network.

No, that is exactly what we are anticipating. And should be rather easy once the FFI is in place.


#10

That sounds quite perfect! Thanks!


#11