Biome User Management

Biome is the Splinter component for user, credential, and private key management. It isolates and securely exposes user-based information for other Splinter components. Biome stores user and credential information in a local PostgreSQL database, manages access tokens, and provides encrypted keys for other Splinter actions, such as signing transactions on behalf of a user.

Biome stores information in a local PostgreSQL database on the Splinter node. Splinter does not share any user, credential, or key information with other Splinter nodes. See Biome Database Tables for the database structure and table names.

Biome is part of the Splinter daemon, splinterd. The splinterd REST API exposes this functionality as Biome-specific endpoints. The splinterd REST API Reference provides documentation and examples for the Biome routes and request/response format.

This topic explains Biome’s architecture, then illustrates how Biome works with examples of using Biome endpoints.

Biome Architecture

Biome provides the following functions:

  • User account management: Creates and stores users by username and ID. A Splinter user has a username, access credentials, and an automatically generated user ID (UUID). Biome generates the UUID when a user is registered.

  • Key management: Encrypts and stores users’ private keys.

  • Credential management: Registers and authenticates users. The initial implementation uses usernames and passwords for authentication and is not recommended for production use.

  • Token management: Stores a refresh token for each user that can be used to issue a new access token when the previous one expires.

  • Database migration: Updates the Biome database when a new release adds or changes tables.

Biome REST API routes

Biome is part of the Splinter daemon, splinterd. The splinterd REST API exposes Biome functionality as Biome-specific endpoints. The following diagram shows the relationship of the Biome component and REST API routes with the other splinterd components and routes.

Biome architecture

Key Management in Biome

Biome’s user key management provides the capability to store and retrieve public/private key pairs and associate them with a user. The Biome implementation is a general solution that reduces the overhead of writing a new key management system for any application that needs keys. It is designed to be flexible enough to support a multitude of use cases in an enterprise environment.

The design of Biome includes the following assumptions:

  • The client application is responsible for encrypting the user’s private key (which is strongly recommended).

  • Biome does not enforce any correctness of the key pairs. The private key should never be available to Biome in plain text, which makes it impossible to check that a private key is actually associated with the public key.

  • Biome does not enforce any uniqueness of the key pairs. Though not ideal, this design supports organizational structures that associate keys with specific permissions rather than individual users.

CanopyJS Library for Saplings

The CanopyJS library provides code so that saplings (Splinter web apps) can use the key management functionality of Biome, as well as handlers to make key data available across saplings running in Canopy. This code includes a function to generate a new keypair using the secp256k1 algorithm, as well as handlers to store an active key in Canopy state or fetch the currently active key.

For example, the Profile sapling uses Biome and the CanopyJS key management library to allow an app to take the following actions:

  • Update user credentials (username or password)
  • Create, delete, and view a given user’s keys
  • Select a key as the active key

The Profile sapling encrypts the private key before sending it to Biome. This sapling is responsible for all direct communication with the Biome endpoints. For more information, see the splinter-canopyjs repository.

The libsplinter biome module

For Splinter developers, Biome functionality is available as independent submodules in the Rust-language libsplinter library, so that customized Splinter applications can choose some functions but not use others. The biome module in the libsplinter library includes the following submodules:

  • client
  • credentials
  • key_management
  • notifications
  • oauth
  • profile
  • refresh_tokens

For more information, see the biome module in the splinter Rust API Reference.

Examples: Using Biome Endpoints

To demonstrate how Biome works, this section shows examples of using the Biome REST API endpoints for the following tasks:

  • Register a new user with /biome/register
  • Log the user in with /biome/login
  • Store the new user’s keys with /biome/keys
  • Fetch a private key with /biome/keys/<public_key>
  • Verify user credentials with /biome/verify
  • Refresh an access token with /biome/token
  • Log a user out with /biome/logout

For details on each request and response, see the biome routes in the splinterd REST API Reference.

Registering a New User

The workflow for adding a new user to the Biome database has three steps: register the new user, log the user in, then add the new user’s public key and encrypted private key to the Biome database.

This example shows the first step: use /biome/register to register a new user in the Biome database.

In this example, the user name is an email address. The password is hashed because the application should not reveal the user’s plain-text password to the REST API. (The examples in this document show an abbreviated hashed password.)

    POST /biome/register
    {
         "username": "coral.reef@example.org",
         "hashed_password": "8e066d41...d99ada0d"
    }

A successful response includes the user ID (a UUID for that user).

    {
        "data": {
            "user_id": "9146dcfa-dd1d-472c-b3d4-5cfb80eea16f",
            "username": "coral.reef@example.org"
        },
        "message": "User created successfully"
    }

Logging In

This example shows the second step for adding a new user to the Biome database: use /biome/login to log the user in and get the user’s access and refresh tokens.

Note: Biome uses JSON Web Tokens (JWT) to manage user authentication and user sessions. An access token is required for interacting with all Biome endpoints (other than POST /biome/register and POST /biome/login).

The request must include the username (this example uses an email address) and a hashed password, because the application should not reveal the user’s plain-text password to the REST API. For example:

    POST /biome/login
    {
        "username": "coral.reef@example.org",
        "hashed_password": "8e066d41...d99ada0d"
    }

A successful response contains the user ID, an access token, and a refresh token. (The examples in this document show abbreviated strings for the tokens.)

    {
        "message": "login successful!",
        "user_id": "9146dcfa-dd1d-472c-b3d4-5cfb80eea16f",
        "token": "eyJ0eXAiOikZjBjOGE0I...aXNzIjoic2PEUXY70Ehc",
        "refresh_token": "QiLCJhbGcilkIjoiZjM1YW...ZC00ZWRhLWiJ9.eyJ1c2"
    }

The access token must be included in the authentication header of all requests submitted on the part of this user.

When an access token expires, use the refresh token to get a new access token (see Refreshing an Access Token).

Storing New User Keys

This example shows the final step for adding a new user: use /biome/keys to store the user’s keys in the Biome database.

This example assumes that the user’s public and private key files already exist. For information on generating these keys, see the splinter-keygen(1) man page.

Important: For security reasons, it is highly recommended to encrypt the private key. The encryption method is left to the calling application; Biome itself is agnostic to the specific encryption algorithm.

The request header must include the user’s access token from the POST /biome/login response in the previous step. The request body specifies the plain-text public key, an encrypted private key, the key’s human-readable display name, and the user ID (from the POST /biome/login response in the previous step).

    POST /biome/keys
    Authorization: bearer eyJ0eXAiOikZjBjOGE0I...aXNzIjoic2PEUXY70Ehc
    SplinterProtocolVersion: 1
    {
        "public_key": "<public_key>",
        "encrypted_private_key": "<private_key>",
        "display_name": "Key for coral.reef@example.org",
        "user_id": "9146dcfa-dd1d-472c-b3d4-5cfb80eea16f"
    }

A successful response includes the message “key added successfully”, as well as the items provided in the request.

    {
        "message": "key added successfully",
        "data": {
            "public_key": "<public_key>",
             "user_id": "9146dcfa-dd1d-472c-b3d4-5cfb80eea16f",
             "display_name": "Key for coral.reef@example.org",
             "encrypted_private_key": "<private_key>"
        }
    }

Fetching a Private Key

Use /biome/keys/<public_key> to fetch the private key from the Biome database so that the key can be used to sign a transaction.

The request header must contain the user’s access token. For example:

    GET /biome/keys/<public_key>
    Authorization: bearer eyJ0eXAiOikZjBjOGE0I...aXNzIjoic2PEUXY70Ehc

A successful response contains the encrypted private key, as well as the user’s display name (usually the same as the username) and user ID.

    {
        "data": {
            "public_key": "<public_key>",
            "encrypted_private_key": "<private_key">,
            "display_name": "Key for coral.reef@example.org",
            "user_id": "9146dcfa-dd1d-472c-b3d4-5cfb80eea16f"
        }
    }

Verifying User Credentials

Use /biome/verify to verify a user’s password by sending the username and hashed password. The request header must contain the user’s access token. For example:

    POST /biome/verify
    Authorization: bearer eyJ0eXAiOikZjBjOGE0I...aXNzIjoic2PEUXY70Ehc
    {
        "username": "coral.reef@example.com",
        "Hashed_password": "8e066d41...d99ada0d"
    }

A successful response includes a message and the user ID.

    {
        "message": "Successful verification",
        "user_id": "9146dcfa-dd1d-472c-b3d4-5cfb80eea16f"
    }

Refreshing an Access Token

When an access token expires, user-related requests return a 401 error with a message indicating that the token has expired.

Use POST /biome/token to request a new access token. Include the expired access token in the request header and put the refresh token in the request body. For example:

    POST /biome/token
    Authorization: bearer eyJ0eXAiOikZjBjOGE0I...aXNzIjoic2PEUXY70Ehc
    {
        "token": "QiLCJhbGcilkIjoiZjM1YW...ZC00ZWRhLWiJ9.eyJ1c2"
    }

A successful response body will contain the new access token.

    {
        "token": "J1c2VyX2lkIjoiZjMu_1...YWxriYX7qryl08ZEp86"
    }

Logging Out

Use /biome/logout to log a user out. This action removes the access tokens associated with the user.

The request header must contain the user’s current access token, and the request body is empty. For example:

    POST /biome/logout
    Authorization: bearer eyJ0eXAiOikZjBjOGE0I...aXNzIjoic2PEUXY70Ehc
    {}

A successful response contains a message.

    {

        "message": "User successfully logged out"
    }

Reference Information

REST API Endpoints for Biome

The splinterd REST API exposes the following Biome-specific endpoints.

/biome/keys Adds a new key, changes a key's display name, and lists all keys.
/biome/keys/{public-key} Fetches information for a given key or deletes the key.
/biome/login Authenticates a user with username and password credentials. A successful login returns a unique user ID (UUID), an access token, and a refresh token.
/biome/logout Logs a user out by removing the access tokens associated with the user.
/biome/register Creates a new user by providing a username and password credentials.
/biome/token Issues a new access token for the user with the given refresh token.
/biome/users Lists all users.
/biome/users/{user-id} Fetches the given user's information, changes their password, and deletes a user.
/biome/verify Verifies that a user's password credentials and associated access token are correct.
/biome/profiles Lists all user profiles.
/biome/profiles/{user-id} Fetches the profile information associated with the given user ID.
/biome/profile Fetches the profile information of the authenticated user.


For more information, see the biome routes in the splinterd REST API Reference.

Biome Database Tables

The following diagram shows the structure of the Biome database tables.

Biome database schema