Skip to main content

Capctha options for authentication process

In this section, we will see how to use the different captcha options available in the Cardinal SDK.

note

Authentication processes aren't supported on the Cardinal python SDK

Available captcha systems​

Friendly Captcha (v1)​

You can use Friendly Captcha as a captcha option in the Cardinal SDK. Friendly Captcha is a privacy-focused captcha service that is GDPR compliant. You can check it out here

import com.icure.cardinal.sdk.CardinalSdk
import com.icure.cardinal.sdk.auth.AuthenticationProcessTelecomType
import com.icure.cardinal.sdk.auth.CaptchaOptions
import com.icure.cardinal.sdk.storage.impl.FileStorageFacade

val process = CardinalSdk.initializeWithProcess(
applicationId = null,
baseUrl = "https://api.icure.cloud",
messageGatewayUrl = "https://msg-gw.icure.cloud",
externalServicesSpecId = specId,
processId = processId,
userTelecomType = AuthenticationProcessTelecomType.Email,
userTelecom = "johndoe@example.com",
captcha = CaptchaOptions.FriendlyCaptcha(friendlyCaptchaResponse),
baseStorage = FileStorageFacade("FILE_PATH"),
)

Google reCAPTCHA (v3)​

You can use Google reCAPTCHA as a captcha option in the Cardinal SDK. Google reCAPTCHA is a captcha service that is widely used across the internet. You can check it out here

import com.icure.cardinal.sdk.CardinalSdk
import com.icure.cardinal.sdk.auth.AuthenticationProcessTelecomType
import com.icure.cardinal.sdk.auth.CaptchaOptions
import com.icure.cardinal.sdk.storage.impl.FileStorageFacade

val process = CardinalSdk.initializeWithProcess(
applicationId = null,
baseUrl = "https://api.icure.cloud",
messageGatewayUrl = "https://msg-gw.icure.cloud",
externalServicesSpecId = specId,
userTelecom = "johndoe@example.com",
userTelecomType = AuthenticationProcessTelecomType.Email,
baseStorage = FileStorageFacade("FILE_PATH"),
processId = processId,
captcha = CaptchaOptions.Recaptcha(reCaptchaResponse),
)

Kerberus​

Kerberus is an open-source Kotlin Multiplatform proof of work captcha library. You can use it without any UI elements. You can check it out here

How to use Kerberus with the Cardinal SDK?​

The easiet way to use Kerberus is by using the Delegated option in the Cardinal SDK. This option will automatically handle the challenge and resolution of the Kerberus captcha.

import com.icure.cardinal.sdk.CardinalSdk
import com.icure.cardinal.sdk.auth.AuthenticationProcessTelecomType
import com.icure.cardinal.sdk.auth.CaptchaOptions
import com.icure.cardinal.sdk.storage.impl.FileStorageFacade

val process = CardinalSdk.initializeWithProcess(
applicationId = "com.mycompany.mycardinalapp",
baseUrl = "https://api.icure.cloud",
messageGatewayUrl = "https://msg-gw.icure.cloud",
externalServicesSpecId = specId,
processId = processId,
userTelecomType = AuthenticationProcessTelecomType.Email,
userTelecom = "johndoe@example.be",
captcha = CaptchaOptions.Kerberus.Delegated { progress -> println("Progress: ${progress * 100}%") },
baseStorage = FileStorageFacade("FILE_PATH"),
)
tip

onProgress callback is optional.

Smoothening the user experience​

If you use the Kerberus.Delegated captcha options, the SDK automatically handles the challenge request and resolution, but this means that after the user provides their information for login or registration, there will be an additional delay before authentication continues.

As an alternative, you can request and begin solving the challenge while the user is still filling in their information, which will smoothen the user experience. You can provide the pre-computed solution using the Kerberus.Computed captcha options.

To do so, you need to:

  1. Request a new Kerberus challenge by making a GET request to the URL https://msg-gw.icure.cloud/{SPECID}/challenge.
  2. Compute the challenge solution using the method resolveChallenge.
  3. Initialize the Cardinal SDK with the pre-computed solution.
caution

In Expo, you need to pass the CryptoService to the resolveChallenge method.

You can refer to the dedicated documentation page to learn how to get the CryptoService and why it is required.

import com.icure.cardinal.sdk.CardinalSdk
import com.icure.cardinal.sdk.auth.AuthenticationProcessTelecomType
import com.icure.cardinal.sdk.auth.CaptchaOptions
import com.icure.cardinal.sdk.storage.impl.FileStorageFacade
import com.icure.kerberus.Challenge
import com.icure.kerberus.Solution
import com.icure.kerberus.resolveChallenge
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.request.accept
import io.ktor.client.request.get
import io.ktor.http.ContentType
import io.ktor.serialization.kotlinx.json.json

val client = HttpClient(CIO) {
install(ContentNegotiation) {
json()
}
}

val msgGwUrl = "https://msg-gw.icure.cloud"
val specId = "SPEC_ID" // Fill from cockpit
val processId = "PROCESS_ID" // Fill from cockpit

suspend fun startSdkAuth(
userEmail: String
) = CardinalSdk.initializeWithProcess(
applicationId = "com.mycompany.mycardinalapp",
baseUrl = "https://api.icure.cloud",
messageGatewayUrl = msgGwUrl,
externalServicesSpecId = specId,
processId = processId,
userTelecomType = AuthenticationProcessTelecomType.Email,
userTelecom = userEmail,
captcha = CaptchaOptions.Kerberus.Computed(getAndSolveKerberusChallenge()),
baseStorage = FileStorageFacade("FILE_PATH"),
)

suspend fun getAndSolveKerberusChallenge(): Solution {
val challenge = client.get("${msgGwUrl}/${specId}/challenge"){
accept(ContentType.Application.Json)
}.body<Challenge>()
return resolveChallenge(challenge, specId) { progress ->
println("Progress: ${progress * 100}%")
}
}