@@ -30,13 +30,14 @@ import android.content.Context
3030import androidx.annotation.VisibleForTesting
3131import com.google.android.gms.tasks.Task
3232import com.google.android.play.core.integrity.IntegrityManagerFactory.createStandard
33+ import com.google.android.play.core.integrity.IntegrityServiceException
3334import com.google.android.play.core.integrity.StandardIntegrityManager
3435import com.google.android.play.core.integrity.StandardIntegrityManager.PrepareIntegrityTokenRequest
3536import com.google.android.play.core.integrity.StandardIntegrityManager.StandardIntegrityTokenProvider
3637import com.google.android.play.core.integrity.StandardIntegrityManager.StandardIntegrityTokenRequest
38+ import com.google.android.play.core.integrity.model.StandardIntegrityErrorCode.INTEGRITY_TOKEN_PROVIDER_INVALID
3739import com.salesforce.androidsdk.rest.AppAttestationChallengeApiClient
3840import com.salesforce.androidsdk.rest.RestClient
39- import com.salesforce.androidsdk.util.SalesforceSDKLogger.e
4041import com.salesforce.androidsdk.util.SalesforceSDKLogger.w
4142import kotlinx.coroutines.runBlocking
4243import kotlinx.coroutines.tasks.await
@@ -137,7 +138,7 @@ class AppAttestationClient(
137138 * @param integrityTokenProvider The Google Play App Integrity API Integrity
138139 * Token Provider. This parameter is intended for testing purposes only
139140 * @return The "attestation" value usable in Salesforce OAuth authorization
140- * and token refresh requests
141+ * and token refresh requests or null if the value cannot be created
141142 */
142143 suspend fun createSalesforceOAuthAuthorizationAppAttestation (
143144 integrityManager : StandardIntegrityManager = this.integrityManager,
@@ -158,11 +159,6 @@ class AppAttestationClient(
158159 .setRequestHash(salesforceAppAttestationChallengeHashHexString)
159160 .build()
160161 )
161- val googlePlayIntegrityTask = integrityTokenResponse.addOnFailureListener { exception ->
162- e(javaClass.name, " Failed To Receive Google Play Integrity Token: Message: '${exception.message} '." )
163- // Synchronously re-prepare the Google Play Integrity Token Provider to provide a result to the caller.
164- runBlocking { prepareIntegrityTokenProvider().await() /* TODO: Make this retry the request. ECJ20260414 */ }
165- }
166162
167163 /*
168164 * Wait for the Google Play Integrity API response and return the
@@ -171,13 +167,24 @@ class AppAttestationClient(
171167 * API introduces latency, though latency is expected to minimal as the
172168 * API will have been prepared earlier in most scenarios.
173169 */
174- googlePlayIntegrityTask.await()
175- return OAuthAuthorizationAttestation (
176- attestationId = deviceId,
177- attestationData = Base64 .getEncoder().encodeToString(
178- googlePlayIntegrityTask.getResult().token().encodeToByteArray()
179- )
180- ).toBase64String()
170+ return runCatching {
171+ integrityTokenResponse.await()
172+
173+ // When the Google Play Integrity API response is received, return the Base64-encoded Salesforce OAuth authorization attestation parameter JSON.
174+ OAuthAuthorizationAttestation (
175+ attestationId = deviceId,
176+ attestationData = Base64 .getEncoder().encodeToString(
177+ integrityTokenResponse.getResult().token().encodeToByteArray()
178+ )
179+ ).toBase64String()
180+ }.getOrElse { e ->
181+ // If the Google Play Integrity API failed due to the Integrity Token Provider being expired, re-prepare it once for an inline retry.
182+ if ((e as ? IntegrityServiceException )?.errorCode == INTEGRITY_TOKEN_PROVIDER_INVALID ) {
183+ createSalesforceOAuthAuthorizationAppAttestation(integrityTokenProvider = null )
184+ } else {
185+ null
186+ }
187+ }
181188 }
182189
183190 /* *
0 commit comments