Skip to main content

Overview

Enables applications to let users sign in seamlessly using their Decentralized Identifiers (DIDs). Think of it as “Login with Google” — but trustless, privacy-preserving, and self-sovereign.

Key Capabilities

  • Authenticates DID Ownership: Authenticates users by cryptographically proving ownership of their DID
  • Enables Trustless Authentication: Removes reliance on centralized identity providers.
  • Delivers a Familiar Web2 Experience: Sign-in feels like any social login — the user clicks a button and approves in their wallet, with no passwords or seed phrases to manage.

Authentication Flow

The Login with Billions process verifies user identity through DID ownership.
1

Initiate Sign-In

The user selects Login with Billions in the application. This triggers a backend call to /api/sign-in, which creates a new authentication request session.
2

Open Billions Wallet

The frontend takes the authentication request, encodes it in Base64, and embeds it into a Universal Link. This link opens the Billions Wallet, prompting the user to authenticate.
3

User Approves

The user approves the sign-in in the Billions Wallet. The wallet generates a signed JWZ (JSON Web Zero-knowledge) token — a verifiable proof of DID ownership.
4

Wallet Posts to Callback

The wallet sends a POST request to your backend /api/callback endpoint containing the sessionId and the signed JWZ token.
5

Backend Verifies the JWZ

Your backend verifies the JWZ token using the Billions Verifier, confirming the authenticity of the user’s DID.
6

Session Created

Upon successful verification, the user’s DID is confirmed. Create or update their session in your database — the DID acts as a persistent identity for all future sign-ins.
7

Access Granted

Your application recognizes the user, grants access, and can use the verified DID for personalized or gated experiences.

Setup Instructions

Before you begin, ensure the following environment requirements are met:

Prerequisites

  • Public URL for callbacks (use ngrok for local development)

Example Repository

The steps below walk through the reference implementation — clone it to follow along. The code snippets on this page are its index.js, and the repo includes the ./static frontend used in the testing steps.

1. Server Configuration

Sets up Express server with required middleware and routes for handling authentication requests and callbacks.
Testing Tip: Use the sample frontend in ./static to test Universal Link handling and callback processing. When moving to production, update URLs, enable HTTPS, and use environment variables for configuration.

2. Authentication Request Handler

Generates basic authentication requests with empty scope and stores them with unique session IDs for later verification.
Get Your Verifier DID: Sign in to your Billions Wallet and copy your profile DID to use during setup.
This is where Universal Links come into play. Your frontend takes the auth request returned by getAuthRequest(), encodes it in Base64, and embeds it into a Universal Link, which redirects the user to the Billions Wallet. The wallet processes the request, prompts the user to sign, and then posts a signed JWZ (JSON Web Zero-knowledge) token to your callback endpoint. That JWZ is what your backend verifies to confirm DID ownership — delivering a seamless login flow across web and mobile.Example link format:
  • Base URL: https://wallet.billions.network/ — Billions Wallet endpoint
  • Fragment: #i_m= — parameter carrying the Base64-encoded auth request

3. Verification Callback Handler

Receives JWZ token as a callback, validates them against stored authentication requests, and confirms user DID ownership.
You’ve successfully verified DID ownership. To turn this into a complete login, store user session details by their DID in your database. The DID acts as a persistent identity, allowing your app to recognize returning users. When a user logs in again with the same Billions Wallet, they’ll present the same DID, letting your application instantly identify them and deliver the right personalized experience — decentralized, secure, and private.

Testing Steps

  1. Visit your app: http://localhost:8080
  2. Test universal link: Click “Login with Billions” button
You can test the full authentication loop — from generating the auth request to verifying the DID — ensuring your app correctly recognizes verified users.

Troubleshooting

The wallet POSTs the JWZ token to your /api/callback endpoint from outside your machine — so hostUrl must be a publicly reachable URL, not localhost. For local development, run ngrok and use the ngrok HTTPS URL as hostUrl. If the callback still doesn’t arrive, confirm the auth request’s callback URI includes the sessionId query parameter.
Auth requests are stored in an in-memory Map, so restarting the server clears all pending sessions — any link generated before the restart will fail. Each session is also deleted after its first callback (requestMap.delete), so a verification link can’t be replayed. In both cases, start a fresh sign-in to generate a new auth request.

Going Further: Beyond Basic Login

Once DID-based login is in place, the same identity can power other authentication experiences — crypto wallet sign-ins, verification against Billions credentials, or 2FA — all anchored to a single decentralized identity.