Getting Started With SSX

Build a Web3 DAO Authentication App With React + Express + SSX


9 min read

Getting Started With SSX

What Is SSX?

"SSX is a library that enables you to easily add user authentication, session management, and more to your dapp."

D_D Newsletter CTA

Okay, But What Is It?

It's an app that allows you to administer authentication sessions for native Sign-In With Ethereum (SIWE pronounced see-we) and have a way to see stats on those sessions.

SSX Dashboard

Why Is This Needed?

Abstracting Functionality

Could you build out your own user session manager with SIWE? Yes, you could, but like everything, why would you keep building the same tool systems repeatedly? Just like when services like Auth0 came into the market, we abstracted the need to try to build and manage authentication services.

Easy Implementation

It's also faster to get up and running with sessions without having to build it yourself for your existing backend.

SSX Implementation With Express.js

Multisig Wallet DAO Logins

SSX has also been working with Safe (Formally Gnosis-Safe) to allow for DAO Logins.

"SSX enables an easy way for users to sign in on behalf of a Gnosis Safe multisig on your platform that they have been delegated access to."

Safe Sign-In With Ethereum Delegate Manager

The Safe Sign-In With Ethereum Delegate Manager is an excellent way to allow Safe wallet owners to delegate or give permission to other non-owners access accounts that the owners may create. Think of it as a more accessible Web3 account and password manager for other users.


Before we go any further, ensure you have the following installed on your computer so you can go through the following code examples.

  • NVM or node v18.12.1 or greater
  • yarn v1.22.19 or greater

Building An SSX React + ExpressJS Application

To start, we will demonstrate a simple application utilizing some of the existing web libraries and packages Spruce ID defined for us for SSX.


SSX Account Setup

We'll first set up our account at

SSX App Login

Once set up, you'll start by creating a New Project.

SSX App Create Your First Project

SSX App Create Project

NOTE: This API key will be hidden afterward, so take note of it. You can, of course, generate a new one in the project settings later.


Once complete, you should see a new project in your dashboard.

SSX App Project Dashboard

We should all be set on this end.

React DApp

Next up is to set up our React application.

The good news is that the Spruce ID has a bootstrap dapp that we can take advantage of.

In your Terminal, start by running and answering the following prompts.

yarn create @spruceid/ssx-dapp;

# Expected Outputs/Prompts:
# ? What is the name of your project? › my-ssx-dapp
# ? Would you like to use TypeScript? › no / yes
# ? Which will be your default provider? › - Use arrow-keys. Return to submit.
# ❯   MetaMask
#     Web3Modal
# ? Which features would you like to enable? ›
# Instructions:
#     ↑/↓: Highlight option
#     ←/→/[space]: Toggle selection
#     a: Toggle all
#     enter/return: Complete answer
# ◉   Dao Login
# ? Provide the SSX enabled server URL (leave blank if none) ›

Next, we need to start the application.

# From ./my-ssx-dapp

yarn start;

# Expected Output:
# Compiled successfully!
# You can now view my-ssx-dapp1 in the browser.
#   Local:            http://localhost:3000
#   On Your Network:
# Note that the development build is not optimized.
# To create a production build, use yarn build.
# webpack compiled successfully
# No issues found.

SSX Example Dapp

What this code offers is an easy implementation of handling wallet interactions. Still, you'll notice that when you perform a SIWE interaction, no network requests go back to issue sessions.

SSX Example Dapp SIWE Not Network Requests

This is because we didn't add an SSX enabled server URL in our initial prompts with yarn create @spruceid/ssx-dapp. To support this, we'll change our settings to allow this server.

File: ./my-ssx-dapp/src/ssx.config.js

const getSSXConfig = async () => {

  return { 
        enableDaoLogin: !!(process.env.REACT_APP_SSX_DAO_LOGIN === "true"),
        // ADD THIS LINE
        providers: { server: { host: process.env.REACT_APP_SSX_METRICS_SERVER ?? "" } },

export default getSSXConfig;

We must also add support for the environment variable in our .envfile.

File: ./my-ssx-dapp/.env


You'll notice now, when we try to perform the authentication process again, it won't work because our backend server isn't set up.

SSX Example Dapp SIWE No Longer Working

Don't worry; this is expected because we need to set up our backend.

ExpressJS Backend

To quickly get up to speed with an existing backend, we'll take advantage of an example Express API from the SpruceID SSX Git Repository.

But first, make sure you get an Infura RPC API Key.

Infura RCP API Key

Next, we'll clone the repository and start working on the example ExpressJS API.

# From ./

git clone;
cd ssx;
yarn install; # This first installation will be needed to set up in the root first to get the proper dependencies setup because the repository is set up with Lerna

Next, we need to configure our environment variables with all the values we've set up.

File: ./ssx/examples/ssx-test-express-api/.env


With that set, let's start our backend server.

# From ./ssx/examples/ssx-test-express-api/

yarn dev;

# Expected Output:
# 9:42:10 p.m. - Starting compilation in watch mode...
# [0] 
# [0] 
# [0] 9:42:11 p.m. - Found 0 errors. Watching for file changes.
# [1] ⚡️[server]: Server is running at http://localhost:5001

We should see our root endpoint on our backend ExpressJS API if everything is working correctly.

SSX ExpressJS API Root Endpoint

Dashboard Stats

Now that we have our frontend and our backend setup let's try Sign-In With Ethereum again.

You should see now that server requests are working and should be submitted to our dashboard.

SSX Example Dapp Network Working

If we go to our SSX Dashboard, we should see our session stats that also pull in some additional information on users.

SSX App Project Dashboard Stats 1

SSX App Project Dashboard Stats 2

There we go; we utilized the sample bootstrap code, demonstrating SSX with a frontend and backend application.

DAO Login - Sign-In with Ethereum Delegate Manager

For this step, you'll need a Safe multisig wallet setup beforehand. I won't go into setting the initial wallet up, but once you do have a Safe multisig wallet setup go this page to utilize the Safe Sign-In With Ethereum Delegate Manager App.

You can also access different chains by changing the query param for chain=eth to chain=gor. Unfortunately you'll need to manually change the query params because the app is not currently part of the default Safe App list, yet.


Safe Wallet Adding Delegate

For demonstration purposes, I set a Safe wallet with 3 Safe Owners (Wallet A, B, & C) where 2 of 3 owners would need to approve transactions.

Safe Wallet - Sign-In with Ethereum Delegate Manager App

NOTE: Remember to use it at your own discretion.

Safe Wallet - Sign-In with Ethereum Delegate Manager App Disclaimer

Safe Wallet - Sign-In with Ethereum Delegate Manager App Clipboard Access

To start, I'm going to add another wallet address as a delegate that isn't one of the Safe owners. You can search with ENS names to automatically find the correct wallet address.

Safe Wallet - SIWE Delegate Manager Delegate Address

⚠️ WARNING: Pay attention to the nonce value so that it is the following sequential transaction number in the queue from your past transaction history (Example current nonce in your transaction history is 1, make sure yours is 2). If it's different than the following number, you will need to wait for other transaction nonces to be executed before this one can be executed. I have made this mistake too many times.

To visit your transaction history, go to:

Safe Wallet - SIWE Delegate Manager Delegate Signature Request 1 Wallet A

Once Wallet A accepts the first signature, it will go into pending to accept another signature from Wallet B or C to approve it.

Safe Wallet - SIWE Delegate Manager Delegate Delegate Pending

I'll switch to Wallet B in MetaMask and go to my Transactions > Queue.

Safe Wallet - Transactions Queue

Approve the signature request.

Forgive the nonce difference; this is where I made that mistake I mentioned before.

Safe Wallet - SIWE Delegate Manager Delegate Signature Request 1 Wallet B

I'll switch back to Wallet A (because it has some actual ETH in it) to finalize and execute the transaction.

Forgive the messiness of different transactions; again, it was the nonce issue from before.

Safe Wallet - SIWE Delegate Manager Delegate Signature Request Ready Wallet B

Safe Wallet - SIWE Delegate Manager Delegate Signature Request Execute Transaction Wallet A

Now to get back to the Delete Manager App. It is still early on, so you can't find the app in the Safe Apps section, so you'll need to go to this link again.

Safe Sign-In With Ethereum Delegate Manager

If everything looks good, we should see our new delegate.

Safe Sign-In With Ethereum Delegate Manager New Delegate

Different Frontend Code Example

Next, we're not going to use the previous frontend that we just set up; instead, we're going to utilize another existing example app that was already created in the SSX repository. This is to save time on the additional functionality details and demonstrate the delegate functionality.

From the same ssx repository we just cloned, we're going to access the ssx-test-app.

cd ./ssx/examples/ssx-test-dapp;

Update our .env file:

File: ./ssx/examples/ssx-test-dapp/.env


Make sure our other app has stopped running and run this new application.

# From ./ssx/examples/ssx-test-dapp;

yarn start;

# Expected Output:
# Compiled successfully!
# You can now view ssx-test-dapp in the browser.
#   Local:            http://localhost:3000
#   On Your Network:
# Note that the development build is not optimized.
# To create a production build, use npm run build.
# webpack compiled successfully

This version of the app should look similar to the previous one, but with some additional functionality and configurations that we can set manually. We'll now sign in with the delegate wallet we just set up in our Safe wallet.

Leave all the preferences as they are except the daoLogin to On.

SSX Example Test Dapp With Preferences

When we try to sign in with our delegated wallet, we should see a different prompt asking us if we want to sign in as ourselves or as a delegate of the Safe wallet address. Select the Safe wallet and click Continue.

SSX Example Test Dapp Account Sign-In As Safe Wallet

Sign the message, and we should now see that we are signed in as the Safe wallet address.

SSX Example Test Dapp Signed In As Safe Wallet

And that's it! You successfully implemented an app using SIWE with SSX and using a delegate with a Safe Wallet.

Code Repository

Here is the original code repository with all the packages and examples.

D_D Newsletter CTA

What's Next

Stay tuned to the next tutorial, where I will be looking at building a NextJS SSX app, a ViteJS SSX app, and hopefully creating a sample monorepo with some additional gated functionality.

If you enjoyed this tutorial, give it some praise, and share it on Twitter.

If you have questions or just want to follow me for updates, make sure to follow me at @codingwithmanny