Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Request Header #536

Draft
wants to merge 13 commits into
base: main
Choose a base branch
from
10 changes: 6 additions & 4 deletions lib/src/main/java/com/smileidentity/SmileID.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import com.smileidentity.networking.PartnerParamsAdapter
import com.smileidentity.networking.SmartSelfieJobResultAdapter
import com.smileidentity.networking.SmileHeaderAuthInterceptor
import com.smileidentity.networking.SmileHeaderMetadataInterceptor
import com.smileidentity.networking.SmileIDSecurityInterceptor
import com.smileidentity.networking.SmileIDService
import com.smileidentity.networking.StringifiedBooleanAdapter
import com.smileidentity.networking.UploadRequestConverterFactory
Expand Down Expand Up @@ -311,9 +312,9 @@ object SmileID {
throw IllegalArgumentException("Invalid jobId or not found")
}
val authRequestJsonString = getSmileTempFile(
jobId,
AUTH_REQUEST_FILE,
true,
folderName = jobId,
fileName = AUTH_REQUEST_FILE,
isUnsubmitted = true,
).useLines { it.joinToString("\n") }
val authRequest = moshi.adapter(AuthenticationRequest::class.java)
.fromJson(authRequestJsonString)?.apply {
Expand Down Expand Up @@ -439,8 +440,9 @@ object SmileID {
connectTimeout(timeout = 60, unit = TimeUnit.SECONDS)
readTimeout(timeout = 60, unit = TimeUnit.SECONDS)
writeTimeout(timeout = 60, unit = TimeUnit.SECONDS)
addInterceptor(interceptor = SmileHeaderAuthInterceptor)
addInterceptor(interceptor = SmileHeaderMetadataInterceptor)
addInterceptor(interceptor = SmileHeaderAuthInterceptor)
addInterceptor(interceptor = SmileIDSecurityInterceptor)
addInterceptor(
HttpLoggingInterceptor().apply {
// This BuildConfig.DEBUG will be false when the SDK is released, regardless of the
Expand Down
9 changes: 9 additions & 0 deletions lib/src/main/java/com/smileidentity/models/Upload.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ data class UploadRequest(
@Json(name = "consent_information") val consentInformation: ConsentInformation? = null,
)

/**
* This class represents security_info.json
*/
@JsonClass(generateAdapter = true)
data class SecurityInfo(
@Json(name = "timestamp") val timestamp: String,
@Json(name = "mac") val mac: String,
)

@JsonClass(generateAdapter = true)
data class UploadImageInfo(
@Json(name = "image_type_id") val imageTypeId: ImageType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ fun UploadRequest.zip(): File {
zipOutputStream.write(infoJson.toByteArray())
zipOutputStream.closeEntry()

// Write security_info.json
zipOutputStream.putNextEntry(ZipEntry("security_info.json"))
val securityInfoJson = moshi.adapter(UploadRequest::class.java).toJson(uploadRequest)
zipOutputStream.write(securityInfoJson.toByteArray())
zipOutputStream.closeEntry()

// Write images
uploadRequest.images.forEach { imageInfo ->
zipOutputStream.putNextEntry(ZipEntry(imageInfo.image.name))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.smileidentity.networking

import com.smileidentity.BuildConfig
import com.smileidentity.util.getCurrentIsoTimestamp
import okhttp3.Interceptor

annotation class SmileHeaderMetadata
Expand All @@ -11,8 +12,10 @@ object SmileHeaderMetadataInterceptor : Interceptor {
request.getCustomAnnotation(SmileHeaderMetadata::class.java)
?: return chain.proceed(request)
val newRequest = request.newBuilder()
.header("Connection", "Keep-Alive")
.header("SmileID-Source-SDK", "android")
.header("SmileID-Source-SDK-Version", BuildConfig.VERSION_NAME)
.header("SmileID-Request-Timestamp", getCurrentIsoTimestamp())
.build()
return chain.proceed(newRequest)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ interface SmileIDService {
*/
@SmileHeaderAuth
@SmileHeaderMetadata
@SmileIDSecurity
@SmileIDOptIn
@Multipart
@POST("/v2/smart-selfie-enroll")
Expand All @@ -103,6 +104,7 @@ interface SmileIDService {
*/
@SmileHeaderAuth
@SmileHeaderMetadata
@SmileIDSecurity
@SmileIDOptIn
@Multipart
@POST("/v2/smart-selfie-authentication")
Expand Down Expand Up @@ -136,6 +138,7 @@ interface SmileIDService {
* If the ID provider is unavailable, the response will be delivered to the callback URL once
* the ID provider is available again.
*/
@SmileIDSecurity
@POST("/v1/async_id_verification")
suspend fun doEnhancedKycAsync(@Body request: EnhancedKycRequest): EnhancedKycAsyncResponse

Expand Down
10 changes: 10 additions & 0 deletions lib/src/main/java/com/smileidentity/util/FileUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.smileidentity.SmileID
import com.smileidentity.SmileIDCrashReporting
import com.smileidentity.models.AuthenticationRequest
import com.smileidentity.models.PrepUploadRequest
import com.smileidentity.models.SecurityInfo
import com.smileidentity.models.UploadRequest
import java.io.File
import java.io.IOException
Expand All @@ -27,6 +28,7 @@ private const val SUBMITTED_PATH = "/submitted"
const val AUTH_REQUEST_FILE = "authentication_request.json"
const val PREP_UPLOAD_REQUEST_FILE = "prep_upload.json"
const val UPLOAD_REQUEST_FILE = "info.json"
const val SECURITY_INFO_FILE = "security_info.json"

// Enum defining the types of files managed within the job processing system.
// This categorization helps in filtering and processing files based on their content or purpose.
Expand Down Expand Up @@ -496,6 +498,14 @@ internal fun createUploadRequestFile(jobId: String, uploadRequest: UploadRequest
return file
}

internal fun createSecurityInfoFile(jobId: String, securityInfo: SecurityInfo): File {
val file = createSmileJsonFile(SECURITY_INFO_FILE, jobId)
file.sink().buffer().use { sink ->
SmileID.moshi.adapter(SecurityInfo::class.java).toJson(sink, securityInfo)
}
return file
}

/**
* Creates an authentication request file for a specific job, incorporating user and job details.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,16 @@ import com.smileidentity.models.JobType.SmartSelfieAuthentication
import com.smileidentity.models.JobType.SmartSelfieEnrollment
import com.smileidentity.models.PartnerParams
import com.smileidentity.models.PrepUploadRequest
import com.smileidentity.models.SecurityInfo
import com.smileidentity.models.SmileIDException
import com.smileidentity.models.v2.LivenessType
import com.smileidentity.models.v2.Metadatum
import com.smileidentity.models.v2.SelfieImageOriginValue.BackCamera
import com.smileidentity.models.v2.SelfieImageOriginValue.FrontCamera
import com.smileidentity.models.v2.asNetworkRequest
import com.smileidentity.networking.SmileIDCryptoManager
import com.smileidentity.networking.asLivenessImage
import com.smileidentity.networking.asSelfieImage
import com.smileidentity.networking.doSmartSelfieAuthentication
import com.smileidentity.networking.doSmartSelfieEnrollment
import com.smileidentity.results.SmartSelfieResult
Expand All @@ -37,7 +41,9 @@ import com.smileidentity.util.area
import com.smileidentity.util.createAuthenticationRequestFile
import com.smileidentity.util.createLivenessFile
import com.smileidentity.util.createPrepUploadFile
import com.smileidentity.util.createSecurityInfoFile
import com.smileidentity.util.createSelfieFile
import com.smileidentity.util.getCurrentIsoTimestamp
import com.smileidentity.util.getExceptionHandler
import com.smileidentity.util.getFileByType
import com.smileidentity.util.getFilesByType
Expand Down Expand Up @@ -358,6 +364,19 @@ class SelfieViewModel(
)
}

val timestamp = getCurrentIsoTimestamp()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For selfie we should use the multi-part signing? The security_info.json we only add for the s3 uploads (biometric kyc, document).

val mac = SmileIDCryptoManager.shared.sign(
timestamp = timestamp,
files = listOfNotNull(
selfieFile.asSelfieImage(),
) + livenessFiles.map { it.asLivenessImage() },
)

createSecurityInfoFile(
jobId = jobId,
securityInfo = SecurityInfo(timestamp = timestamp, mac = mac),
)

val apiResponse = if (isEnroll) {
SmileID.api.doSmartSelfieEnrollment(
selfieImage = selfieFile,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import com.smileidentity.models.IdInfo
import com.smileidentity.models.JobType
import com.smileidentity.models.PartnerParams
import com.smileidentity.models.PrepUploadRequest
import com.smileidentity.models.SecurityInfo
import com.smileidentity.models.SmileIDException
import com.smileidentity.models.UploadRequest
import com.smileidentity.models.v2.Metadatum
import com.smileidentity.networking.SmileIDCryptoManager
import com.smileidentity.networking.asDocumentBackImage
import com.smileidentity.networking.asDocumentFrontImage
import com.smileidentity.networking.asLivenessImage
Expand All @@ -30,7 +32,9 @@ import com.smileidentity.util.FileType
import com.smileidentity.util.StringResource
import com.smileidentity.util.createAuthenticationRequestFile
import com.smileidentity.util.createPrepUploadFile
import com.smileidentity.util.createSecurityInfoFile
import com.smileidentity.util.createUploadRequestFile
import com.smileidentity.util.getCurrentIsoTimestamp
import com.smileidentity.util.getExceptionHandler
import com.smileidentity.util.getFileByType
import com.smileidentity.util.getFilesByType
Expand Down Expand Up @@ -156,6 +160,21 @@ internal abstract class OrchestratedDocumentViewModel<T : Parcelable>(
consentInformation = consentInformation,
)

val timestamp = getCurrentIsoTimestamp()
val mac = SmileIDCryptoManager.shared.sign(
timestamp = timestamp,
files = listOfNotNull(
frontImageInfo,
backImageInfo,
selfieImageInfo,
) + livenessImageInfo,
)

createSecurityInfoFile(
jobId = jobId,
securityInfo = SecurityInfo(timestamp = timestamp, mac = mac),
)

if (SmileID.allowOfflineMode) {
createAuthenticationRequestFile(jobId, authRequest)
createPrepUploadFile(
Expand Down
4 changes: 3 additions & 1 deletion sample/sample.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.jetbrains.kotlin.compose.compiler.gradle.ComposeFeatureFlag

plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.compose.compiler)
Expand Down Expand Up @@ -85,7 +87,7 @@ android {
}

composeCompiler {
enableStrongSkippingMode = true
featureFlags.addAll(ComposeFeatureFlag.StrongSkipping)
reportsDestination = layout.buildDirectory.dir("compose_compiler")
metricsDestination = layout.buildDirectory.dir("compose_compiler")
}
Expand Down
Loading