Self-Hosted Registration with Clazar

Last updated: August 8, 2025

This guide explains how to configure a self-hosted registration endpoint for integrating with Clazar. By setting this up, you can handle buyer registration directly on your platform when users subscribe via AWS, Azure, or GCP Marketplace.


๐Ÿ“Œ Overview

When a buyer subscribes to your listing on a cloud marketplace, Clazar sends a POST request to your configured endpoint. This request contains cloud-specific data in the payload.

To ensure data security:

  • A signature-based approach is used.

  • Your endpoint must verify the signature and ensure the request hasnโ€™t been tampered with.

  • Upon validation, respond with a 302 Redirect containing the URL to complete registration.


๐Ÿ— High-Level Architecture

๐Ÿ“Š Data Flow Diagram of Self-Hosted Registration Flow

image.png

๐Ÿ›  Step-by-Step Instructions

โœ… Step 1: Create an Endpoint to Receive POST Requests

  • Set up a publicly accessible HTTP POST endpoint on your server.

  • This endpoint will receive requests from Clazar.

  • Register this endpoint in the Clazar app configuration.


โœ… Step 2: Verify the Signature to Check Data Integrity

Clazar sends the following headers:

{
  "X-Clazar-Signature": "<signature>",
  "X-Clazar-Timestamp": "<current_timestamp>"
}

The request body will contain the payload with the cloud-specific information.


To verify the integrity of the data, follow these steps:

๐Ÿ” Construct the Message

Concatenate the timestamp and payload:

message = f"{timestamp}.{payload}"

๐Ÿšง Note: Payload must be key-sorted before signature generation.


๐Ÿ” Generate the Expected Signature

  • Clazar uses anย HMACย withย SHA-256ย to sign the message.

  • To calculate the expected signature, use the signing secret provided by Clazar to create a HMAC (hash-based message authentication code) and generate the signature. Below is the example for different programming languages


๐Ÿ Python

import hmac
import hashlib
import base64

def generate_signature(secret_key, message):
    secret_key_bytes = secret_key.encode('utf-8')
    message_bytes = message.encode('utf-8')
    hmac_signature = hmac.new(secret_key_bytes, message_bytes, hashlib.sha256).digest()
    return base64.b64encode(hmac_signature).decode('utf-8')

# Example usage
secret_key = "your_secret_key"
message = f"{current_timestamp}.{json.dumps(request_data, sort_keys=True, separators=(',', ':'))}"
signature = generate_signature(secret_key, message)
print("Signature:", signature)

๐ŸŸฆ Node.js

const crypto = require('crypto');

function generateSignature(secretKey, message) {
    return crypto.createHmac('sha256', secretKey)
                 .update(message)
                 .digest('base64');
}

function sortObjectKeys(obj) {
  if (typeof obj !== 'object' || obj === null) return obj;

  if (Array.isArray(obj)) return obj.map(sortObjectKeys);

  return Object.keys(obj).sort().reduce((result, key) => {
    result[key] = sortObjectKeys(obj[key]);
    return result;
  }, {});
}

// Example usage
const secretKey = "your_secret_key";
const sortedBody = sortObjectKeys(req.body);
const payload = JSON.stringify(sortedBody);
const message = `${timestamp}.${payload}`;

const signature = generateSignature(secretKey, message);
console.log("Signature:", signature);

โ˜• Java

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

public class HMACSignature {
    public static String generateSignature(String secretKey, String message) throws Exception {
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        byte[] hmacBytes = sha256_HMAC.doFinal(message.getBytes());
        return Base64.getEncoder().encodeToString(hmacBytes);
    }

    public static void main(String[] args) {
        try {
            String secretKey = "your_secret_key";
            String message = "timestamp.payload";
            String signature = generateSignature(secretKey, message);
            System.out.println("Signature: " + signature);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

๐Ÿ” Compare Signatures

  • Match your generated signature with the value of X-Clazar-Signature.

  • If they donโ€™t match, reject the request as it may be tampered.


โฑ Handle Replay Attacks

  • Ensure the X-Clazar-Timestamp is within a reasonable tolerance (e.g. 5 minutes).

  • If itโ€™s too old, reject the request.


โœ… Step 3: Process the Cloud Information

Clazar sends cloud-specific data in the payload. Use this to identify the buyer and map them to your system.

๐Ÿ“ฆ AWS Example

{
  "cloud_details": {
    "ProductCode": "4abcd7cksf2sl82bytk12ffj7",
    "CustomerAWSAccountId": "123458492006",
    "CustomerIdentifier": "ABcdH7jsXqL"
  },
  "clazar_listing_id": "0abc6f67-9822-8b68-8f5c-145e7db863cb",
  "clazar_buyer_id": "a1b2c366-d5a1-49d3-ac55-6c537f481c58",
  "cloud": "aws"
}

๐Ÿ”ต Azure Example

{
  "cloud_details": {
    "subscriptionName": "Example Subscription",
    "offerId": "example-offer-id",
    "planId": "example_ab12csf1-s2d8-1245-ab53-1234424b99ac-vs",
    "id": "123cef2f-5b28-4s5d-abcd-d3ag8821av13",
    "subscription": {
      "allowedCustomerOperations": ["Delete", "Read", "Update"],
      "purchaser": {
        "puid": "1234000A09FF123",
        "tenantId": "abc123b0-be36-5f2a-7avx-ds6123a56532",
        "emailId": "name@example.com",
        "objectId": "abc123b0-be36-5f2a-7asf-ds6123a12345"
      },
      "created": "2024-01-01T21:09:11.6442825Z",
      "isFreeTrial": false,
      "saasSubscriptionStatus": "PendingFulfillmentStart",
      "publisherId": "example1234578901234",
      "beneficiary": {
        "puid": "12345000F09DX123",
        "tenantId": "abc123b0-be36-5f2a-7avx-ds6123a56532",
        "emailId": "beneficiary@example.com",
        "objectId": "abc123b0-be36-5f2a-7asf-ds6123a12345"
      },
      "isTest": false,
      "name": "Company Name",
      "offerId": "example-offer-id",
      "autoRenew": false,
      "planId": "example_ab12csf1-s2d8-1245-ab53-1234424b99ac-vs",
      "term": {"termUnit": "P1M"},
      "id": "123cef2f-2b28-4s5d-abcd-d3ag8821as13",
      "lastModified": "0001-01-01T00:00:00",
      "sandboxType": "None",
      "sessionMode": "None"
    }
  },
  "clazar_listing_id": "0abc6f67-9822-8b68-8f5c-145e7db863cb",
  "clazar_contract_id": "a1b2c366-d5a1-49d3-ac55-6c537f481c58",
  "cloud": "azure"
}

๐ŸŸฉ GCP Example

{
  "cloud_details": {
    "google": {
      "roles": ["account_admin"],
      "user_identity": 123456789123454167534
    },
    "user_info": {
      "name": "Example Name",
      "id": "123456789123454167534",
      "verified_email": true,
      "given_name": "Example",
      "family_name": "Name",
      "email": "name@example.com",
      "picture": "https://lh3.googleusercontent.com/a/example"
    },
    "sub": "678912345678912345678"
  },
  "clazar_listing_id": "0abc6f67-9822-8b68-8f5c-145e7db863cb",
  "clazar_contract_id": "a1b2c366-d5a1-49d3-ac55-6c537f481c58",
  "cloud": "gcp"
}

โœ… Step 4: Send a 302 Redirection Response

After processing the information, your endpoint should send aย 302 redirection responseย with the redirection URL included in the Location header.


๐Ÿงช Testing Your Endpoint

Clazar provides a test mode.

๐Ÿงพ Test Header:

{
  "X-Clazar-Signature": "<signature>",
  "X-Clazar-Timestamp": "<current_timestamp>",
  "X-Test-Mode": "true"
}

๐Ÿงช Sample Test Request:

{
  "cloud_details": {
    "ProductCode": "4abcd7cksf2sl82bytk12ffj7",
    "CustomerAWSAccountId": "123458492006",
    "CustomerIdentifier": "ABcdH7jsXqL"
  },
  "clazar_listing_id": "0abc6f67-9822-8b68-8f5c-145e7db863cb",
  "clazar_buyer_id": "a1b2c366-d5a1-49d3-ac55-6c537f481c58",
  "cloud": "aws"
}

โœ… Summary

Task

Description

1. Create HTTP POST Endpoint

Accept POST from Clazar

2. Verify Signature

Use HMAC-SHA256 to validate integrity

3. Process Cloud Data

Adapt logic for AWS, Azure, or GCP payload

4. Respond with 302

Include redirection URL in Location header

With this setup, you can seamlessly manage buyer registrations using your own secure infrastructure.