Adding
Decentralized IDs
and
User-Owned Storage
to a
React App

Friedger Müffke

Dev Day 2019

Berlin, 25 May 2019

slides.com/friedger/devday19-berlin/live

Friedger Müffke

 

PhD in Bristol, UK

 

Android/Web Developer

 

friedger.id

 

@friedger
@social.nasqueron.org

 

@fmdroid@twitter

Engineering Partner
Blockstack

 

Founder Droidcon

 

Founder OpenIntents

1960

2020

2000

1980

2040

Mainframe era
IBM

Decentralized era
Blockstack ?

Cloud era
Google

Desktop era
Microsoft

Next Era in Computing

All About
Data

Become a User

  • Use decentralized app (app.co)
  • Share your experience

Open source!

Contribute and get rewarded!

Decentralized Applications
Components

Decentralized Applications

Verticals

Decentralized Applications
Components

Decentralized Identity

You

You to Carol as sibling

You to PwC as employee

You to Germany as citizen

You to Bob as friend

Relationships

You

Your facts of birth

Your credit history

Your health records

Your education

Attributes

You

Your cloud service

Your mobile device

Your lawyer

Your broker

Agents

You

Relationships

Attributes

Agents

You are all
of these

Decentralized Identity

  • Self-sovereign
  • Cryptographically verifiable
  • Person vs. profiles

 

  • No more passwords, no more social logins
  • W3C working group
  • 27 identity provider methods

 

did:example:123456789abcdefghi

App

App

App

Authenticator

Network

Decentralized Identifier

Login Request

š© microsoft.com/ownyouridentity

blockstack.org/install

browser.blockstack.org

Create Blockstack ID

Create Blockstack ID

Protect Blockstack ID

Recover Blockstack ID

Use Blockstack ID

Sign In

Define your App Configuration:

  • Scope
  • App domain
  • Redirect path
  • Manifest path

Sign In

yarn add blockstack
import {UserSession} from 'blockstack'

const userSession = new UserSession()

Provide a sign in button

Sign In

document.getElementById('signin').onclick = () => {
  userSession.redirectToSignIn()
}

And call redirectToSignIn()

  • The domain name your app is served from.
  • The permissions and data your app is requesting.
  • Your app's name.
  • Your app's logo.

Sign In

Sign In

// Check for the auth response token in the URL, 
// provided by the browser redirect.
if (userSession.isSignInPending()) {

   // Decodes the token and retrieves user data.
   userSession.handlePendingSignIn()
.then((userData) => {
       // Refresh main page once signed in.
       window.location = window.origin 
     })
}

Sign In

if (userSession.isSignInPending()) {
  ...

} else if (userSession.isUserSignedIn()) {
   var userData = userSession.loadUserData()
   
   // Do something with user profile data..
   showProfile(userData.profile)
}

 

Sign In

{
 "username": "matt.id",
 "profile": {
   "name": "Matthew Little",
   "image": [{
     "name": "avatar",
     "contentUrl": "https://gaia-matt.com/1159ZPz88pypemHP84SMacuJWa3XmFSKcv/avatar.png"
   }]
 },
 "email": "matthew@blockstack.com",
 "decentralizedID": "did:stack:1159ZPz88pypemHP84SMacuJWa3XmFSKcv",
 "hubUrl": "https://gaia-matt.digitaloceanspaces.com/1QHGBN4d2WtnHgEFhsMpAqcJAL2Sy76zoK/",
 "appPrivateKey": "6660d3ce7f79038aa5cadb7305897d9a20cfd95ed764c28bd3ffd2618c610553"
}

Example User Data

Sign In

{
 "username": "matt.id",
 "profile": {
   "name": "Matthew Little",
   "image": [{
     "name": "avatar",
     "contentUrl": "https://gaia-matt.example.com/1159ZPz88pypemHP84SMacuJWa3XmFSKcv/avatar.png"
   }]
 },
 "email": "matthew@blockstack.com",
 "decentralizedID": "did:stack:1159ZPz88pypemHP84SMacuJWa3XmFSKcv",
 "hubUrl": "https://gaia-matt.digitaloceanspaces.com/1QHGBN4d2WtnHgEFhsMpAqcJAL2Sy76zoK/",
 "appPrivateKey": "6660d3ce7f79038aa5cadb7305897d9a20cfd95ed764c28bd3ffd2618c610553"
}

Example User Data

App Key Generation

© Cogarius, Brussels

More APIs

None for private key so far

Decentralized Storage

Decentralized Storage

  • Diversity in locations
  • Distributed vs. self-controlled

 

Server-less apps

User based (S3, Azure,..)

Content based (IPFS, Storj, SSB, ..)

Address based (Gaia)

 

Gaia Storage

Address-based access protocol

Apps for My Data

My storage

Alice's storage

Apps for My Data

My storage

Write data

  var statusMsg = 'Hello! 🚀'

  userSession.putFile('status.txt', statusMsg)
    .then(() => {
      console.log('file updated!')
    })

Gaia Storage

Read data

  
  userSession.getFile('status.txt')
    .then((statusMsg) => {
      console.log('Status: ' + statusMsg)
     })

Gaia Storage

   Console
   > Status: Hello! 🚀

Sharing Data/Multi-user apps

  "apps": {
   "https://app.graphitedocs.com": "https://gaia-matt.com/1QHGBN4d2WtnHgEFhsMpAqcJAL2Sy76zoK/",
   "https://helloblockstack.com": "https://gaia-matt.com/1KBU9qxDg8xMgyFdwiVDGU4RZr16Z7TB2S/"
  }

Gaia Storage

publish_data

scope in AppConfig:

Sharing Data/Multi-user apps

   // Upload unencrypted, public file (logged in as friedger.id)
   var options = { encrypt: false }
   var statusMsg = 'Hello! 🚀'
   userSession.putFile('status.txt', statusMsg, options).then(() => {
     console.log('uploaded publicly accessible file!')
   })

Gaia Storage

Sharing Data/Multi-user apps

   // Get file for specific user (logged in as alice.id)
   var options = {
     username: 'friedger.id',
     decrypt: false
   }
   userSession.getFile('status.txt', options).then((msg) => {
     console.log(`Got status for ${options.username}: ${msg}`)
   })

Gaia Storage

Sharing Data/Multi-user apps

   // Upload unencrypted, public file (logged in as friedger.id)
   var options = { encrypt: false }
   var statusMsg = userSession.encryptContent('Hello! 🚀',  
                                               { publicKey: alicePubKey })
   userSession.putFile('status.txt', statusMsg, options).then(() => {
     console.log('uploaded publicly accessible file!')
   })

Gaia Storage

Sharing Data/Multi-user apps

   // Get file for specific user (logged in as alice.id)
   var options = {
     username: 'friedger.id',
     decrypt: false
   }
   userSession.getFile('status.txt', options).then((encMsg) => {
     var msg = userSession.decryptContent(encMsg, 
                                             { privateKey: myPrivKey})
     console.log(`Got status for ${options.username}: ${msg}`)
   })

Gaia Storage

Indexer

Data Flow

Share document privately

OI Calendar

cal.openintents.org

react-redux CRUD + bigcalendar
https://github.com/yasnaraj/react-calendar-events-example

Add Auth Reducer

Update Event Reducer

Developer Tools

  • Authentication
  • Storage (Gaia)
    • Files
    • Collections
  • Encryption
  • In-app payment

Javascript
Android, iOS, React Native
 

Gatsby starter library

yeoman generator-blockstack

Client side

Developer Tools

Infrastructure
 

blockstack-core

gaia

Integrations
 

omniauth-blockstack

blockstack-ruby

Server side

App Mining

The better the app,
the more you earn.

  • app.co/mining
  • Monthly rating
  • Monthly payout
    currently: $100k

App Reviewers

  • Product Hunt: Innovation
  • TryMyUI: Usability
  • New Internet Labs: Good Citizenship
  • Awario: Awareness

Ranking

Rewards

Review the reviewers

Future

  • Bigger monthly payout
  • Long-tail
  • Payout in STX
    (mining reward distribution)

Hackathon

Adding Decentralized IDs and User-Owned Storage to a React App

By friedger

Adding Decentralized IDs and User-Owned Storage to a React App

DevDay 2019

  • 1,150