Skip to main content
Sessions required

Every yes:id SDK module needs a valid session before it can run. Complete the Sessions Guide first — it takes 5 minutes and is required before the code below will work.

Using Face Authentication

The user blinks to start, completes directional challenges (look left / right / up / down), and the live face is matched against one or two reference images you provide.

Prerequisites

YesidSessionManager.setup(
api = "YOUR_API_KEY",
publishable = "YOUR_PUBLISHABLE_KEY",
consumerUsername = "YOUR_USERNAME"
)

Compose integration

import com.yesid.face.FaceAuthentication.FaceAuthenticationCamera
import com.yesid.face.FaceAuthentication.domain.FaceMatchResults
import com.yesid.face.FaceAuthentication.presentation.FaceAuthConfigurationBuilder

@Composable
fun FaceAuthScreen(sessionId: String, referenceImage: Bitmap) {
FaceAuthenticationCamera.FaceAuthCamera(
configurationBuilder = FaceAuthConfigurationBuilder
.setSessionID(sessionId),
firstImage = referenceImage,
secondImage = null,
onMatchResults = { result: FaceMatchResults ->
val similarity = result.similarity
val matched = (similarity ?: 0.0) >= 0.75
}
)
}

Matching against two reference images

FaceAuthenticationCamera.FaceAuthCamera(
configurationBuilder = FaceAuthConfigurationBuilder.setSessionID(sessionId),
firstImage = enrolledFaceBitmap,
secondImage = documentPortraitBitmap,
onMatchResultsFirstImage = { r -> },
onMatchResultsSecondImage = { r -> },
)

Liveness-only mode

FaceAuthenticationCamera.FaceAuthCamera(
configurationBuilder = FaceAuthConfigurationBuilder
.setSessionID(sessionId)
.setLivenessOnly(true),
firstImage = null,
secondImage = null,
onLivenessOnlyResults = { capturedFrames: List<Bitmap> -> }
)

Configuration reference

MethodTypeDefaultDescription
setSessionID(id)StringRequired. Session ID
setLivenessOnly(flag)BooleanfalseSkip matching; return captured frames
setDisableSession(flag)BooleanfalseSkip session validation
setUIMessages(messages)FaceAuthUIMessagesdefaultsOverride user-facing strings
setFraudDefenseSettings(...)maxAttempts=5Tune lockout behaviour
setLensFacing(facing)IntLENS_FACING_FRONTCamera to use

Customising UI messages

FaceAuthConfigurationBuilder.setUIMessages(
FaceAuthUIMessages(
positionFace = "Place your face in the oval",
blinkToStart = "Blink to begin",
fraudDetected = "Verification failed. Try again later."
)
)

Resetting state

FaceAuthenticationCamera.restart()

Complete Activity example

The real integration pattern from the yes:id demo — config screen → camera → results:

class FaceMatchActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val sessionId = intent.getStringExtra("sessionId") ?: ""

setContent {
var scanning by remember { mutableStateOf(false) }
var matchResult by remember { mutableStateOf<FaceMatchResults?>(null) }
var livenessOnly by remember { mutableStateOf(false) }
val handled = remember { mutableStateOf(false) }

val config = remember {
FaceAuthConfigurationBuilder
.setUserLicense("YOUR_LICENSE_KEY")
.setSessionID(sessionId)
}

when {
scanning && matchResult == null -> {
config.setLivenessOnly(livenessOnly)

FaceAuthenticationCamera.FaceAuthCamera(
configurationBuilder = config,
firstImage = null,
secondImage = null,
onMatchResults = { res ->
if (!handled.value) {
handled.value = true
scanning = false
matchResult = res
}
},
onLivenessOnlyResults = { frames ->
if (!handled.value) {
handled.value = true
scanning = false
}
}
)
}

matchResult != null -> {
val similarity = matchResult!!.similarity ?: 0.0
val matched = similarity >= 0.6

Column(Modifier.padding(16.dp)) {
Text(if (matched) "Identity confirmed" else "No match",
style = MaterialTheme.typography.headlineSmall)
Spacer(Modifier.height(12.dp))
Text("Similarity: ${String.format("%.1f", similarity * 100)}%")
Text("Verdict: ${if (matched) "Match" else "No match"}")

Spacer(Modifier.height(16.dp))
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
Button(onClick = { finish() }) { Text("Done") }
OutlinedButton(onClick = {
handled.value = false; matchResult = null; scanning = false
}) { Text("Try again") }
}
}
}

else -> {
Column(Modifier.padding(16.dp)) {
Text("Face verification", style = MaterialTheme.typography.headlineSmall)
Spacer(Modifier.height(16.dp))

Row(verticalAlignment = Alignment.CenterVertically) {
Text("Liveness only", Modifier.weight(1f))
Switch(checked = livenessOnly, onCheckedChange = { livenessOnly = it })
}

Spacer(Modifier.height(16.dp))
Button(onClick = { handled.value = false; matchResult = null; scanning = true }) {
Text(if (livenessOnly) "Start liveness capture" else "Match faces")
}
}
}
}
}
}
}