Sigma Auth
Reference

The Sigma Auth backup service provides secure storage and retrieval of encrypted Bitcoin key backups.

Authentication

Use the JWT access token from the OAuth flow:

Authorization: Bearer <access_token>

Endpoint Authentication Requirements

Authenticated Endpoints

These endpoints require authentication to protect user data:

EndpointMethodAuthenticationDescription
/api/backupGETBearer tokenRetrieve your encrypted backup by BAP ID
/api/backupPOSTBearer tokenStore encrypted backup
/api/backup/statusGETBearer tokenCheck backup status
/api/backup/link-oauthPOSTBearer tokenLink OAuth account to Bitcoin identity

Public Endpoints

These endpoints are intentionally public to enable cross-device restore:

EndpointMethodAuthenticationDescription
/api/backup?oauthId=provider|accountIdGETNone (OAuth ID required)Retrieve backup by OAuth account

Authentication Examples

Example Request

// After OAuth authentication
const response = await fetch('https://auth.sigmaidentity.com/api/backup/status', {
  headers: {
    'Authorization': `Bearer ${accessToken}`
  }
});

Security Design

Why OAuth Backup Retrieval is Public

The /api/backup?oauthId=... endpoint doesn't require authentication because:

  1. Enables cross-device restore - Users can restore from a new device without their Bitcoin key
  2. OAuth provider verification - The OAuth provider already verified the user's identity
  3. Client-side encryption - Backups are encrypted and require a password to decrypt
  4. No sensitive data exposed - Only encrypted blobs are returned

Protection Mechanisms

Even though OAuth backup retrieval is public, it's secure because:

  • Strong encryption: AES-256-GCM encryption with user-chosen passwords
  • OAuth verification: Must prove ownership of the OAuth account
  • Rate limiting: Prevents brute force attempts
  • No key exposure: Private keys are never transmitted or stored in plaintext

Best Practices

For Storing Backups

import { encryptBackup, type WifBackup } from 'bitcoin-backup';

// 1. Authenticate user
const accessToken = await authenticateUser();

// 2. Create backup object and encrypt client-side
const backup: WifBackup = {
  wif: privateKey.toWif(),
  label: 'My Wallet',
  createdAt: new Date().toISOString()
};
const encryptedBackup = await encryptBackup(backup, password);

// 3. Store encrypted backup
await fetch('https://auth.sigmaidentity.com/api/backup', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    encryptedBackup: encryptedBackup,
    oauthProvider: 'google', // Optional: link to OAuth account
    oauthId: '123456789'     // Optional: OAuth account ID
  })
});

For Retrieving Backups

// Authenticated retrieval by BAP ID (when user has their key)
const backup = await fetch('https://auth.sigmaidentity.com/api/backup?bapId=Go8vCHAa4S6AhXKTABGpANiz35J', {
  headers: {
    'Authorization': `Bearer ${accessToken}`
  }
});

// OAuth-based retrieval (for cross-device restore, no auth required)
const oauthBackup = await fetch(
  'https://auth.sigmaidentity.com/api/backup?oauthId=google|123456789'
);

// Both return the same format:
const data = await backup.json();
// { backup: "encrypted_blob_string" }

For Linking OAuth Accounts

// Link an OAuth account to your BAP ID for recovery
// Useful when you already have a backup but want to add a new OAuth recovery method
await fetch('https://auth.sigmaidentity.com/api/backup/link-oauth', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    provider: 'google',
    providerAccountId: '123456789'
  })
});

// Response:
// {
//   success: true,
//   message: "OAuth account linked successfully",
//   bapId: "Go8vCHAa4S6AhXKTABGpANiz35J"
// }

// Error if account already linked to different identity:
// {
//   error: "This OAuth account is already linked to another identity",
//   existingBapId: "DifferentBapId123",
//   code: "OAUTH_ALREADY_LINKED"
// }

Error Responses

Authentication Failures

{
  "error": "unauthorized",
  "error_description": "Invalid or expired authentication token"
}

Missing Authentication

{
  "error": "authentication_required",
  "error_description": "This endpoint requires authentication"
}

Rate Limiting

All backup endpoints are rate-limited to prevent abuse:

  • Authenticated requests: 100 requests per minute
  • OAuth backup retrieval: 10 requests per minute per IP
  • Failed authentication: Progressive delays after failed attempts