Password Manager with 3Box

Build a ReactJS app using 3Box APIs

Ryan Pedersen

What we are building

We will be creating a ReactJS app that integrates with several of the 3Box APIs. It’s intended to be used as a password manager, but the app can also be used to store, get, or delete any “secret” key-value pair associated with any of your spaces.

We will be covering the 3Box Profiles API, profile-hover, and the 3Box Storage (Spaces) API.

🦄3Box

About 3Box
3Box is an open-source, decentralized identity layer built on IPFS and OrbitDB.

With 3Box, DApp developers do not need to maintain a centralized back end service or store data on the blockchain.

With 3Box, end-users control their data, allowing them to decide what data to share and with whom they’d like to share it.

3Box profiles are ultimately a collection of IPFS hashes mapped to OrbitDB, which then maps to the user’s blockchain account through their 3ID (3Box identity system). 3Box runs an IPFS pinning node to ensure the retention of important CID.

The documentation covers the architecture in detail.

3Box Profiles

3Box Profiles allow DApp developers to store information that is intended to be shared across apps, such as names, profile pictures, and social verifications. The Profiles API can be used anywhere developers want access to general info about users, or to incorporate a human touch instead of defaulting to a hexadecimal value.

A subset of the Profiles API is the Profile Hover plugin, a lightweight drop-in component that augments a user’s hexadecimal code by displaying their social info. Profile Hover is highly customizable and allows for a more welcoming, personal user interaction. We will use it in this app to display the authenticated user.

3Box Storage

3Box Storage allows DApp developers to perform various operations on users’ spaces, including getting, setting, and deleting both public and private information. Each user has a data store for both public and private data.

Storage is a sandboxed key-value data store that houses information related to a specific application or context. It uses IPFS for decentralized storage and OrbitDB for database structuring.

The Storage API can be used for storing any key-value pair, including preferences, settings, and sensitive information. It can also be used to store IPFS hashes that point to more complex files like images or Word docs.

3Box benefits

  • Store data with the user on IPFS and not on the blockchain when not necessary
  • See a person and not a hexadecimal value
  • Build UX-friendly DApps with a suite of out-of-the-box tools
  • Auth and Profile experience similar to already-familiar web2 apps
  • Users take ownership of their data

🗺Setting Up

This tutorial does include a couple of libraries that may be outside the scope of a basic ReactJS app — mainly, Router and SCSS. More information on both can be found in the documentation below:

Cloning app

git clone https://github.com/ryanpedersen42/s3cretkeep3er.git
npm install

Below is the directory structure of the app.

Directory structure for the project

🏗How it works

We will go into detail on the 3Box-specific actions in the app below. You can follow along in your IDE.

1. Authentication

handleAuth function

This function handles the authentication process for your app. In just a few lines of code, we confirm the user’s web3 account and use the result to take action across several 3Box APIs.

We start by prompting the user to log in with their web3 provider; we will use the returned address to start our actions with 3Box.openBox() is a static method that authenticates the user of a given ethereum address into 3box and returns the box instance of the associated address. This box instance will be saved in this.state and will be used later to change between spaces.

The Promise on line 11 awaits confirmation that the users 3Box DB is fully synced before continuing on to actions on the intended 3Box Storage Space. Once confirmed, we open up the s3cretkeep3r space and set the associated dappSpace variable to this.state.

The number of signatures required during authentication depends on the user’s prior activity in 3Box. The first time a user logs in, they will need to provide three signatures: one to create an account, one to open the box, and one to open the space.

2. Profile Hover

We use profile-hover on main-page.jsx as an out-of-the-box implementation of the Profiles API. If you want to build a custom Profile instead, there are ample resources to help — try the Builder Series on Profiles and Profiles API docs to start.

You can also take a look at the Profile Object like this:

3. Add new key-value pair

onSubmit

space.private.set() takes two strings — input key and input value — to put into our s3cretkeep3r space. The .private indicates that the key and value will be encrypted. The end-user needs to sign to access their private spaces for each session they open.

To put a public key-value pair, we would use .public instead of .private

For more information on the encryption of private data, documentation can be viewed here.

4. Get key-value pair

getSecret function

The space.private.get() function works similarly to the space.private.set() function, but it gets the value of the string that is passed in. If there is no such key, it returns undefined.

5. Delete key-value pair

deleteSecret

This function takes in a string and removes the value of the associated key. It returns Boolean — true if successful.

6. Log Out

handleLogout

box.logout() clears the local cache and logs the user out. If this is called, the user will need to sign a consent message the next time you call openBox().


💭 Using These Tools

The tools listed above should be applicable to a variety of apps, so whether you are building a decentralized Reddit, Twitter, or an Action DApp, feel free to plug and play. Full documentation here.


Bonus: miscellaneous errors

TypeError: Cannot read property ‘ciphertext' of null
>Make sure you have error handling for the returned values as some may be undefined. (More info here)

Uncaught(in promise) TypeError: Cannot read property 'sendAsync' of undefined
>Comes from the sendEth function in index.js of 3Box-js. Check to make sure you are passing in the right value to openSpace().

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade