Skip to content

Commit d5750de

Browse files
Merge pull request #48 from Web3Auth/feat/fallback-mechanisn-when-nwtwork-becomes-unstable
Added fallback mechanism when network becomes unstable or not available
2 parents c8c08a9 + 2a473b8 commit d5750de

File tree

4 files changed

+119
-67
lines changed

4 files changed

+119
-67
lines changed

.idea/thriftCompiler.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
33
package="com.web3auth.core">
44

5+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
56
<uses-permission android:name="android.permission.INTERNET" />
67
<queries>
78
<intent>

core/src/main/java/com/web3auth/core/Web3Auth.kt

Lines changed: 76 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@ package com.web3auth.core
33
import android.content.Context
44
import android.content.Intent
55
import android.net.Uri
6-
import android.os.Build
76
import android.os.Handler
87
import android.os.Looper
9-
import androidx.annotation.RequiresApi
108
import androidx.browser.customtabs.CustomTabsIntent
119
import androidx.core.os.postDelayed
1210
import com.google.gson.GsonBuilder
@@ -18,6 +16,7 @@ import com.web3auth.core.keystore.KeyStoreManagerUtils
1816
import com.web3auth.core.types.*
1917
import com.web3auth.core.types.Base64
2018
import java8.util.concurrent.CompletableFuture
19+
import kotlinx.coroutines.DelicateCoroutinesApi
2120
import kotlinx.coroutines.GlobalScope
2221
import kotlinx.coroutines.launch
2322
import org.json.JSONObject
@@ -75,7 +74,9 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) {
7574
initiateKeyStoreManager()
7675

7776
//authorize session
78-
authorizeSession()
77+
if (ApiHelper.isNetworkAvailable(context)) {
78+
authorizeSession()
79+
}
7980
}
8081

8182
private fun initiateKeyStoreManager() {
@@ -166,7 +167,7 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) {
166167
fun login(loginParams: LoginParams): CompletableFuture<Web3AuthResponse> {
167168
//check for share
168169
if (web3AuthOption.loginConfig != null) {
169-
var loginConfigItem: LoginConfigItem? = web3AuthOption.loginConfig?.values?.first()
170+
val loginConfigItem: LoginConfigItem? = web3AuthOption.loginConfig?.values?.first()
170171
val share: String? =
171172
KeyStoreManagerUtils.decryptData(loginConfigItem?.verifier.toString())
172173
if (share?.isNotEmpty() == true) {
@@ -182,7 +183,9 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) {
182183
}
183184

184185
fun logout(params: Map<String, Any>? = null): CompletableFuture<Void> {
185-
sessionTimeOutAPI()
186+
if (ApiHelper.isNetworkAvailable(context)) {
187+
sessionTimeOutAPI()
188+
}
186189
request("logout", extraParams = params)
187190

188191
logoutCompletableFuture = CompletableFuture()
@@ -192,42 +195,43 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) {
192195
/**
193196
* Authorize User session in order to avoid re-login
194197
*/
198+
@OptIn(DelicateCoroutinesApi::class)
195199
private fun authorizeSession() {
196200
sessionCompletableFuture = CompletableFuture()
197201
sessionId = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.SESSION_ID)
198202
if (sessionId != null && sessionId?.isNotEmpty() == true) {
199203
val pubKey = "04".plus(KeyStoreManagerUtils.getPubKey(sessionId.toString()))
200204
GlobalScope.launch {
201-
val result = web3AuthApi.authorizeSession(pubKey)
202-
if (result.isSuccessful && result.body() != null) {
203-
val messageObj = JSONObject(result.body()?.message).toString()
204-
shareMetadata = gson.fromJson(
205-
messageObj,
206-
ShareMetadata::class.java
207-
)
208-
println("shareMetadata$shareMetadata")
209-
210-
KeyStoreManagerUtils.savePreferenceData(
211-
KeyStoreManagerUtils.EPHEM_PUBLIC_Key,
212-
shareMetadata.ephemPublicKey.toString()
213-
)
214-
KeyStoreManagerUtils.savePreferenceData(
215-
KeyStoreManagerUtils.IV_KEY,
216-
shareMetadata.iv.toString()
217-
)
218-
KeyStoreManagerUtils.savePreferenceData(
219-
KeyStoreManagerUtils.MAC,
220-
shareMetadata.mac.toString()
221-
)
222-
223-
val aes256cbc = AES256CBC(
224-
sessionId?.let { it },
225-
shareMetadata.ephemPublicKey,
226-
shareMetadata.iv.toString()
227-
)
228-
229-
// Implementation specific oddity - hex string actually gets passed as a base64 string
230-
try {
205+
try {
206+
val result = web3AuthApi.authorizeSession(pubKey)
207+
if (result.isSuccessful && result.body() != null) {
208+
val messageObj = JSONObject(result.body()?.message).toString()
209+
shareMetadata = gson.fromJson(
210+
messageObj,
211+
ShareMetadata::class.java
212+
)
213+
println("shareMetadata$shareMetadata")
214+
215+
KeyStoreManagerUtils.savePreferenceData(
216+
KeyStoreManagerUtils.EPHEM_PUBLIC_Key,
217+
shareMetadata.ephemPublicKey.toString()
218+
)
219+
KeyStoreManagerUtils.savePreferenceData(
220+
KeyStoreManagerUtils.IV_KEY,
221+
shareMetadata.iv.toString()
222+
)
223+
KeyStoreManagerUtils.savePreferenceData(
224+
KeyStoreManagerUtils.MAC,
225+
shareMetadata.mac.toString()
226+
)
227+
228+
val aes256cbc = AES256CBC(
229+
sessionId,
230+
shareMetadata.ephemPublicKey,
231+
shareMetadata.iv.toString()
232+
)
233+
234+
// Implementation specific oddity - hex string actually gets passed as a base64 string
231235
val encryptedShareBytes =
232236
AES256CBC.toByteArray(BigInteger(shareMetadata.ciphertext, 16))
233237
val share = aes256cbc.decrypt(Base64.encodeBytes(encryptedShareBytes))
@@ -257,9 +261,9 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) {
257261
sessionCompletableFuture.complete(web3AuthResponse)
258262
}
259263
}
260-
} catch (ex: Exception) {
261-
ex.printStackTrace()
262264
}
265+
} catch (ex: Exception) {
266+
ex.printStackTrace()
263267
}
264268
}
265269
}
@@ -273,39 +277,44 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions) {
273277
* Session TimeOut API for logout
274278
*/
275279
private fun sessionTimeOutAPI() {
276-
val ephemKey =
277-
KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.EPHEM_PUBLIC_Key)
278-
val ivKey = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.IV_KEY)
279-
val mac = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.MAC)
280-
281-
if (ephemKey?.isEmpty() == true && ivKey?.isEmpty() == true) return
280+
try {
281+
val ephemKey =
282+
KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.EPHEM_PUBLIC_Key)
283+
val ivKey = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.IV_KEY)
284+
val mac = KeyStoreManagerUtils.getPreferencesData(KeyStoreManagerUtils.MAC)
285+
286+
if (ephemKey?.isEmpty() == true && ivKey?.isEmpty() == true) return
287+
288+
val aes256cbc = AES256CBC(
289+
sessionId,
290+
ephemKey,
291+
ivKey.toString()
292+
)
293+
val encryptedData = aes256cbc.encrypt("".toByteArray(StandardCharsets.UTF_8))
294+
val encryptedMetadata = ShareMetadata(ivKey, ephemKey, encryptedData, mac)
295+
val gsonData = gson.toJson(encryptedMetadata)
282296

283-
val aes256cbc = AES256CBC(
284-
sessionId?.let { it },
285-
ephemKey,
286-
ivKey.toString()
287-
)
288-
var encryptedData = aes256cbc.encrypt("".toByteArray(StandardCharsets.UTF_8))
289-
var encryptedMetadata = ShareMetadata(ivKey, ephemKey, encryptedData, mac)
290-
var gsonData = gson.toJson(encryptedMetadata)
291-
292-
GlobalScope.launch {
293-
val result = web3AuthApi.logout(
294-
LogoutApiRequest(
295-
key = "04".plus(KeyStoreManagerUtils.getPubKey(sessionId = sessionId.toString())),
296-
data = gsonData,
297-
signature = KeyStoreManagerUtils.getECDSASignature(
298-
BigInteger(sessionId, 16),
299-
gsonData
300-
),
301-
timeout = 1
297+
GlobalScope.launch {
298+
val result = web3AuthApi.logout(
299+
LogoutApiRequest(
300+
key = "04".plus(KeyStoreManagerUtils.getPubKey(sessionId = sessionId.toString())),
301+
data = gsonData,
302+
signature = KeyStoreManagerUtils.getECDSASignature(
303+
sessionId?.let { BigInteger(it, 16) },
304+
gsonData
305+
),
306+
timeout = 1
307+
)
302308
)
303-
)
304-
if (result.isSuccessful) {
305-
//Delete local storage
306-
var loginConfigItem: LoginConfigItem? = web3AuthOption.loginConfig?.values?.first()
307-
KeyStoreManagerUtils.deletePreferencesData(loginConfigItem?.verifier.toString())
309+
if (result.isSuccessful) {
310+
//Delete local storage
311+
val loginConfigItem: LoginConfigItem? =
312+
web3AuthOption.loginConfig?.values?.first()
313+
KeyStoreManagerUtils.deletePreferencesData(loginConfigItem?.verifier.toString())
314+
}
308315
}
316+
} catch (ex: Exception) {
317+
ex.printStackTrace()
309318
}
310319
}
311320

core/src/main/java/com/web3auth/core/api/ApiHelper.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
package com.web3auth.core.api
22

3+
import android.content.Context
4+
import android.net.ConnectivityManager
5+
import android.net.NetworkCapabilities
6+
import android.os.Build
37
import com.google.gson.GsonBuilder
48
import com.web3auth.core.BuildConfig
59
import okhttp3.OkHttpClient
610
import okhttp3.logging.HttpLoggingInterceptor
711
import retrofit2.Retrofit
812
import retrofit2.converter.gson.GsonConverterFactory
13+
import java.util.concurrent.TimeUnit
914

1015
object ApiHelper {
1116

1217
private const val baseUrl = "https://broadcast-server.tor.us"
1318

1419
private val okHttpClient = OkHttpClient().newBuilder()
20+
.readTimeout(60, TimeUnit.SECONDS)
21+
.connectTimeout(20, TimeUnit.SECONDS)
1522
.addInterceptor(HttpLoggingInterceptor().apply {
1623
if (BuildConfig.DEBUG) {
1724
level = HttpLoggingInterceptor.Level.BODY
@@ -27,4 +34,33 @@ object ApiHelper {
2734
.client(okHttpClient)
2835
.build()
2936
}
37+
38+
fun isNetworkAvailable(context: Context?): Boolean {
39+
if (context == null) return false
40+
val connectivityManager =
41+
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
42+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
43+
val capabilities =
44+
connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
45+
if (capabilities != null) {
46+
when {
47+
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> {
48+
return true
49+
}
50+
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> {
51+
return true
52+
}
53+
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> {
54+
return true
55+
}
56+
}
57+
}
58+
} else {
59+
val activeNetworkInfo = connectivityManager.activeNetworkInfo
60+
if (activeNetworkInfo != null && activeNetworkInfo.isConnected) {
61+
return true
62+
}
63+
}
64+
return false
65+
}
3066
}

0 commit comments

Comments
 (0)