From 29fe09605c8c59486ba869a1f76d6f946dc5929c Mon Sep 17 00:00:00 2001 From: Fabian Devel Date: Tue, 17 Dec 2024 11:48:57 +0100 Subject: [PATCH] docs(AppIntegrity): Add small documentation to the AppIntegrityManager --- .../core2/appintegrity/AppIntegrityManager.kt | 47 ++++++++++++++----- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/Core2/AppIntegrity/src/main/java/com/infomaniak/core2/appintegrity/AppIntegrityManager.kt b/Core2/AppIntegrity/src/main/java/com/infomaniak/core2/appintegrity/AppIntegrityManager.kt index cd72f28fea..19e5b88537 100644 --- a/Core2/AppIntegrity/src/main/java/com/infomaniak/core2/appintegrity/AppIntegrityManager.kt +++ b/Core2/AppIntegrity/src/main/java/com/infomaniak/core2/appintegrity/AppIntegrityManager.kt @@ -29,6 +29,13 @@ import io.sentry.Sentry import io.sentry.SentryLevel import java.util.UUID +/** + * Manager used to verify that the device used is real and doesn't have integrity problems + * + * There is 2 types of Request: + * - the standard request ([requestIntegrityVerdictToken]) that need a warm-up first ([warmUpTokenProvider]) + * - the classic request ([requestClassicIntegrityVerdictToken]) that need additional Api checks + */ class AppIntegrityManager(private val appContext: Context) { private var appIntegrityTokenProvider: StandardIntegrityTokenProvider? = null @@ -38,6 +45,10 @@ class AppIntegrityManager(private val appContext: Context) { private var challenge = "" private var challengeId = "" + /** + * This function is needed in case of standard verdict request by [requestIntegrityVerdictToken]. + * It must be called once at the initialisation because it can take a long time (up to several minutes) + */ fun warmUpTokenProvider(appCloudNumber: Long, onFailure: () -> Unit) { val integrityManager = IntegrityManagerFactory.createStandard(appContext) integrityManager.prepareIntegrityToken( @@ -48,6 +59,10 @@ class AppIntegrityManager(private val appContext: Context) { }.addOnFailureListener { manageException(it, "Error during warmup", onFailure) } } + /** + * Standard verdict request for Integrity token + * It should protect automatically from replay attack, but for now this protection seemed to not be working + */ fun requestIntegrityVerdictToken( requestHash: String, onSuccess: (String) -> Unit, @@ -63,6 +78,12 @@ class AppIntegrityManager(private val appContext: Context) { } } + /** + * Classic verdict request for Integrity token + * + * This doesn't automatically protect from replay attack, thus the use of challenge/challengeId pair with our API to add this + * layer of protection. + */ fun requestClassicIntegrityVerdictToken(onSuccess: (String) -> Unit, onFailure: () -> Unit) { // You can comment this if you want to test the App Integrity (also see getJwtToken in AppIntegrityRepository) @@ -78,6 +99,19 @@ class AppIntegrityManager(private val appContext: Context) { ?.addOnFailureListener { manageException(it, "Error when requiring a classic integrity token", onFailure) } } + suspend fun getChallenge(onSuccess: () -> Unit, onFailure: () -> Unit) = runCatching { + generateChallengeId() + val apiResponse = appIntegrityRepository.getChallenge(challengeId) + SentryLog.d( + tag = APP_INTEGRITY_MANAGER_TAG, + msg = "challengeId hash : ${challengeId.hashCode()} / challenge hash: ${apiResponse.data.hashCode()}", + ) + apiResponse.data?.let { challenge = it } + onSuccess() + }.getOrElse { + manageException(it, "Error fetching challenge", onFailure) + } + suspend fun getApiIntegrityVerdict( integrityToken: String, packageName: String, @@ -98,19 +132,6 @@ class AppIntegrityManager(private val appContext: Context) { } } - suspend fun getChallenge(onSuccess: () -> Unit, onFailure: () -> Unit) = runCatching { - generateChallengeId() - val apiResponse = appIntegrityRepository.getChallenge(challengeId) - SentryLog.d( - tag = APP_INTEGRITY_MANAGER_TAG, - msg = "challengeId hash : ${challengeId.hashCode()} / challenge hash: ${apiResponse.data.hashCode()}", - ) - apiResponse.data?.let { challenge = it } - onSuccess() - }.getOrElse { - manageException(it, "Error fetching challenge", onFailure) - } - /** * Only used to test App Integrity in Apps before their real backend implementation */