Block Store

Many users still manage their own credentials when setting up a new Android device. This manual process can become challenging and often results in a poor user experience. The Block Store API, a library powered by Google Play services, looks to solve this by providing a way for apps to save user credentials without the complexity or security risk associated with saving user passwords.

The Block Store API allows your app to store user credentials that it can later retrieve to re-authenticate users on a new device. This helps provide a more seamless experience for the user, as they don't need to see a sign-in screen when launching your app for the first time on the new device.

The benefits to using Block Store include the following:

  • Encrypted credential storage solution for developers. Credentials are end-to-end encrypted when possible.
  • Save tokens instead of usernames and passwords.
  • Eliminate friction from sign-in flows.
  • Save users from the burden of managing complex passwords.
  • Google verifies the user's identity.

Before you begin

Configure your app

  1. In your project-level build.gradle file, include Google's Maven repository in both your buildscript and allprojects sections:

    buildscript {
        repositories {
            google()
        }
    }
    
    allprojects {
        repositories {
            google()
        }
    }
    
  2. Add the dependencies for the Block Store API to your module's app-level Gradle file, which is usually app/build.gradle:

    dependencies {
      implementation 'com.google.android.gms:play-services-auth-blockstore:16.0.2'
    }
    

How it works

When a user signs into your app, you can save the authentication token that you generate for that user to Block Store. This is done by calling setBytes() on an instance of StoreBytesData.Builder to store the user's credentials to the source device. After you save the token with Block Store, the token is encrypted and stored locally on the device.

The following code snippet shows how to save the authentication token:

val client = Blockstore.getClient(this)
val data = StoreBytesData.Builder()
        .setBytes(/* BYTE_ARRAY */)
        .build()
client.storeBytes(data)
        .addOnSuccessListener{ result ->
            Log.d(TAG, "Stored: ${result.getBytesStored()}")
        }

Later on, when a user goes through a device-to-device restore flow on a new device, Google Play services first verifies the user then retrieves your Block Store data. The user has already agreed to restore your app data as a part of the restore flow, so no additional consents are required. When the user opens your app, you can request your token from Block Store by calling retrieveBytes(). The retrieved token can then be used to keep the user signed in on the new device.

val client = Blockstore.getClient(this)
client.retrieveBytes()
        .addOnSuccessListener { result ->
            Log.d(TAG, "Retrieved: ${String(result)}")
}