Server Authentication

Secure user identification with HMAC-SHA256 signatures.

Overview

By default, user identification is trust-based — anyone with your project ID could identify as any user. Secure Mode adds server-side verification to prevent identity spoofing.

When enabled, the SDK requires an HMAC-SHA256 signature generated on your server for every identify call. The signature is computed by hashing the user's ID with your workspace's secret key.

Enable Secure Mode from Settings > Login & SSO. Once enabled, identify calls without a valid signature will be rejected.

Get your secret key

Your secret signing key is in the JotReview dashboard under Settings > Login & SSO.

Keep this key private — it should only exist on your server, never in client-side code or bundled into your app. Rotate it immediately if you believe it has been compromised.

The key is a 32-byte hex string that looks like:

13f2a9c1d8e7b4f6a0c5d2e9b1a4f7e3c

Node.js implementation

The signing logic is identical regardless of which client SDK you use — hash the user ID with your secret key and return the hex digest:

1// server.js

const JOTREVIEW_SECRET = process.env.JOTREVIEW_SECRET_KEY;

function generateSignature(userId) { return crypto .createHmac('sha256', JOTREVIEW_SECRET) .update(userId) .digest('hex'); }

// Express endpoint app.get('/api/jotreview-signature', requireAuth, (req, res) => { const signature = generateSignature(req.user.id); res.json({ signature }); }); `

Python implementation

1import hmac
2import hashlib

JOTREVIEW_SECRET = os.environ['JOTREVIEW_SECRET_KEY']

def generate_signature(user_id: str) -> str: return hmac.new( JOTREVIEW_SECRET.encode('utf-8'), user_id.encode('utf-8'), hashlib.sha256 ).hexdigest()

# Django view from django.http import JsonResponse from django.contrib.auth.decorators import login_required

@login_required def jotreview_signature(request): signature = generate_signature(str(request.user.id)) return JsonResponse({'signature': signature}) `

React Native implementation with signature

Fetch the signature from your server and pass it to JotReview.identify. Never compute the signature on the device.

1

async function handleSuccessfulLogin(user) { // Fetch signature from your backend const res = await fetch("https://api.yourapp.com/jotreview-signature", { headers: { Authorization: Bearer ${user.accessToken} }, }); const { signature } = await res.json();

// Identify with the server-generated signature JotReview.identify({ userId: user.id, email: user.email, firstName: user.firstName, lastName: user.lastName, signature, }); } `

If the signature is invalid, JotReview falls back to anonymous mode and logs a warning. Enable Strict Mode in Settings > Login & SSO to reject the session entirely instead of falling back.