Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR-14342 -SDK enhancements #22

Merged
merged 3 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ plugins {


group 'com.frontegg.android'
version '1.2.0'
version '1.2.2'


android {
Expand Down Expand Up @@ -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'
}

Expand Down
4 changes: 3 additions & 1 deletion android/src/main/java/com/frontegg/android/FronteggApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ class FronteggApp private constructor(
var clientId: String,
val isEmbeddedMode: Boolean = true,
val regions: List<RegionConfig> = listOf(),
val selectedRegion: RegionConfig? = null
val selectedRegion: RegionConfig? = null,
val handleLoginWithSocialLogin: Boolean = true,
val handleLoginWithSSO: Boolean = false
) {

val credentialManager: CredentialManager = CredentialManager(context)
Expand Down
16 changes: 13 additions & 3 deletions android/src/main/java/com/frontegg/android/FronteggAuth.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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)
}
}

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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)
}
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion android/src/main/java/com/frontegg/android/services/Api.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ open class Api(
return headers.toHeaders()
}

private fun buildPostRequest(
fun buildPostRequest(
path: String,
body: JsonObject?,
additionalHeaders: Map<String, String> = mapOf()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,25 @@ class AuthorizeUrlGenerator {
}


fun generate(loginHint:String? = null, loginAction:String? = null): Pair<String, String> {
fun generate(
loginHint: String? = null,
loginAction: String? = null,
preserveCodeVerifier: Boolean? = false
): Pair<String, String> {
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()
Expand All @@ -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()
Expand Down