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 ownsafe_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
andinsert
- which we will refer to as theBASIC
-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 typeMutableData
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 thepermissions
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 thatchange_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.