Skip to main content

Overview

Origins are authentication providers or entry points for identities in the Bloque platform. They represent organizations, blockchains, OAuth providers, or any system that can verify and register user identities.

What is an Origin?

An origin defines how users prove their identity when registering. Common origin types include:
  • EVM Blockchains - Ethereum, Polygon, Base (wallet signature verification)
  • OAuth Providers - Auth0, Google, etc.
  • OTP Providers - WhatsApp, Email (one-time password)
  • API Keys - Traditional API key authentication

Origin Structure

identity/src/internal/wire-types.ts
interface Origin {
  namespace: string;                    // Unique origin identifier
  provider: 'evm' | 'auth0' | 'whatsapp' | 'email' | 'api-key';
  status: 'active' | 'inactive' | 'disabled';
  metadata: Record<string, unknown>;
  created_at: string;
  updated_at: string;
}

List Available Origins

Retrieve all registered origins:
const origins = await bloque.identity.origins.list();

// Filter active origins
const activeOrigins = origins.filter(o => o.status === 'active');

// Find EVM origins
const evmOrigins = origins.filter(o => o.provider === 'evm');

console.log('Available origins:', origins.map(o => o.namespace));

Challenge Types

When registering an identity, users must complete a challenge to prove ownership. Bloque supports multiple challenge types:
Challenge TypeDescriptionUse Case
SIGNING_CHALLENGECryptographic signatureBlockchain wallets
API_KEYAPI key authenticationBackend services
OAUTH_REDIRECTOAuth flowSocial logins
WEBAUTHNWebAuthn/PasskeysPasswordless auth
OTPOne-time passwordEmail/SMS/WhatsApp
PASSWORDPassword authenticationTraditional login

Registration Types

Bloque supports two types of identity registration:

Individual Registration (KYC)

For personal user accounts:
identity/src/origins/types.ts
interface IndividualRegisterParams {
  assertionResult: AssertionResult;     // Challenge response
  extraContext?: Record<string, unknown>;
  type: 'individual';
  profile: UserProfile;
}

interface UserProfile {
  firstName?: string;
  lastName?: string;
  birthdate?: string;                   // ISO 8601 (YYYY-MM-DD)
  email?: string;
  phone?: string;
  gender?: string;
  addressLine1?: string;
  addressLine2?: string;
  city?: string;
  state?: string;
  postalCode?: string;
  neighborhood?: string;
  countryOfBirthCode?: string;          // ISO country code
  countryOfResidenceCode?: string;
  personalIdType?: string;              // e.g., 'SSN', 'passport'
  personalIdNumber?: string;
}

Business Registration (KYB)

For business entities:
identity/src/origins/types.ts
interface BusinessRegisterParams {
  assertionResult: AssertionResult;
  extraContext?: Record<string, unknown>;
  type: 'business';
  profile: BusinessProfile;
}

interface BusinessProfile {
  // Required fields
  legalName: string;                    // Official legal name
  name: string;                         // Trading name/DBA
  taxId: string;                        // EIN, VAT, RFC, etc.
  type: string;                         // LLC, Corporation, etc.
  incorporationDate: string;            // YYYY-MM-DD
  addressLine1: string;
  city: string;
  state: string;
  postalCode: string;
  country: string;
  
  // Optional fields
  addressLine2?: string;
  countryCode?: string;                 // ISO country code
  email?: string;
  phone?: string;
  logo?: string;                        // URL to logo image
  
  // Owner information
  ownerName?: string;
  ownerIdType?: string;
  ownerIdNumber?: string;
  ownerAddressLine1?: string;
  ownerAddressLine2?: string;
  ownerCity?: string;
  ownerState?: string;
  ownerPostalCode?: string;
  ownerCountryCode?: string;
}

Register Individual Identity

Example: Blockchain Wallet Registration

const registration = await bloque.identity.origins.register(
  '[email protected]',
  'ethereum-mainnet',
  {
    assertionResult: {
      alias: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
      challengeType: 'SIGNING_CHALLENGE',
      value: {
        signature: '0x1234567890abcdef...',
        alias: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6'
      },
      originalChallengeParams: {
        challenge: 'bloque-challenge-1234567890',
        timestamp: 1640995200
      }
    },
    type: 'individual',
    profile: {
      firstName: 'John',
      lastName: 'Doe',
      email: '[email protected]',
      phone: '+1234567890',
      birthdate: '1990-01-15',
      city: 'New York',
      state: 'NY',
      postalCode: '10001',
      addressLine1: '123 Main St',
      countryOfBirthCode: 'USA',
      countryOfResidenceCode: 'USA',
      personalIdType: 'SSN',
      personalIdNumber: '123-45-6789'
    }
  }
);

console.log('Access token:', registration.accessToken);

Example: Email OTP Registration

// 1. Request OTP challenge
const challenge = await bloque.identity.origins.email.assert('[email protected]');

console.log('OTP sent to:', challenge.value.email);
console.log('Expires at:', challenge.value.expires_at);
console.log('Attempts remaining:', challenge.params.attempts_remaining);

// 2. User enters OTP, then register
const registration = await bloque.identity.origins.register(
  '[email protected]',
  'bloque-email',
  {
    assertionResult: {
      alias: '[email protected]',
      challengeType: 'OTP',
      value: {
        signature: userEnteredOTP,
        alias: '[email protected]'
      }
    },
    type: 'individual',
    profile: {
      firstName: 'Jane',
      lastName: 'Smith',
      email: '[email protected]',
      phone: '+1234567890'
    }
  }
);

Example: WhatsApp OTP Registration

// 1. Request WhatsApp OTP
const challenge = await bloque.identity.origins.whatsapp.assert('+1234567890');

console.log('OTP sent to:', challenge.value.phone);

// 2. Register with OTP
const registration = await bloque.identity.origins.register(
  '+1234567890',
  'bloque-whatsapp',
  {
    assertionResult: {
      alias: '+1234567890',
      challengeType: 'OTP',
      value: {
        signature: userEnteredOTP,
        alias: '+1234567890'
      }
    },
    type: 'individual',
    profile: {
      firstName: 'Carlos',
      lastName: 'Garcia',
      phone: '+1234567890'
    }
  }
);

Register Business Identity

const businessRegistration = await bloque.identity.origins.register(
  'business-123',
  'bloque-api',
  {
    assertionResult: {
      alias: 'business-123',
      challengeType: 'API_KEY',
      value: {
        apiKey: 'sk_live_abc123def456',
        alias: 'business-123'
      }
    },
    type: 'business',
    profile: {
      legalName: 'Acme Corporation',
      name: 'Acme Corp',
      taxId: '12-3456789',
      type: 'LLC',
      incorporationDate: '2020-01-15',
      addressLine1: '123 Business St',
      city: 'New York',
      state: 'NY',
      postalCode: '10001',
      country: 'United States',
      email: '[email protected]',
      phone: '+1-555-0123',
      ownerName: 'Jane Smith',
      ownerIdType: 'SSN',
      ownerIdNumber: '123-45-6789'
    }
  }
);

console.log('Business registered:', businessRegistration.accessToken);

Custom Origins

Create a client for a custom origin:
const customOrigin = bloque.identity.origins.custom('my-custom-origin');

// Request assertion from custom origin
const assertion = await customOrigin.assert('user-identifier');

// Register using custom origin
const registration = await bloque.identity.origins.register(
  'user-identifier',
  'my-custom-origin',
  registerParams
);

Registration Response

Successful registration returns an access token:
identity/src/origins/types.ts
interface RegisterResult {
  accessToken: string;  // JWT access token for the registered identity
}
Use this token for authenticated API requests:
const { accessToken } = await bloque.identity.origins.register(
  alias,
  origin,
  params
);

// Use token for authenticated requests
const authenticatedSDK = SDK.connect({
  accessToken: accessToken,
  environment: 'sandbox'
});

Built-in Origin Clients

Bloque provides pre-configured clients for common origins:
// Email OTP
const emailChallenge = await bloque.identity.origins.email.assert(
  '[email protected]'
);

// WhatsApp OTP
const whatsappChallenge = await bloque.identity.origins.whatsapp.assert(
  '+1234567890'
);

Best Practices

Select an origin that matches your authentication method:
  • Web3 apps: Use blockchain origins (EVM, Solana, etc.)
  • Traditional apps: Use email/WhatsApp OTP or OAuth
  • Backend services: Use API key authentication
  • Never expose API keys in client-side code
  • Validate OTP codes server-side
  • Use HTTPS for all challenge requests
  • Implement rate limiting for OTP requests
  • Validate all profile fields before submission
  • Use ISO 8601 format for dates (YYYY-MM-DD)
  • Use ISO country codes for country fields
  • Normalize phone numbers to E.164 format
Store access tokens securely. Never commit them to version control or expose them in client-side code.

Compliance

KYC verification after registration

Aliases

Manage identity aliases

Build docs developers (and LLMs) love