diff --git a/android/build.gradle b/android/build.gradle index 45ff4cf..4066b22 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -7,7 +7,7 @@ plugins { group 'com.frontegg.android' -version '1.2.0' +version '1.2.2' android { @@ -49,11 +49,11 @@ android { dependencies { implementation 'androidx.core:core-ktx:[1.7,)' implementation 'io.reactivex.rxjava3:rxkotlin:3.0.1' - implementation 'com.squareup.okhttp3:okhttp:4.9.2' + implementation 'com.squareup.okhttp3:okhttp:4.12.0' implementation 'com.google.code.gson:gson:2.8.9' - implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.1" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" - implementation "androidx.browser:browser:1.6.0" + implementation "androidx.browser:browser:1.7.0" implementation 'com.google.androidbrowserhelper:androidbrowserhelper:2.5.0' } diff --git a/android/src/main/java/com/frontegg/android/FronteggApp.kt b/android/src/main/java/com/frontegg/android/FronteggApp.kt index d44fe21..47ffe01 100644 --- a/android/src/main/java/com/frontegg/android/FronteggApp.kt +++ b/android/src/main/java/com/frontegg/android/FronteggApp.kt @@ -18,7 +18,9 @@ class FronteggApp private constructor( var clientId: String, val isEmbeddedMode: Boolean = true, val regions: List = listOf(), - val selectedRegion: RegionConfig? = null + val selectedRegion: RegionConfig? = null, + val handleLoginWithSocialLogin: Boolean = true, + val handleLoginWithSSO: Boolean = false ) { val credentialManager: CredentialManager = CredentialManager(context) diff --git a/android/src/main/java/com/frontegg/android/FronteggAuth.kt b/android/src/main/java/com/frontegg/android/FronteggAuth.kt index 0237b30..3f4bf40 100644 --- a/android/src/main/java/com/frontegg/android/FronteggAuth.kt +++ b/android/src/main/java/com/frontegg/android/FronteggAuth.kt @@ -6,10 +6,12 @@ import android.os.Handler import android.os.Looper import android.util.Log import android.webkit.CookieManager +import android.webkit.WebView import com.frontegg.android.models.User import com.frontegg.android.regions.RegionConfig import com.frontegg.android.services.Api import com.frontegg.android.services.CredentialManager +import com.frontegg.android.utils.AuthorizeUrlGenerator import com.frontegg.android.utils.Constants import com.frontegg.android.utils.CredentialKeys import com.frontegg.android.utils.JWTHelper @@ -171,9 +173,9 @@ class FronteggAuth( this.initializing.value = false } - fun handleHostedLoginCallback(code: String): Boolean { + fun handleHostedLoginCallback(code: String, webView: WebView? = null): Boolean { - val codeVerifier = credentialManager.get(CredentialKeys.CODE_VERIFIER) + val codeVerifier = credentialManager.getCodeVerifier() val redirectUrl = Constants.oauthCallbackUrl(baseUrl) if (codeVerifier == null) { @@ -185,7 +187,15 @@ class FronteggAuth( if (data != null) { setCredentials(data.access_token, data.refresh_token) } else { - // TODO: handle error + Log.e(TAG, "Failed to exchange token" ) + if(webView != null){ + val authorizeUrl = AuthorizeUrlGenerator() + val url = authorizeUrl.generate() + Handler(Looper.getMainLooper()).post { + webView.loadUrl(url.first) + } + } + } } diff --git a/android/src/main/java/com/frontegg/android/embedded/FronteggNativeBridge.kt b/android/src/main/java/com/frontegg/android/embedded/FronteggNativeBridge.kt index f6a537a..98feb8d 100644 --- a/android/src/main/java/com/frontegg/android/embedded/FronteggNativeBridge.kt +++ b/android/src/main/java/com/frontegg/android/embedded/FronteggNativeBridge.kt @@ -35,9 +35,9 @@ class FronteggNativeBridge(val context: Context) { val generatedUrl = try { val jsonData = JSONObject(directLogin).toString().toByteArray(Charsets.UTF_8) val jsonString = Base64.encodeToString(jsonData, Base64.DEFAULT) - AuthorizeUrlGenerator().generate(null, jsonString) + AuthorizeUrlGenerator().generate(null, jsonString, true) } catch (e: JSONException) { - AuthorizeUrlGenerator().generate() + AuthorizeUrlGenerator().generate(null, null, true) } val authorizationUrl = Uri.parse(generatedUrl.first) diff --git a/android/src/main/java/com/frontegg/android/embedded/FronteggWebClient.kt b/android/src/main/java/com/frontegg/android/embedded/FronteggWebClient.kt index c7baa03..1203db8 100644 --- a/android/src/main/java/com/frontegg/android/embedded/FronteggWebClient.kt +++ b/android/src/main/java/com/frontegg/android/embedded/FronteggWebClient.kt @@ -16,12 +16,15 @@ import com.frontegg.android.utils.Constants import com.frontegg.android.utils.Constants.Companion.loginRoutes import com.frontegg.android.utils.Constants.Companion.socialLoginRedirectUrl import com.frontegg.android.utils.Constants.Companion.successLoginRoutes +import com.google.gson.Gson +import com.google.gson.JsonParser import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import okhttp3.OkHttpClient import okhttp3.Request +import org.json.JSONObject class FronteggWebClient(val context: Context) : WebViewClient() { @@ -50,6 +53,16 @@ class FronteggWebClient(val context: Context) : WebViewClient() { else -> FronteggAuth.instance.isLoading.value = true } + + + + val fronteggApp = FronteggApp.getInstance() + val nativeModuleFunctions = JSONObject() + nativeModuleFunctions.put("loginWithSocialLogin", fronteggApp.handleLoginWithSocialLogin) + nativeModuleFunctions.put("loginWithSSO", fronteggApp.handleLoginWithSSO) + val jsObject = nativeModuleFunctions.toString() + view?.evaluateJavascript("window.FronteggNativeBridgeFunctions = ${jsObject};", null) + } override fun onReceivedError( @@ -159,12 +172,10 @@ class FronteggWebClient(val context: Context) : WebViewClient() { } return super.shouldOverrideUrlLoading(view, request) } - - OverrideUrlType.Unknown -> { - openExternalBrowser(request.url) - return true - } - +// OverrideUrlType.Unknown -> { +// openExternalBrowser(request.url) +// return true +// } else -> { return super.shouldOverrideUrlLoading(view, request) } @@ -175,14 +186,6 @@ class FronteggWebClient(val context: Context) : WebViewClient() { } - override fun shouldInterceptRequest( - view: WebView?, - request: WebResourceRequest? - ): WebResourceResponse? { - return super.shouldInterceptRequest(view, request) - } - - override fun onLoadResource(view: WebView?, url: String?) { if (url == null || view == null) { super.onLoadResource(view, url) @@ -281,7 +284,7 @@ class FronteggWebClient(val context: Context) : WebViewClient() { return false } - if (FronteggAuth.instance.handleHostedLoginCallback(code)) { + if (FronteggAuth.instance.handleHostedLoginCallback(code, webView)) { return true; } diff --git a/android/src/main/java/com/frontegg/android/services/Api.kt b/android/src/main/java/com/frontegg/android/services/Api.kt index dac61c4..5bdc21a 100644 --- a/android/src/main/java/com/frontegg/android/services/Api.kt +++ b/android/src/main/java/com/frontegg/android/services/Api.kt @@ -50,7 +50,7 @@ open class Api( return headers.toHeaders() } - private fun buildPostRequest( + fun buildPostRequest( path: String, body: JsonObject?, additionalHeaders: Map = mapOf() diff --git a/android/src/main/java/com/frontegg/android/utils/AuthorizeUrlGenerator.kt b/android/src/main/java/com/frontegg/android/utils/AuthorizeUrlGenerator.kt index 7da25c4..b87453f 100644 --- a/android/src/main/java/com/frontegg/android/utils/AuthorizeUrlGenerator.kt +++ b/android/src/main/java/com/frontegg/android/utils/AuthorizeUrlGenerator.kt @@ -35,13 +35,25 @@ class AuthorizeUrlGenerator { } - fun generate(loginHint:String? = null, loginAction:String? = null): Pair { + fun generate( + loginHint: String? = null, + loginAction: String? = null, + preserveCodeVerifier: Boolean? = false + ): Pair { val nonce = createRandomString() - val codeVerifier = createRandomString() + val credentialManager = FronteggApp.getInstance().credentialManager + + + val codeVerifier:String = if (preserveCodeVerifier == true) { + credentialManager.getCodeVerifier()!! + } else { + val code = createRandomString() + credentialManager.saveCodeVerifier(code) + code + } + val codeChallenge = generateCodeChallenge(codeVerifier) - val credentialManager = FronteggApp.getInstance().credentialManager - credentialManager.saveCodeVerifier(codeVerifier) val redirectUrl = Constants.oauthCallbackUrl(baseUrl) val authorizeUrlBuilder = Uri.Builder() @@ -55,12 +67,14 @@ class AuthorizeUrlGenerator { .appendQueryParameter("code_challenge_method", "S256") .appendQueryParameter("nonce", nonce) - if(loginHint != null){ + if (loginHint != null) { authorizeUrlBuilder.appendQueryParameter("login_hint", loginHint) } - if(loginAction != null){ + if (loginAction != null) { authorizeUrlBuilder.appendQueryParameter("login_direct_action", loginAction) + + return Pair(authorizeUrlBuilder.build().toString(), codeVerifier) } val url = authorizeUrlBuilder.build().toString()