@@ -21,6 +21,7 @@ import com.web3auth.core.types.LoginConfigItem
2121import com.web3auth.core.types.LoginParams
2222import com.web3auth.core.types.MFALevel
2323import com.web3auth.core.types.REDIRECT_URL
24+ import com.web3auth.core.types.RedirectResponse
2425import com.web3auth.core.types.RequestData
2526import com.web3auth.core.types.SessionResponse
2627import com.web3auth.core.types.SignMessage
@@ -48,13 +49,14 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
4849
4950 private lateinit var loginCompletableFuture: CompletableFuture <Web3AuthResponse >
5051 private lateinit var enableMfaCompletableFuture: CompletableFuture <Boolean >
52+ private lateinit var manageMfaCompletableFuture: CompletableFuture <Boolean >
5153 private lateinit var signMsgCF: CompletableFuture <SignResponse >
5254
5355 private var web3AuthResponse: Web3AuthResponse ? = null
5456 private var web3AuthOption = web3AuthOptions
5557 private var sessionManager: SessionManager = SessionManager (
5658 context,
57- web3AuthOptions.sessionTime ? : 86400 ,
59+ web3AuthOptions.sessionTime ? : 30 * 86400 ,
5860 web3AuthOptions.redirectUrl.toString()
5961 )
6062
@@ -75,7 +77,8 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
7577 buildEnv = web3AuthOption.buildEnv?.name?.lowercase(Locale .ROOT ),
7678 mfaSettings = web3AuthOption.mfaSettings?.let { gson.toJson(it) },
7779 sessionTime = web3AuthOption.sessionTime,
78- originData = web3AuthOption.originData?.let { gson.toJson(it) }
80+ originData = web3AuthOption.originData?.let { gson.toJson(it) },
81+ dashboardUrl = web3AuthOption.dashboardUrl
7982 )
8083 }
8184
@@ -108,36 +111,63 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
108111 actionType : String , params : LoginParams ?
109112 ) {
110113 val sdkUrl = Uri .parse(web3AuthOption.sdkUrl)
111- val initOptions = JSONObject (gson.toJson(getInitOptions()))
112- val initParams = JSONObject (gson.toJson(getInitParams(params)))
114+
115+ val initOptions = if (actionType == " manage_mfa" ) {
116+ getInitOptions().copy(redirectUrl = getInitOptions().dashboardUrl)
117+ } else {
118+ getInitOptions()
119+ }
120+
121+ val initParams = if (actionType == " manage_mfa" ) {
122+ initOptions.dashboardUrl?.let { getInitParams(params).copy(redirectUrl = it) }
123+ } else {
124+ getInitParams(params)
125+ }
126+
127+ val initOptionsJson = JSONObject (gson.toJson(initOptions))
128+ val initParamsJson = JSONObject (gson.toJson(initParams))
129+
130+ val sessionId = SessionManager .generateRandomSessionKey()
113131
114132 val paramMap = JSONObject ()
115133 paramMap.put(
116- " options" , initOptions
134+ " options" , initOptionsJson
117135 )
118136 paramMap.put(" actionType" , actionType)
119137
120- if (actionType == " enable_mfa" ) {
138+ if (actionType == " enable_mfa" || actionType == " manage_mfa " ) {
121139 val userInfo = web3AuthResponse?.userInfo
122- initParams .put(" loginProvider" , userInfo?.typeOfLogin)
140+ initParamsJson .put(" loginProvider" , userInfo?.typeOfLogin)
123141 var extraOptionsString = " "
124142 var existingExtraLoginOptions = ExtraLoginOptions ()
125- if (initParams .has(" extraLoginOptions" )) {
126- extraOptionsString = initParams .getString(" extraLoginOptions" )
143+ if (initParamsJson .has(" extraLoginOptions" )) {
144+ extraOptionsString = initParamsJson .getString(" extraLoginOptions" )
127145 existingExtraLoginOptions =
128146 gson.fromJson(extraOptionsString, ExtraLoginOptions ::class .java)
129147 }
130148 existingExtraLoginOptions.login_hint = userInfo?.verifierId
131- initParams.put(" extraLoginOptions" , gson.toJson(existingExtraLoginOptions))
132- initParams.put(" mfaLevel" , MFALevel .MANDATORY .name.lowercase(Locale .ROOT ))
149+ initParamsJson.put(" extraLoginOptions" , gson.toJson(existingExtraLoginOptions))
150+ initParamsJson.put(" mfaLevel" , MFALevel .MANDATORY .name.lowercase(Locale .ROOT ))
151+ val loginIdObject = mapOf (" loginId" to sessionId, " platform" to " android" )
152+ initParamsJson.put(
153+ " appState" ,
154+ gson.toJson(loginIdObject).toByteArray(Charsets .UTF_8 ).toBase64URLString()
155+ )
156+ initParamsJson.put(" dappUrl" , web3AuthOption.redirectUrl)
133157 paramMap.put(" sessionId" , sessionManager.getSessionId())
134158 }
135- paramMap.put(" params" , initParams)
159+ paramMap.put(" params" , initParamsJson)
160+
161+ val jsonObject = JSONObject (paramMap.toString())
136162
137- val loginIdCf = getLoginId(paramMap)
163+ var paramsString = jsonObject.toString()
164+ paramsString = paramsString.replace(" \\ /" , " /" )
165+
166+ val loginIdCf = getLoginId(sessionId, paramsString)
138167 loginIdCf.whenComplete { loginId, error ->
139168 if (error == null ) {
140169 val jsonObject = mapOf (" loginId" to loginId)
170+
141171 val hash = " b64Params=" + gson.toJson(jsonObject).toByteArray(Charsets .UTF_8 )
142172 .toBase64URLString()
143173
@@ -205,20 +235,38 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
205235 val hashUri = Uri .parse(uri?.host + " ?" + uri?.fragment)
206236 val error = uri?.getQueryParameter(" error" )
207237 if (error != null ) {
208- loginCompletableFuture.completeExceptionally(UnKnownException (error))
238+ if (::loginCompletableFuture.isInitialized) loginCompletableFuture.completeExceptionally(
239+ UnKnownException (error)
240+ )
241+
209242 if (::enableMfaCompletableFuture.isInitialized) enableMfaCompletableFuture.completeExceptionally(
210243 UnKnownException (error)
211244 )
245+
246+ if (::manageMfaCompletableFuture.isInitialized) manageMfaCompletableFuture.completeExceptionally(
247+ UnKnownException (error)
248+ )
212249 return
213250 }
214251
215252 val b64Params = hashUri.getQueryParameter(" b64Params" )
216253 if (b64Params.isNullOrBlank()) {
217254 throwLoginError(ErrorCode .INVALID_LOGIN )
218255 throwEnableMFAError(ErrorCode .INVALID_LOGIN )
256+ throwManageMFAError(ErrorCode .INVALID_LOGIN )
219257 return
220258 }
221259 val b64ParamString = decodeBase64URLString(b64Params).toString(Charsets .UTF_8 )
260+
261+ if (b64ParamString.contains(" actionType" )) {
262+ val response = gson.fromJson(b64ParamString, RedirectResponse ::class .java)
263+ if (response.actionType == " manage_mfa" ) {
264+ if (::manageMfaCompletableFuture.isInitialized)
265+ manageMfaCompletableFuture.complete(true )
266+ return
267+ }
268+ }
269+
222270 val sessionResponse = gson.fromJson(b64ParamString, SessionResponse ::class .java)
223271 val sessionId = sessionResponse.sessionId
224272
@@ -235,9 +283,11 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
235283 if (web3AuthResponse?.error?.isNotBlank() == true ) {
236284 throwLoginError(ErrorCode .SOMETHING_WENT_WRONG )
237285 throwEnableMFAError(ErrorCode .SOMETHING_WENT_WRONG )
286+ throwManageMFAError(ErrorCode .SOMETHING_WENT_WRONG )
238287 } else if (web3AuthResponse?.privKey.isNullOrBlank() && web3AuthResponse?.factorKey.isNullOrBlank()) {
239288 throwLoginError(ErrorCode .SOMETHING_WENT_WRONG )
240289 throwEnableMFAError(ErrorCode .SOMETHING_WENT_WRONG )
290+ throwManageMFAError(ErrorCode .SOMETHING_WENT_WRONG )
241291 } else {
242292 web3AuthResponse?.sessionId?.let {
243293 SessionManager .saveSessionIdToStorage(it)
@@ -251,7 +301,9 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
251301 web3AuthResponse?.userInfo?.dappShare!! ,
252302 )
253303 }
254- loginCompletableFuture.complete(web3AuthResponse)
304+ if (::loginCompletableFuture.isInitialized)
305+ loginCompletableFuture.complete(web3AuthResponse)
306+
255307 if (::enableMfaCompletableFuture.isInitialized)
256308 enableMfaCompletableFuture.complete(true )
257309 }
@@ -263,6 +315,7 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
263315 } else {
264316 throwLoginError(ErrorCode .SOMETHING_WENT_WRONG )
265317 throwEnableMFAError(ErrorCode .SOMETHING_WENT_WRONG )
318+ throwManageMFAError(ErrorCode .SOMETHING_WENT_WRONG )
266319 }
267320 }
268321
@@ -334,6 +387,22 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
334387 return enableMfaCompletableFuture
335388 }
336389
390+
391+ fun manageMFA (loginParams : LoginParams ? = null): CompletableFuture <Boolean > {
392+ manageMfaCompletableFuture = CompletableFuture ()
393+ if (web3AuthResponse?.userInfo?.isMfaEnabled == false ) {
394+ throwManageMFAError(ErrorCode .MFA_NOT_ENABLED )
395+ return manageMfaCompletableFuture
396+ }
397+ val sessionId = sessionManager.getSessionId()
398+ if (sessionId.isBlank()) {
399+ throwManageMFAError(ErrorCode .NOUSERFOUND )
400+ return manageMfaCompletableFuture
401+ }
402+ processRequest(" manage_mfa" , loginParams)
403+ return manageMfaCompletableFuture
404+ }
405+
337406 /* *
338407 * Authorize User session in order to avoid re-login
339408 */
@@ -437,11 +506,10 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
437506 * @param jsonObject The JSONObject from which to retrieve the login ID.
438507 * @return A CompletableFuture<String> representing the asynchronous operation, containing the login ID.
439508 */
440- private fun getLoginId (jsonObject : JSONObject ): CompletableFuture <String > {
441- val sessionId = SessionManager .generateRandomSessionKey()
509+ private fun getLoginId (sessionId : String , jsonObject : String ): CompletableFuture <String > {
442510 sessionManager.setSessionId(sessionId)
443511 return sessionManager.createSession(
444- jsonObject.toString() ,
512+ jsonObject,
445513 baseContext,
446514 )
447515 }
@@ -471,8 +539,8 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
471539 paramMap.put(
472540 " options" , initOptions
473541 )
474-
475- val loginIdCf = getLoginId(paramMap)
542+ val sessionId = SessionManager .generateRandomSessionKey()
543+ val loginIdCf = getLoginId(sessionId, paramMap.toString() )
476544
477545 loginIdCf.whenComplete { loginId, error ->
478546 if (error == null ) {
@@ -536,7 +604,8 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
536604 " options" , initOptions
537605 )
538606
539- val loginIdCf = getLoginId(paramMap)
607+ val loginId = SessionManager .generateRandomSessionKey()
608+ val loginIdCf = getLoginId(loginId, paramMap.toString())
540609
541610 loginIdCf.whenComplete { loginId, error ->
542611 if (error == null ) {
@@ -590,6 +659,17 @@ class Web3Auth(web3AuthOptions: Web3AuthOptions, context: Context) : WebViewResu
590659 )
591660 }
592661
662+ private fun throwManageMFAError (error : ErrorCode ) {
663+ if (::manageMfaCompletableFuture.isInitialized)
664+ manageMfaCompletableFuture.completeExceptionally(
665+ Exception (
666+ Web3AuthError .getError(
667+ error
668+ )
669+ )
670+ )
671+ }
672+
593673 private fun throwLoginError (error : ErrorCode ) {
594674 if (::loginCompletableFuture.isInitialized) {
595675 loginCompletableFuture.completeExceptionally(
0 commit comments