Skip to content

FaceAuthen Overview ​

FaceAuthen is CAKE's face-based authentication service: a user registers a face profile once, then authenticates with a selfie on every subsequent sensitive action. This page covers the profile lifecycle, the transaction model, authentication, and the end-to-end flow.

INFO

Every sample in this documentation uses the same fictional identity — Nguyễn Văn A, NID 001xxxxxxxxx, user_id user_00000001, ref_id ref_00000001. Credentials, tokens and keys appear as <PLACEHOLDER>. None of it is real data; replace it all with your own values.

Prerequisites ​

WhatDescription
Access IDA UUID identifying your Tenant. Sent in the Authorization header. Provided by CAKE.
Access KeyThe secret key used to sign backend requests. Provided by CAKE.
Base URLIssued by CAKE together with your credentials, for both stage and production.
App-IdScopes a transaction to a per-app configuration — challenge settings and flash liveness. Defaults to default.
Mobile SDKCaptures the selfie and signs its own requests with the per-transaction JWT.

Samples throughout this documentation write the base URL as <BASE_URL> — substitute the value above.

Core Concepts ​

Profile and Transaction ​

FaceAuthen has two distinct objects, and confusing them is the most common integration error.

FieldTypeDescription
Profileper userThe registered face template, keyed by user_id. Created by Register Faces, amended by Update Face Authen, removed by Delete Face Authen. Long-lived.
Transactionper authenticationOne authentication attempt, keyed by ref_id. Created by Create Transaction, closed by Verify Transaction Authentication Key. Short-lived.

A profile must exist before any authentication can succeed. A transaction is optional for a bare face check, but required whenever you need a verifiable, auditable result your backend can trust.

Authentication ​

WhatDescription
HMAC — Authorization: ATV <ACCESS_ID>:<SIGNATURE>Used by your backend on every endpoint in this section. See the derivation below.
JWT — Authorization: Bearer {token} plus X-SignatureUsed by the Mobile SDK, which signs its requests with the per-transaction JWT as the HMAC key. See Request Signing.
Device signature — Device-Id, X-Device-Key-Id, X-Device-SignatureAdded by the Mobile SDK to its Bearer-token requests on tenants with the device signature check enabled, using a key registered for the device with Init Signing Credential. See Request Signing.

WARNING

The Access Key never leaves your backend. The SDK is issued a per-transaction JWT by Create Transaction and signs with that instead.

Option 1: HMAC authentication (backend to FaceAuthen backend) ​

Server-to-server requests are authenticated with HMAC-SHA256, which proves both the integrity and the authenticity of the request body using a secret shared by your backend and CAKE.

HeaderDescription
X-TV-TimestampCurrent timestamp in RFC3339 format. Example: 2019-04-21T18:00:15+07:00
AuthorizationATV <ACCESS_ID>:<SIGNATURE>
text
StringToSign = HttpMethod + "\n" + UrlPath + "\n" + Timestamp + "\n" + HashedBody

# HttpMethod: POST, GET, PUT, PATCH or DELETE
# UrlPath:    relative route path, excluding the domain. Example: /v1/face_auth
# Timestamp:  request time in RFC3339 format; must match the X-TV-Timestamp header
# HashedBody: hex_encode(SHA256(raw body))

Signature = Base64(HmacSha256(AccessKeySecret, Utf8EncodingOf(StringToSign)))
javascript
const CryptoJS = require("crypto-js");

function tokenize(method, path, timestamp, body, key) {
  const hashed_body = CryptoJS.SHA256(body).toString(CryptoJS.enc.Hex);
  const formatted = `${method}\n${path}\n${timestamp}\n${hashed_body}`;
  const hmac = CryptoJS.HmacSHA256(formatted, key);
  const hashed = hmac.toString(CryptoJS.enc.Hex);
  return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(hashed));
}

INFO

The StringToSign uses the hex-encoded SHA256 of the raw body. Some CAKE tenants are provisioned with a Base64-encoded body hash instead — confirm which variant your tenant uses with the CAKE team.

Option 2: JWT token (Mobile SDK to FaceAuthen backend) ​

Create Transaction returns a JWT token scoped to one transaction. The Mobile SDK presents it as a bearer token and signs each request body with it — a different scheme from the backend's ATV header.

FieldTypeDescription
AuthorizationheaderBearer {token}
X-TV-TimestampheaderRFC3339 timestamp used in the signature.
X-SignatureheaderBase64 HMAC-SHA256 over the timestamp and hashed body, keyed with the JWT.

The full derivation is in Request Signing.

How It Works ​

sequenceDiagram
    autonumber
    participant App as Mobile App / SDK
    participant BE as Your Backend
    participant FA as FaceAuth Backend

    Note over App,FA: Phase 1 — Enrolment (once per user)
    App->>BE: Selfie images
    BE->>FA: POST /v1/face_auth_register
    FA-->>BE: status success, face_auth VERIFIED

    Note over BE,FA: Phase 2 — Open an authentication
    BE->>FA: POST /v1/create_transaction (HMAC signed)
    FA-->>BE: id, status NOT_VERIFIED, token, level
    BE-->>App: token

    Note over App,FA: Phase 3 — Authenticate
    App->>FA: POST /v1/face_auth (Bearer token + X-Signature)
    FA-->>App: auth_check matched + score, authentication_key
    App-->>BE: authentication_key

    Note over BE,FA: Phase 4 — Redeem and decide
    BE->>FA: POST /v1/verify_transaction_key
    FA-->>BE: status VERIFIED
    BE-->>App: Action approved

Phase 1 — Enrolment ​

  1. Your app captures one or more selfies and passes them to your backend, which uploads them and collects the image IDs.
  2. POST /v1/face_auth_register creates the profile for that user_id. Registration runs sanity, liveness and cross-image matching checks; any failure rejects the enrolment.

Phase 2 — Open an authentication ​

  1. POST /v1/create_transaction opens a transaction, choosing the challenge level and which sanity_options the verify step must run.
  2. The response carries the transaction id, status of NOT_VERIFIED, and the token. Your backend passes the token to the app.

Phase 3 — Authenticate ​

  1. The app captures a fresh selfie and calls POST /v1/face_auth, authenticating with the bearer token and signing the body per Request Signing.
  2. The response returns auth_check — matched, unmatched or unsure with a score — and, when a transaction was referenced, an authentication_key.
  3. The app returns the authentication_key to your backend.

Phase 4 — Redeem and decide ​

  1. POST /v1/verify_transaction_key redeems the key and moves the transaction to VERIFIED. Decide on this server-side result, not on what the app reported.

WARNING

Repeated failures lock the profile — 2002206 User profile is locked, after face_auth_brute_force_limit_exceeded. A locked profile rejects every subsequent attempt until Unlock Profile is called. Build an operator path for this before launch, or locked users will have no way back.

Shared Response Envelope ​

json
{
  "data": {
    "status": "success",
    "request_id": "cfc7b8d5-f2e2-437b-80e5-d600dfad26e2"
  },
  "errors": [],
  "success": true,
  "code": 0,
  "message": "Success"
}
FieldTypeDescription
data.statusstringsuccess or failure.
data.request_idstringRequest ID; quote it to CAKE Support when checking logs.
errorsarrayDetail of each failure. Empty on success.
errors[].codestringMachine-readable error code.
errors[].messagestringHuman-readable description.
errors[].detailobjectOptional context, e.g. field naming the invalid parameter.
successboolWhether the call succeeded.
codeintNumeric status code — 0 on success.
messagestringStatus message.

An HTTP 200 does not mean the check passed. Read success, then data.status, then the verdict.

Error Codes ​

FaceAuthen shares the numeric code space with the other CAKE identity services. The two you will branch on most:

CodeMessage
2002201 · 2002205Face authentication did not match — see the verdict warning in Error Codes.
2002206User profile is locked. Clear it with Unlock Profile.
4041002The profile of user not found — register first.

The complete numeric and string tables are in Error Codes.

Next Steps ​

Developers