What is ROLA?
ROLA (Radix Off-Ledger Authentication) is a challenge-response protocol that lets your backend verify a user owns a Radix account or persona — without submitting any on-ledger transaction. It's the Radix equivalent of "Sign-In with Ethereum" but uses the native Radix Wallet.
How It Works
- Backend generates a challenge — a random 32-byte hex string stored with a 5-minute expiry
- Frontend requests proof — sends the challenge to the Radix Wallet via
requestProofOfOwnership() - User approves in wallet — wallet signs the challenge with the account's private key (Ed25519 or secp256k1)
- Frontend sends proof to backend — contains public key, signature, and curve type
- Backend verifies — checks the signature, confirms the public key matches the account's
owner_keysmetadata on ledger, and deletes the challenge
Implementation
1. Generate Challenges (Backend)
import crypto from 'crypto'
// Store challenges with expiry (use Redis, DB, or in-memory Map)
const challenges = new Map<string, { expires: number }>()
function createChallenge(): string {
const challenge = crypto.randomBytes(32).toString('hex')
challenges.set(challenge, {
expires: Date.now() + 5 * 60 * 1000 // 5 minutes
})
return challenge
}2. Request Proof (Frontend)
import { DataRequestBuilder } from '@radixdlt/radix-dapp-toolkit'
// Fetch challenge from your backend
const challenge = await fetch('/api/auth/challenge').then(r => r.json())
// Request proof of account ownership
const result = await rdt.walletApi.sendRequest(
DataRequestBuilder.accounts()
.atLeast(1)
.withProof(challenge)
)3. Verify Proof (Backend)
import { Rola } from '@radixdlt/rola'
import { RadixNetwork } from '@radixdlt/babylon-gateway-api-sdk'
const rola = Rola({
networkId: RadixNetwork.Mainnet,
applicationName: 'My dApp',
dAppDefinitionAddress: 'account_rdx...',
expectedOrigin: 'https://my-dapp.com'
})
// Verify the signed challenge
const result = await rola.verifySignedChallenge({
challenge: challengeHex,
proof: { publicKey, signature, curve },
address: accountAddress,
type: 'account'
})
if (result.isOk()) {
// Create session (JWT, cookie, etc.)
}Delete used challenges
Always delete a challenge after verification — successful or not. This prevents replay attacks where a captured proof is resubmitted.
When to Use ROLA
| Use Case | Auth Method |
|---|---|
| User login / session creation | ROLA |
| Prove account ownership to backend | ROLA |
| Transfer assets or call components | On-ledger transaction |
| Gate content by badge ownership | ROLA + Gateway query |
ROLA proves identity. On-ledger transactions perform actions. For token-gated access, verify ownership via ROLA then query the account's resources via the Gateway SDK.
