Skip to content

Commit 449f0fa

Browse files
author
Jeff Yanta
committed
Merge branch 'develop'
2 parents db1fb44 + e31b382 commit 449f0fa

9 files changed

Lines changed: 121 additions & 133 deletions

File tree

api/build.gradle.kts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
2-
import org.jetbrains.kotlin.cli.common.toBooleanLenient
3-
import java.util.Properties
4-
51
plugins {
62
id(Plugins.android_library)
73
id(Plugins.kotlin_android)
@@ -19,6 +15,16 @@ android {
1915
testInstrumentationRunner = Android.testInstrumentationRunner
2016

2117
buildConfigField("Boolean", "NOTIFY_ERRORS", "false")
18+
buildConfigField(
19+
"String",
20+
"GOOGLE_CLOUD_PROJECT_NUMBER",
21+
"\"${tryReadProperty(rootProject.rootDir, "GOOGLE_CLOUD_PROJECT_NUMBER", "-1L")}\""
22+
)
23+
buildConfigField(
24+
"String",
25+
"INTEGRITY_NONCE",
26+
"\"${tryReadProperty(rootProject.rootDir, "INTEGRITY_NONCE", "")}\""
27+
)
2228

2329
javaCompileOptions {
2430
annotationProcessorOptions {
@@ -82,9 +88,7 @@ dependencies {
8288
implementation(Libs.mixpanel)
8389

8490
implementation(platform(Libs.firebase_bom))
85-
implementation(Libs.firebase_appcheck)
86-
implementation(Libs.firebase_appcheck_debug)
87-
implementation(Libs.firebase_appcheck_playintegrity)
91+
implementation(Libs.play_integrity)
8892

8993
implementation(Libs.androidx_paging_runtime)
9094

api/src/main/java/com/getcode/model/intents/IntentType.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import com.getcode.ed25519.Ed25519
55
import com.getcode.solana.keys.Signature
66
import com.getcode.model.intents.actions.ActionType
77
import com.getcode.model.intents.actions.numberActions
8-
import com.getcode.network.appcheck.toDeviceToken
8+
import com.getcode.network.integrity.toDeviceToken
99
import com.getcode.network.repository.*
1010
import com.getcode.solana.keys.PublicKey
1111
import com.getcode.utils.sign

api/src/main/java/com/getcode/network/appcheck/AppCheck.kt

Lines changed: 0 additions & 95 deletions
This file was deleted.
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package com.getcode.network.integrity
2+
3+
import android.annotation.SuppressLint
4+
import android.content.Context
5+
import android.os.Build
6+
import android.provider.Settings
7+
import android.util.Base64
8+
import com.codeinc.gen.common.v1.Model
9+
import com.getcode.api.BuildConfig
10+
import com.getcode.api.BuildConfig.GOOGLE_CLOUD_PROJECT_NUMBER
11+
import com.google.android.gms.tasks.Task
12+
import com.google.android.play.core.integrity.IntegrityManager
13+
import com.google.android.play.core.integrity.IntegrityManagerFactory
14+
import com.google.android.play.core.integrity.IntegrityTokenRequest
15+
import com.google.android.play.core.integrity.IntegrityTokenResponse
16+
import io.reactivex.rxjava3.core.BackpressureStrategy
17+
import io.reactivex.rxjava3.core.Flowable
18+
import io.reactivex.rxjava3.core.Single
19+
import kotlinx.coroutines.suspendCancellableCoroutine
20+
import timber.log.Timber
21+
import kotlin.coroutines.resume
22+
import kotlin.coroutines.resumeWithException
23+
24+
data class DeviceTokenResult(
25+
val token: String?
26+
)
27+
28+
object DeviceCheck {
29+
30+
private lateinit var integrityManager: IntegrityManager
31+
32+
private lateinit var deviceId: String
33+
34+
@SuppressLint("HardwareIds")
35+
fun register(context: Context) {
36+
integrityManager = IntegrityManagerFactory.create(context)
37+
deviceId = Settings.Secure.getString(context.contentResolver, Settings.Secure.ANDROID_ID)
38+
}
39+
40+
private fun handleAppCheckError(error: Throwable): Boolean {
41+
error.printStackTrace()
42+
return true
43+
}
44+
45+
@Deprecated("Replace with Result variant")
46+
fun integrityResponseSingle(): Single<DeviceTokenResult> {
47+
return Single.create { emitter ->
48+
tokenResponse(
49+
onToken = { emitter.onSuccess(DeviceTokenResult(it)) },
50+
onError = { emitter.onError(it) }
51+
)
52+
}
53+
}
54+
55+
@Deprecated("Replace with Result variant")
56+
fun integrityResponseFlowable(
57+
backpressureStrategy: BackpressureStrategy = BackpressureStrategy.BUFFER
58+
): Flowable<DeviceTokenResult> {
59+
return Flowable.create({ emitter ->
60+
tokenResponse(
61+
onToken = { emitter.onNext(DeviceTokenResult(it)) },
62+
onError = { emitter.onError(it) }
63+
)
64+
}, backpressureStrategy)
65+
}
66+
67+
suspend fun integrityResponse(): DeviceTokenResult = suspendCancellableCoroutine { cont ->
68+
tokenResponse(
69+
onToken = { cont.resume(DeviceTokenResult(it)) },
70+
onError = { cont.resumeWithException(it) }
71+
)
72+
}
73+
74+
private fun tokenResponse(onToken: (String?) -> Unit, onError: (Exception) -> Unit) {
75+
val rawNonce = deviceId
76+
val nonce = Base64.encodeToString(rawNonce.toByteArray(), Base64.NO_WRAP)
77+
// Request the integrity token by providing a nonce.
78+
val integrityTokenResponse: Task<IntegrityTokenResponse> =
79+
integrityManager.requestIntegrityToken(
80+
IntegrityTokenRequest.builder()
81+
.setCloudProjectNumber(GOOGLE_CLOUD_PROJECT_NUMBER.toLong())
82+
.setNonce(nonce)
83+
.build()
84+
)
85+
86+
integrityTokenResponse.addOnSuccessListener {
87+
Timber.d("integrity token=${it.token()}")
88+
onToken(it.token())
89+
}.addOnFailureListener { error ->
90+
if (!handleAppCheckError(error)) {
91+
onError(error)
92+
return@addOnFailureListener
93+
}
94+
95+
onToken(null)
96+
}
97+
}
98+
}
99+
100+
fun String.toDeviceToken() = Model.DeviceToken.newBuilder().setValue(this).build()

api/src/main/java/com/getcode/network/repository/Extensions.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ fun String.replaceParam(vararg value: String?): String {
118118

119119
fun String.replaceParam(index: Int = 0, value: String?): String {
120120
val param = "%${index + 1}\$s"
121-
Timber.d("param=$param with value=$value")
122121
return this.replace(param, value.orEmpty())
123122
}
124123

api/src/main/java/com/getcode/network/repository/PhoneRepository.kt

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,15 @@ import com.codeinc.gen.phone.v1.PhoneVerificationService
44
import com.getcode.db.Database
55
import com.getcode.ed25519.Ed25519
66
import com.getcode.network.api.PhoneApi
7-
import com.getcode.network.appcheck.AppCheck
8-
import com.getcode.network.appcheck.toDeviceToken
97
import com.getcode.network.core.NetworkOracle
10-
import com.google.firebase.Firebase
11-
import com.google.firebase.appcheck.AppCheckToken
12-
import com.google.firebase.appcheck.appCheck
13-
import io.reactivex.rxjava3.core.BackpressureStrategy
8+
import com.getcode.network.integrity.DeviceCheck
9+
import com.getcode.network.integrity.toDeviceToken
1410
import io.reactivex.rxjava3.core.Flowable
1511
import io.reactivex.rxjava3.core.Single
1612
import kotlinx.coroutines.flow.MutableStateFlow
17-
import java.io.ByteArrayOutputStream
1813
import javax.inject.Inject
1914
import javax.inject.Singleton
2015

21-
22-
fun appCheckToken(
23-
backpressureStrategy: BackpressureStrategy = BackpressureStrategy.BUFFER
24-
): Flowable<AppCheckToken> {
25-
return Flowable.create({ emitter ->
26-
Firebase.appCheck.limitedUseAppCheckToken
27-
.addOnSuccessListener { emitter.onNext(it) }
28-
.addOnFailureListener { emitter.onError(it) }
29-
}, backpressureStrategy)
30-
}
31-
3216
@Singleton
3317
class PhoneRepository @Inject constructor(
3418
private val phoneApi: PhoneApi,
@@ -51,7 +35,7 @@ class PhoneRepository @Inject constructor(
5135
if (isMock()) return Single.just(PhoneVerificationService.SendVerificationCodeResponse.Result.OK)
5236
.toFlowable()
5337

54-
return AppCheck.limitedUseTokenFlowable()
38+
return DeviceCheck.integrityResponseFlowable()
5539
.flatMap { tokenResult ->
5640
val request =
5741
PhoneVerificationService.SendVerificationCodeRequest.newBuilder()

api/src/main/java/com/getcode/network/repository/TransactionRepository.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import com.codeinc.gen.transaction.v2.TransactionService.SubmitIntentResponse.Re
77
import com.codeinc.gen.transaction.v2.TransactionService.SubmitIntentResponse.ResponseCase.SERVER_PARAMETERS
88
import com.codeinc.gen.transaction.v2.TransactionService.SubmitIntentResponse.ResponseCase.SUCCESS
99
import com.getcode.crypt.MnemonicPhrase
10-
import com.getcode.ed25519.Ed25519
1110
import com.getcode.ed25519.Ed25519.KeyPair
1211
import com.getcode.model.*
1312
import com.getcode.model.intents.ActionGroup
@@ -24,7 +23,7 @@ import com.getcode.model.intents.IntentType
2423
import com.getcode.model.intents.IntentUpgradePrivacy
2524
import com.getcode.model.intents.ServerParameter
2625
import com.getcode.network.api.TransactionApiV2
27-
import com.getcode.network.appcheck.AppCheck
26+
import com.getcode.network.integrity.DeviceCheck
2827
import com.getcode.solana.keys.AssociatedTokenAccount
2928
import com.getcode.solana.keys.Mint
3029
import com.getcode.solana.keys.PublicKey
@@ -47,7 +46,6 @@ import kotlinx.coroutines.flow.flowOn
4746
import kotlinx.coroutines.flow.map
4847
import kotlinx.coroutines.reactive.asFlow
4948
import timber.log.Timber
50-
import java.io.ByteArrayOutputStream
5149
import java.util.concurrent.TimeUnit
5250
import javax.inject.Inject
5351
import javax.inject.Singleton
@@ -100,9 +98,9 @@ class TransactionRepository @Inject constructor(
10098

10199
val createAccounts = IntentCreateAccounts.newInstance(organizer)
102100

103-
return AppCheck.limitedUseTokenSingle()
101+
return DeviceCheck.integrityResponseSingle()
104102
.flatMap { tokenResult ->
105-
submit(createAccounts, organizer.tray.owner.getCluster().authority.keyPair, tokenResult.token?.token)
103+
submit(createAccounts, organizer.tray.owner.getCluster().authority.keyPair, tokenResult.token)
106104
}
107105
}
108106

app/src/main/java/com/getcode/App.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import android.app.Application
44
import androidx.appcompat.app.AppCompatDelegate
55
import com.bugsnag.android.Bugsnag
66
import com.getcode.manager.AuthManager
7-
import com.getcode.network.appcheck.AppCheck
7+
import com.getcode.network.integrity.DeviceCheck
88
import com.getcode.utils.ErrorUtils
99
import com.getcode.view.main.bill.CashBillAssets
1010
import com.google.firebase.Firebase
@@ -27,7 +27,7 @@ class App : Application() {
2727
CashBillAssets.load(this)
2828

2929
Firebase.initialize(this)
30-
AppCheck.register()
30+
DeviceCheck.register(this)
3131
authManager.init(this)
3232

3333
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)

buildSrc/src/main/java/Dependencies.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,14 +182,12 @@ object Libs {
182182

183183
const val firebase_bom = "com.google.firebase:firebase-bom:${Versions.firebase_bom}"
184184
const val firebase_analytics = "com.google.firebase:firebase-analytics"
185-
const val firebase_appcheck = "com.google.firebase:firebase-appcheck"
186-
const val firebase_appcheck_debug = "com.google.firebase:firebase-appcheck-debug"
187-
const val firebase_appcheck_playintegrity = "com.google.firebase:firebase-appcheck-playintegrity"
188185
const val firebase_crashlytics = "com.google.firebase:firebase-crashlytics"
189186
const val firebase_messaging = "com.google.firebase:firebase-messaging"
190187
const val firebase_installations = "com.google.firebase:firebase-installations"
191188
const val firebase_perf = "com.google.firebase:firebase-perf"
192189

190+
const val play_integrity = "com.google.android.play:integrity:1.3.0"
193191
const val play_service_auth = "com.google.android.gms:play-services-auth:${Versions.play_service_auth}"
194192
const val play_service_auth_phone = "com.google.android.gms:play-services-auth-api-phone:${Versions.play_service_auth_phone}"
195193

0 commit comments

Comments
 (0)