Non interactive sign in with App Private Key in UserSession

@jude, @hank, @aaron, @yukan

I read that it’s possible to do non-interactive login with the App Private Key in blockstack.js UserSession: http://blockstack.github.io/blockstack.js/classes/usersession.html

A user can be signed in either directly through the interactive sign in process or by directly providing the app private key.

Is there any code samples on how to log a user in non-interactively and receive a JWT that I can pass back to Gaia as a bearer token if I already have an App Private key ? (i.e avoiding the browser redirect)

1 Like

Quick thought: I know you can use userSession.handlePendingSignIn(authResponseToken) manually, but you’d still have to create a token.

Seems like the perfect use case for SimpleID :wink:

In all seriousness, depending on how you want to do this, we may be able to help. Just let me know.

1 Like

Similar to SimpleID, the idea is to make converting an anonymous user to a full blown Blockstack ID a journey. Most users quit using an app when they see a weird foreign login thingy and I don’t even want the user to commit to having to choose a username and password upfront until they test app features for a period of time. My intention with this flow is to only defer logging in with blockstack but still be able to use Gaia.

Journey

  1. anonymous user (30 seconds - 1 minute, localstorage only). get a feel for the app
  2. local pub/priv key user (1 day to a week) . use most features and gaia
  3. full blockstack user ( 1 week + introduce them to blockstack id and ecosystem of apps )

So the obvious solution it to create a local key pair and store it on the device to authenticate the user. I am only targeting native (React Native) so the client will have access to SecureStorage. So I can store a seed locally and never have to send it to a server. (keybase.io has a great flow I want to replicate, but also integrate with blockstack). Then eventually in the journey the user will enjoy the app enough and build up enough trust that they will want to unlock all features. At this point they will register a Blockstack ID and be introduced to the apps/browser/ecosystem.

So far I pulled down parts of the Blockstack Browser code to initialize a wallet, create an app account, but i do not know how to obtain a jwt via the App Private key: [UPDATE: code below works now]

import { InstanceDataStore } from 'blockstack/lib/auth/sessionStore';
import { UserData } from 'blockstack/lib/auth/authApp';
import * as bip39 from 'bip39';
import * as bip32utils from 'bip32-utils';
import * as bitcoin from 'bitcoinjs-lib';
import { randomBytes } from 'crypto';
import * as blockstack from 'blockstack';
import {getBlockchainIdentities} from '@utils'; // copied from the blockstack browser project utils https://github.com/blockstack/blockstack-browser/tree/master/app/js/utils
...

   ///
   /// 1) init wallet
   ///
    let masterKeychain = null
    const STRENGTH = 128 // 128 bits generates a 12 word mnemonic
    // save seed phrase to SecureStorage on the device, allow the user to backup 
    let backupPhrase = bip39.generateMnemonic(STRENGTH, randomBytes)
    console.log(backupPhrase);
    const seedBuffer = await bip39.mnemonicToSeed(backupPhrase)
    masterKeychain = await bitcoin.HDNode.fromSeedBuffer(seedBuffer)
    // const ciphertextBuffer = await encrypt(new Buffer(backupPhrase), 'password');
    // const encryptedBackupPhrase = ciphertextBuffer.toString('hex')
   
    ///
    ///2) create blockchain identity
    ///
    // skip identity 0 for blockstack browser use
    let identitiesToGenerate = 2; 
    const {
      identityPublicKeychain,
      bitcoinPublicKeychain,
      firstBitcoinAddress,
      identityAddresses,
      identityKeypairs
    } = getBlockchainIdentities(masterKeychain, identitiesToGenerate)
    let appPublicKey = identityKeypairs[1].address;
    let appPrivateKey = identityKeypairs[1].key;

    /// 3)  get jwt so i can write to gaia
    // see https://forum.blockstack.org/t/creating-a-usersession-using-app-private-key/8096/4
   const appConfig = new blockstack.AppConfig(
          ['store_write', 'publish_data'], 
          'goodtimes.io' 
    )
    const userData: UserData = {
      username: '',
      decentralizedID: '',
      appPrivateKey: appPrivateKey,
      authResponseToken: '',
      hubUrl: 'https://hub.blockstack.org',
      identityAddress: appPublicKey,
      profile: null,
    }

    const dataStore = new InstanceDataStore({ 
        appPrivateKey: appPrivateKey, 
        hubUrl: 'https://hub.blockstack.org',
        userData: userData
    });

    const userSession = new blockstack.UserSession({
      appConfig: appConfig,
      sessionStore: dataStore
    });

    // 4) putFile (the jwt for gaia is injected via the userSession code above)
    userSession.putFile('goodtimes.json', '{"blockstack":"rocks"}');

     /// 5) eventually register a name when the user wants to become a full user and own a blockstack ID. They can export their backup phrase from there devices SecureStorage on the client side and import it into the blockstack browser. 

Try out this option here:

1 Like

@Irikefe41

Awesome thanks for link! It worked. I updated the code above for the entire flow.

1 Like