Skip to content

Commit

Permalink
feat(AppIntegrity): Send the token as header in initUploadSession
Browse files Browse the repository at this point in the history
  • Loading branch information
FabianDevel committed Dec 13, 2024
1 parent 080bbba commit ee91dc0
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,6 @@ class AppIntegrityManager(private val appContext: Context) {

companion object {
const val APP_INTEGRITY_MANAGER_TAG = "App integrity manager"
const val MOBILE_TOKEN_HEADER = "Ik-mobile-token"
const val ATTESTATION_TOKEN_HEADER = "Ik-mobile-token"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/
package com.infomaniak.core2.appintegrity

import com.infomaniak.core2.appintegrity.AppIntegrityManager.Companion.MOBILE_TOKEN_HEADER
import com.infomaniak.core2.appintegrity.AppIntegrityManager.Companion.ATTESTATION_TOKEN_HEADER
import com.infomaniak.core2.appintegrity.exceptions.ApiException
import com.infomaniak.core2.appintegrity.exceptions.NetworkException
import com.infomaniak.core2.appintegrity.exceptions.UnexpectedApiErrorFormatException
Expand Down Expand Up @@ -63,7 +63,7 @@ internal class AppIntegrityRepository {
return post<ApiResponse<String>>(
url = Url(AppIntegrityRoutes.demo),
data = mapOf<String, String>(),
appendHeaders = { append(MOBILE_TOKEN_HEADER, mobileToken) }
appendHeaders = { append(ATTESTATION_TOKEN_HEADER, mobileToken) }
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.infomaniak.core2.appintegrity.AppIntegrityManager
import com.infomaniak.core2.appintegrity.AppIntegrityManager.Companion.APP_INTEGRITY_MANAGER_TAG
import com.infomaniak.core2.appintegrity.AppIntegrityRoutes
import com.infomaniak.multiplatform_swisstransfer.common.interfaces.upload.RemoteUploadFile
import com.infomaniak.multiplatform_swisstransfer.common.interfaces.upload.UploadFileSession
import com.infomaniak.multiplatform_swisstransfer.common.utils.mapToList
import com.infomaniak.multiplatform_swisstransfer.data.NewUploadSession
import com.infomaniak.multiplatform_swisstransfer.managers.AppSettingsManager
import com.infomaniak.multiplatform_swisstransfer.managers.UploadManager
import com.infomaniak.multiplatform_swisstransfer.network.utils.SharedApiRoutes
import com.infomaniak.sentry.SentryLog
import com.infomaniak.swisstransfer.BuildConfig
import com.infomaniak.swisstransfer.di.IoDispatcher
Expand Down Expand Up @@ -136,11 +136,11 @@ class ImportFilesViewModel @Inject constructor(
}
}

fun sendTransfer() {
private fun sendTransfer(attestationToken: String) {
viewModelScope.launch(ioDispatcher) {
runCatching {
val uuid = uploadManager.createAndGetUpload(generateNewUploadSession()).uuid
uploadWorkerScheduler.scheduleWork(uuid)
uploadWorkerScheduler.scheduleWork(uuid, attestationToken)
_sendActionResult.update {
val totalSize = importationFilesManager.importedFiles.value.sumOf { it.fileSize }
SendActionResult.Success(totalSize)
Expand All @@ -159,7 +159,7 @@ class ImportFilesViewModel @Inject constructor(
runCatching {
appIntegrityManager.getChallenge(
onSuccess = { requestAppIntegrityToken(appIntegrityManager) },
onFailure = { _integrityCheckResult.value = AppIntegrityResult.Fail },
onFailure = ::setFailedIntegrityResult,
)
}.onFailure { exception ->
SentryLog.e(TAG, "Failed to start the upload", exception)
Expand All @@ -174,7 +174,7 @@ class ImportFilesViewModel @Inject constructor(
SentryLog.i(APP_INTEGRITY_MANAGER_TAG, "request for app integrity token successful $token")
getApiIntegrityVerdict(appIntegrityManager, token)
},
onFailure = { _integrityCheckResult.value = AppIntegrityResult.Fail },
onFailure = ::setFailedIntegrityResult,
)
}

Expand All @@ -183,20 +183,23 @@ class ImportFilesViewModel @Inject constructor(
appIntegrityManager.getApiIntegrityVerdict(
integrityToken = appIntegrityToken,
packageName = BuildConfig.APPLICATION_ID,
targetUrl = AppIntegrityRoutes.demo,
onSuccess = { mobileToken ->
targetUrl = SharedApiRoutes.createUploadContainer,
onSuccess = { attestationToken ->
SentryLog.i(APP_INTEGRITY_MANAGER_TAG, "Api verdict check")
Log.i(APP_INTEGRITY_MANAGER_TAG, "getApiIntegrityVerdict: $mobileToken")
Log.i(APP_INTEGRITY_MANAGER_TAG, "getApiIntegrityVerdict: $attestationToken")
_integrityCheckResult.value = AppIntegrityResult.Success
viewModelScope.launch(ioDispatcher) {
appIntegrityManager.callDemoRoute(mobileToken)
}
sendTransfer(attestationToken)
},
onFailure = { _integrityCheckResult.value = AppIntegrityResult.Fail },
onFailure = ::setFailedIntegrityResult,
)
}
}

private fun setFailedIntegrityResult(exception: Throwable?) {
SentryLog.e(APP_INTEGRITY_MANAGER_TAG, "Failed integrity check", exception)
_integrityCheckResult.value = AppIntegrityResult.Fail
}

fun resetIntegrityCheckResult() {
_integrityCheckResult.value = AppIntegrityResult.Idle
}
Expand All @@ -211,6 +214,7 @@ class ImportFilesViewModel @Inject constructor(
return NewUploadSession(
duration = selectedValidityPeriodOption.value.apiValue,
authorEmail = if (selectedTransferType.value == TransferTypeUi.MAIL) _transferAuthorEmail else "",
authorEmailToken = null,
password = if (selectedPasswordOption.value == PasswordTransferOption.ACTIVATED) transferPassword else NO_PASSWORD,
message = _transferMessage,
numberOfDownload = selectedDownloadLimitOption.value.apiValue,
Expand All @@ -225,7 +229,7 @@ class ImportFilesViewModel @Inject constructor(
override val remoteUploadFile: RemoteUploadFile? = null
override val size: Long = fileUi.fileSize
}
}
},
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ fun ImportFilesScreen(
HandleIntegrityCheckResult(
integrityCheckResult = { integrityCheckResult },
resetResult = { importFilesViewModel.resetIntegrityCheckResult() },
sendTransfer = { importFilesViewModel.sendTransfer() },
)

HandleSendActionResult({ sendActionResult }, { selectedTransferType }, navigateToUploadProgress)
Expand Down Expand Up @@ -152,15 +151,10 @@ private fun HandleSendActionResult(
private fun HandleIntegrityCheckResult(
integrityCheckResult: () -> AppIntegrityResult,
resetResult: () -> Unit,
sendTransfer: () -> Unit,
) {
val result = integrityCheckResult()
LaunchedEffect(result == AppIntegrityResult.Success || result == AppIntegrityResult.Fail) {
when (integrityCheckResult()) {
AppIntegrityResult.Success -> sendTransfer()
AppIntegrityResult.Fail -> Unit // TODO: Show error
else -> Unit
}
if (integrityCheckResult() == AppIntegrityResult.Fail) Unit // TODO: Show error
resetResult()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import androidx.compose.runtime.Immutable
import androidx.hilt.work.HiltWorker
import androidx.work.*
import androidx.work.WorkInfo.State
import com.infomaniak.core2.appintegrity.AppIntegrityManager
import com.infomaniak.multiplatform_swisstransfer.SharedApiUrlCreator
import com.infomaniak.multiplatform_swisstransfer.managers.UploadManager
import com.infomaniak.sentry.SentryLog
Expand All @@ -43,6 +44,8 @@ class UploadWorker @AssistedInject constructor(
private val uploadManager: UploadManager,
) : BaseCoroutineWorker(appContext, params) {

private val appIntegrityManager by lazy { AppIntegrityManager(appContext) }

private val fileChunkSizeManager by lazy {
FileChunkSizeManager(
chunkMinSize = EXPECTED_CHUNK_SIZE,
Expand All @@ -64,8 +67,12 @@ class UploadWorker @AssistedInject constructor(
SentryLog.w(TAG, "No upload pending")
return Result.failure()
}
val attestationToken = inputData.getString(ATTESTATION_TOKEN_KEY) ?: return Result.failure()

val uploadSession = uploadManager.initUploadSession(recaptcha = "Recaptcha")!!
val uploadSession = uploadManager.initUploadSession(
attestationHeaderName = AppIntegrityManager.ATTESTATION_TOKEN_HEADER,
attestationToken = attestationToken
)!!
val totalSize = uploadSession.files.sumOf { it.size }

SentryLog.d(TAG, "Work started with ${uploadSession.files.count()} files of $totalSize bytes")
Expand Down Expand Up @@ -101,9 +108,14 @@ class UploadWorker @AssistedInject constructor(
private val sharedApiUrlCreator: SharedApiUrlCreator,
) {

fun scheduleWork(uploadSessionUuid: String) {
fun scheduleWork(uploadSessionUuid: String, attestationToken: String) {
SentryLog.i(TAG, "Work scheduled uploadSessionUuid:$uploadSessionUuid")
val workData = workDataOf(
ATTESTATION_TOKEN_KEY to attestationToken,
)

val workRequest = OneTimeWorkRequestBuilder<UploadWorker>()
.setInputData(workData)
.addTag(uploadSessionUuid)
.setConstraints(Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
.build()
Expand Down Expand Up @@ -169,6 +181,8 @@ class UploadWorker @AssistedInject constructor(
private const val UPLOADED_BYTES_TAG = "uploaded_bytes_tag"
private const val TRANSFER_UUID_TAG = "transfer_uuid_tag"

private const val ATTESTATION_TOKEN_KEY = "attestationTokenKey"

private const val PROGRESS_ELAPSED_TIME = 50
}
}
3 changes: 1 addition & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@ hiltNavigationCompose = "1.2.0"
junit = "4.13.2"
junitVersion = "1.2.1"
kotlin = "2.0.20"
ktorClientMock = "1.2.0"
lifecycleRuntimeKtx = "2.8.7"
navigation = "2.8.4"
qrose = "1.0.1"
recaptcha = "18.6.1"
sentry = "4.12.0"
serialization = "1.7.3"
swisstransfer = "0.9.5"
swisstransfer = "0.9.6"
workmanager = "2.10.0"

[libraries]
Expand Down

0 comments on commit ee91dc0

Please sign in to comment.