Identity Verification (HMAC)
Secure the pre-authenticated widget by verifying affiliate identity with a server-side HMAC-SHA256 signature.
Why Use Identity Verification?
When you embed the Refgrow widget with data-project-email pre-set, the email is visible in the page source. A tech-savvy user could change this attribute via browser DevTools and access another affiliate's dashboard (earnings, referral code, payment method).
Identity Verification prevents this by requiring a server-generated HMAC hash alongside the email. The hash is computed using your project secret, which only your server knows. If the hash doesn't match, the widget refuses to load affiliate data.
How It Works
- Your server computes
HMAC-SHA256(email, project_secret) - You pass the hash as
data-user-hashin the widget embed - Refgrow's API verifies the hash before returning any affiliate data
- If verification fails, the API returns
403 Forbidden
Setup
Step 1: Enable in Settings
Go to your project Settings → General → Identity Verification (HMAC) and toggle it on.
data-user-hash before enabling this setting. Otherwise, all affiliate widgets will stop loading data until the hash is added.Step 2: Generate the Hash on Your Server
Use your HMAC Secret Key (shown in Settings → General → Identity Verification when enabled) and the affiliate's email to compute the hash. Always lowercase the email before hashing. Store the secret key as an environment variable on your server — never expose it in frontend code.
Node.js
const crypto = require('crypto');
const userHash = crypto
.createHmac('sha256', process.env.REFGROW_HMAC_SECRET)
.update(userEmail.toLowerCase())
.digest('hex');Python
import hmac
import hashlib
user_hash = hmac.new(
HMAC_SECRET.encode(),
user_email.lower().encode(),
hashlib.sha256
).hexdigest()PHP
$userHash = hash_hmac(
'sha256',
strtolower($userEmail),
$hmacSecret
);Ruby
require 'openssl'
user_hash = OpenSSL::HMAC.hexdigest(
'sha256',
hmac_secret,
user_email.downcase
)Go
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"strings"
)
func userHash(email, secret string) string {
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(strings.ToLower(email)))
return hex.EncodeToString(mac.Sum(nil))
}Step 3: Add the Hash to Your Widget
Standard & Compact Widget
Pass the generated hash as the data-user-hash attribute:
<div id="refgrow"
data-project-id="YOUR_PROJECT_ID"
data-project-email="user@example.com"
data-user-hash="a1b2c3d4e5f6...">
</div>
<script src="https://scripts.refgrowcdn.com/latest.js" async defer></script>Modal Widget
Pass the hash as the 5th parameter to openModal. The 4th parameter (legacy) should be null:
RefgrowCompact.openModal(
'YOUR_PROJECT_ID',
'user@example.com',
'en', // language
null, // legacy param, pass null
'a1b2c3...' // HMAC hash
)How Verification Works
When the widget loads, it sends the email and hash to the Refgrow API. The API computes the expected hash using the stored HMAC secret key and compares it:
- Hash matches: Affiliate data is returned normally
- Hash doesn't match: API returns
403— "Invalid identity verification hash" - No hash provided (when required): API returns
403— "Identity verification required"
Backward Compatibility
Identity verification is opt-in. When disabled (default), the widget works exactly as before — no hash is needed. This means you can:
- First update your embed code to include
data-user-hash - Deploy the change to production
- Then enable the setting in Refgrow
This ensures zero downtime during the transition.
Security Notes
- Never expose your Project Secret in client-side code. The hash must be computed on your server.
- The hash is specific to each email address. Changing the email without updating the hash will fail verification.
- If you rotate your Project Secret, all existing hashes become invalid. Update your server code with the new secret and redeploy before rotating.
Troubleshooting
Widget shows "Identity verification required"
Your project has identity verification enabled but the widget embed is missing the data-user-hash attribute. Add the hash to your embed code.
Widget shows "Invalid identity verification hash"
- Check that you're using the correct Project Secret
- Make sure you lowercase the email before hashing:
email.toLowerCase() - Verify the hash is the full hex string (64 characters for SHA-256)
- Ensure the email in
data-project-emailmatches exactly what you hashed