Skip to main content
MBKYC uses a split-secret authentication model: the SDK holds only the non-secret API key ID, while the secret stays wherever you choose to keep it (normally your backend). The SDK delegates JWT signing to a callback you provide — the token signer.
The SDK never receives, stores, or transmits your API secret. This means a compromised device or browser cannot leak it.

The JWT

When the SDK needs to authenticate (device registration and handshake), it builds a JWT:
header:  { "alg": "HS256", "typ": "JWT" }
payload: { "key_id": "<your API key ID>", "fingerprint": "<device fingerprint>" }
It then computes the signing inputbase64url(header) + "." + base64url(payload) — and hands those bytes to your token signer. Your signer computes HMAC-SHA256(signingInput, keySecret) and returns the raw signature. The SDK assembles the final header.payload.signature and sends it in the x-auth-key: Bearer <JWT> header. The backend looks up the key_id, confirms the key is active, and verifies the signature with its stored copy of the secret. A revoked key fails here.

Implementing the signer

The signer is the same idea in every SDK — receive bytes, return a signature.
const tokenSigner = {
  async sign(signingInput: Uint8Array): Promise<Uint8Array> {
    const res = await fetch('/api/mbkyc/sign', { method: 'POST', body: signingInput });
    return new Uint8Array(await res.arrayBuffer());
  },
};

Server-side signing endpoint

Your /api/mbkyc/sign endpoint holds the secret and does the HMAC. In Node:
import { createHmac } from 'node:crypto';

app.post('/api/mbkyc/sign', express.raw({ type: '*/*' }), (req, res) => {
  const signature = createHmac('sha256', process.env.MBKYC_KEY_SECRET)
    .update(req.body)        // the raw signingInput bytes
    .digest();
  res.type('application/octet-stream').send(signature);
});
Authenticate and rate-limit your signing endpoint. It is effectively a delegated capability to authenticate as your organization — treat it like any other privileged internal API. It should only ever sign inputs for sessions your own application initiated.

Other headers

The SDK also sends:
  • x-sdk-id: <sdk>/<version> (e.g. kotlin/0.7.0) — identifies the SDK build.
  • Any extraHeaders you configured (max 5) — for example, headers your proxy or gateway requires to admit the request.