From d8b9ea1cb4d44f22f34865647b01da4d4a14b443 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Mon, 4 Nov 2024 15:52:35 -0700 Subject: [PATCH 01/10] Use a webview for WP.com login --- .../login/LoginPrologueRevampedFragment.kt | 2 +- WordPress/src/main/AndroidManifest.xml | 13 +++- .../android/ui/accounts/LoginActivity.java | 18 ++++- .../ui/accounts/UnifiedLoginTracker.kt | 1 + .../accounts/login/LoginPrologueListener.kt | 4 +- .../ui/accounts/login/WPcomLoginHelper.kt | 51 +++++++++++++ .../accounts/login/LoginPrologueFragment.kt | 2 +- .../login/LoginPrologueRevampedFragment.kt | 4 +- .../network/rest/wpapi/WPcomLoginClient.kt | 75 +++++++++++++++++++ .../WPcomAuthorizationCodeResponse.kt | 9 +++ .../android/fluxc/store/AccountStore.java | 6 ++ 11 files changed, 178 insertions(+), 7 deletions(-) create mode 100644 WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt create mode 100644 libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt create mode 100644 libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/WPcomAuthorizationCodeResponse.kt diff --git a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt index 597a8d55a5a5..c7108f67870a 100644 --- a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt +++ b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt @@ -56,7 +56,7 @@ class LoginPrologueRevampedFragment : Fragment() { LoginScreenRevamped( onWpComLoginClicked = { viewModel.onWpComLoginClicked() - loginPrologueListener.showEmailLoginScreen() + loginPrologueListener.showEmailLoginScreen(this.context) }, onSiteAddressLoginClicked = { viewModel.onSiteAddressLoginClicked() diff --git a/WordPress/src/main/AndroidManifest.xml b/WordPress/src/main/AndroidManifest.xml index ee53ed4330f8..366619328880 100644 --- a/WordPress/src/main/AndroidManifest.xml +++ b/WordPress/src/main/AndroidManifest.xml @@ -113,7 +113,18 @@ + android:windowSoftInputMode="adjustResize" + android:exported="true"> + + + + + + + + mDispatchingAndroidInjector; @Inject protected LoginAnalyticsListener mLoginAnalyticsListener; @@ -144,6 +148,14 @@ private enum SmartLockHelperState { protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // Attempt Login if this activity was created in response to a user confirming login + mLoginHelper.tryLoginWithDataString(getIntent().getDataString()); + + if (mLoginHelper.isLoggedIn()) { + this.loggedInAndFinish(new ArrayList(), true); + return; + } + LoginFlowThemeHelper.injectMissingCustomAttributes(getTheme()); setContentView(R.layout.login_activity); @@ -452,8 +464,10 @@ private void startLogin() { // LoginPrologueListener implementation methods @Override - public void showEmailLoginScreen() { - checkSmartLockPasswordAndStartLogin(); + public void showEmailLoginScreen(@NonNull Context context) { + Intent loginWithWPcom = new Intent(Intent.ACTION_VIEW, mLoginHelper.loginUri()); + mUnifiedLoginTracker.setFlowAndStep(Flow.WORDPRESS_COM_WEB, Step.START); + context.startActivity(loginWithWPcom); } @Override diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/UnifiedLoginTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/UnifiedLoginTracker.kt index ebc0f143f3ea..58d6efde4d1f 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/UnifiedLoginTracker.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/UnifiedLoginTracker.kt @@ -126,6 +126,7 @@ class UnifiedLoginTracker enum class Flow(val value: String) { PROLOGUE("prologue"), WORDPRESS_COM("wordpress_com"), + WORDPRESS_COM_WEB("wordpress_com_web"), GOOGLE_LOGIN("google_login"), SMART_LOCK_LOGIN("smart_lock_login"), LOGIN_MAGIC_LINK("login_magic_link"), diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginPrologueListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginPrologueListener.kt index 2ea009c72b6e..9a5cb9aa42aa 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginPrologueListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginPrologueListener.kt @@ -1,7 +1,9 @@ package org.wordpress.android.ui.accounts.login +import android.content.Context + interface LoginPrologueListener { // Login Prologue callbacks - fun showEmailLoginScreen() + fun showEmailLoginScreen(context: Context) fun loginViaSiteAddress() } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt new file mode 100644 index 000000000000..86d9b9561296 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt @@ -0,0 +1,51 @@ +package org.wordpress.android.ui.accounts.login + +import android.net.Uri +import android.util.Log +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.cancel +import kotlinx.coroutines.runBlocking +import org.wordpress.android.BuildConfig +import org.wordpress.android.fluxc.network.rest.wpapi.WPcomLoginClient +import org.wordpress.android.fluxc.store.AccountStore +import org.wordpress.android.util.config.AppConfig +import javax.inject.Inject +import kotlin.coroutines.CoroutineContext + +class WPcomLoginHelper @Inject constructor( + private val loginClient: WPcomLoginClient, + private val accountStore: AccountStore, + private val appConfig: AppConfig +) { + private val context: CoroutineContext = Dispatchers.IO + + fun loginUri(): Uri { + return loginClient.loginUri(BuildConfig.OAUTH_REDIRECT_URI) + } + + fun tryLoginWithDataString(data: String?) { + if (data == null) { + return + } + + val code = this.codeFromAuthorizationUri(data) ?: return + + runBlocking { + val tokenResult = loginClient.exchangeAuthCodeForToken(code, BuildConfig.OAUTH_REDIRECT_URI) + accountStore.updateAccessToken(tokenResult.getOrThrow()) + Log.i("WPCOM_LOGIN", "Login Successful") + } + } + + fun isLoggedIn(): Boolean { + return accountStore.hasAccessToken() + } + + fun dispose() { + context.cancel() + } + + private fun codeFromAuthorizationUri(string: String): String? { + return Uri.parse(string).getQueryParameter("code") + } +} diff --git a/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueFragment.kt b/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueFragment.kt index 337f05a08b3f..446006d6e47e 100644 --- a/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueFragment.kt +++ b/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueFragment.kt @@ -56,7 +56,7 @@ class LoginPrologueFragment : Fragment(R.layout.login_signup_screen) { continueWithWpcomButton.setOnClickListener { unifiedLoginTracker.trackClick(Click.CONTINUE_WITH_WORDPRESS_COM) - loginPrologueListener.showEmailLoginScreen() + loginPrologueListener.showEmailLoginScreen(view.context) } enterYourSiteAddressButton.setOnClickListener { diff --git a/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt b/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt index 0b8817da3b64..950054d9fa18 100644 --- a/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt +++ b/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt @@ -46,7 +46,9 @@ class LoginPrologueRevampedFragment : Fragment() { setContent { AppThemeM2 { LoginScreenRevamped( - onWpComLoginClicked = loginPrologueListener::showEmailLoginScreen, + onWpComLoginClicked = { + loginPrologueListener.showEmailLoginScreen(this.context) + }, onSiteAddressLoginClicked = loginPrologueListener::loginViaSiteAddress, ) } diff --git a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt new file mode 100644 index 000000000000..f38163d7043a --- /dev/null +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt @@ -0,0 +1,75 @@ +package org.wordpress.android.fluxc.network.rest.wpapi + +import android.net.Uri +import android.util.Log +import com.google.gson.Gson +import kotlinx.coroutines.withContext +import okhttp3.FormBody +import okhttp3.OkHttpClient +import okhttp3.Request +import org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords.WPcomAuthorizationCodeResponse +import org.wordpress.android.fluxc.network.rest.wpcom.auth.AppSecrets +import javax.inject.Inject +import javax.inject.Singleton +import kotlin.coroutines.CoroutineContext + +@Singleton +class WPcomLoginClient @Inject constructor( + private val context: CoroutineContext, + private val appSecrets: AppSecrets +) { + private val client = OkHttpClient() + + fun loginUri(redirectUri: String): Uri { + return Uri.Builder().scheme("https") + .authority("public-api.wordpress.com") + .path("/oauth2/authorize") + .appendQueryParameter("client_id", appSecrets.appId) + .appendQueryParameter("redirect_uri", redirectUri) + .appendQueryParameter("response_type", "code") + .appendQueryParameter("scope", "global") + .build() + } + + suspend fun exchangeAuthCodeForToken(code: String, redirectUri: String): Result { + val tokenUrl = Uri.Builder() + .scheme("https") + .authority("public-api.wordpress.com") + .path("oauth2/token") + .build() + .toString() + + val formBody = FormBody.Builder() + + mutableMapOf( + "client_id" to appSecrets.appId, + "redirect_uri" to redirectUri, + "client_secret" to appSecrets.appSecret, + "code" to code, + "grant_type" to "authorization_code", + ).forEach { (t, u) -> formBody.add(t, u) } + + val request = Request.Builder() + .url(tokenUrl) + .post(formBody.build()) + .build() + + return withContext(context) { + val response = client.newCall(request).execute() + + if (!response.isSuccessful) { + response.body?.let { Log.e("WPCOM_LOGIN", it.string()) } + Result.failure(WPcomLoginError.AccessDenied) + } else { + val json = response.body?.string() ?: return@withContext Result.failure(WPcomLoginError.InvalidResponse) + val gson = Gson().fromJson(json, WPcomAuthorizationCodeResponse::class.java) + Result.success(gson.access_token) + } + } + } +} + +sealed class WPcomLoginError(val code: Int): Throwable() { + data object AccessDenied: WPcomLoginError(1) + data object InvalidResponse: WPcomLoginError(2) +} diff --git a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/WPcomAuthorizationCodeResponse.kt b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/WPcomAuthorizationCodeResponse.kt new file mode 100644 index 000000000000..6b604e78beb5 --- /dev/null +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/WPcomAuthorizationCodeResponse.kt @@ -0,0 +1,9 @@ +package org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords + +data class WPcomAuthorizationCodeResponse( + val access_token: String, + val token_type: String, + val blog_id: String, + val blog_url: String, + val scope: String +) diff --git a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/store/AccountStore.java b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/store/AccountStore.java index 7e8e63c3288d..cb7a115a6987 100644 --- a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/store/AccountStore.java +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/store/AccountStore.java @@ -1325,6 +1325,12 @@ public String getAccessToken() { return mAccessToken.get(); } + // Ths is the preferred way to authenticate a WordPress.com or Jetpack user in the app + public void updateAccessToken(@NonNull String token) { + mAccessToken.set(token); + emitChange(new OnAuthenticationChanged()); + } + private void updateToken(UpdateTokenPayload updateTokenPayload) { mAccessToken.set(updateTokenPayload.token); emitChange(new OnAuthenticationChanged()); From eb3d0d99d2f97ae7ee624b46b0c05690c2ba6d65 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Mon, 18 Nov 2024 14:51:11 -0700 Subject: [PATCH 02/10] Use Custom Chrome Tabs --- WordPress/build.gradle | 2 ++ .../wordpress/android/ui/accounts/LoginActivity.java | 11 ++++++++--- gradle/libs.versions.toml | 2 ++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 6402167fd714..64a205254217 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -443,6 +443,8 @@ dependencies { implementation(libs.google.mlkit.text.recognition) implementation(libs.google.mlkit.barcode.scanning.main) + implementation(libs.androidx.browser) + // CameraX implementation(libs.androidx.camera.camera2) implementation(libs.androidx.camera.lifecycle) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java index 91d93680b505..2a8cf3a7e758 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java @@ -10,6 +10,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.browser.customtabs.CustomTabsIntent; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; import androidx.lifecycle.ViewModelProvider; @@ -465,9 +466,13 @@ private void startLogin() { @Override public void showEmailLoginScreen(@NonNull Context context) { - Intent loginWithWPcom = new Intent(Intent.ACTION_VIEW, mLoginHelper.loginUri()); - mUnifiedLoginTracker.setFlowAndStep(Flow.WORDPRESS_COM_WEB, Step.START); - context.startActivity(loginWithWPcom); + CustomTabsIntent intent = new CustomTabsIntent.Builder() + .setShareState(CustomTabsIntent.SHARE_STATE_OFF) + .setStartAnimations(this, R.anim.activity_slide_up_from_bottom, R.anim.activity_slide_up_from_bottom) + .setExitAnimations(this, R.anim.activity_slide_out_to_bottom, R.anim.activity_slide_out_to_bottom) + .setUrlBarHidingEnabled(true) + .build(); + intent.launchUrl(this, mLoginHelper.loginUri()); } @Override diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ec10411efc9f..22ce3db0a9d0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,6 +9,7 @@ androidx-activity = '1.9.3' androidx-annotation = '1.9.1' androidx-appcompat = '1.7.0' androidx-arch-core = '2.2.0' +androidx-browser = '1.5.0' androidx-camera = '1.4.0' androidx-cardview = '1.0.0' androidx-compose-bom = '2024.11.00' @@ -120,6 +121,7 @@ androidx-annotation = { group = "androidx.annotation", name = "annotation", vers androidx-appcompat-main = { group = "androidx.appcompat", name = "appcompat", version.ref = "androidx-appcompat" } androidx-appcompat-resources = { group = "androidx.appcompat", name = "appcompat-resources", version.ref = "androidx-appcompat" } androidx-arch-core-testing = { group = "androidx.arch.core", name = "core-testing", version.ref = "androidx-arch-core" } +androidx-browser = { group="androidx.browser", "name" = "browser", version.ref = "androidx-browser" } androidx-camera-camera2 = { group = "androidx.camera", name = "camera-camera2", version.ref = "androidx-camera" } androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycle", version.ref = "androidx-camera" } androidx-camera-view = { group = "androidx.camera", name = "camera-view", version.ref = "androidx-camera" } From e2e9e167e90a43a702aeb3becc99bbd953ea9fd6 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:10:29 -0700 Subject: [PATCH 03/10] Rename showEmailLoginScreen->showWPcomLoginScreen --- .../ui/accounts/login/LoginPrologueRevampedFragment.kt | 2 +- .../org/wordpress/android/ui/accounts/LoginActivity.java | 6 ++++-- .../wordpress/android/ui/accounts/LoginNavigationEvents.kt | 2 +- .../android/ui/accounts/login/LoginPrologueListener.kt | 2 +- .../android/ui/accounts/login/LoginPrologueFragment.kt | 2 +- .../ui/accounts/login/LoginPrologueRevampedFragment.kt | 2 +- 6 files changed, 9 insertions(+), 7 deletions(-) diff --git a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt index c7108f67870a..e12b0359e1d3 100644 --- a/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt +++ b/WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt @@ -56,7 +56,7 @@ class LoginPrologueRevampedFragment : Fragment() { LoginScreenRevamped( onWpComLoginClicked = { viewModel.onWpComLoginClicked() - loginPrologueListener.showEmailLoginScreen(this.context) + loginPrologueListener.showWPcomLoginScreen(this.context) }, onSiteAddressLoginClicked = { viewModel.onSiteAddressLoginClicked() diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java index 2a8cf3a7e758..61f4e55dc6b8 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java @@ -464,8 +464,10 @@ private void startLogin() { // LoginPrologueListener implementation methods - @Override - public void showEmailLoginScreen(@NonNull Context context) { + public void showWPcomLoginScreen(@NonNull Context context) { + AnalyticsTracker.track(AnalyticsTracker.Stat.LOGIN_WPCOM_WEBVIEW); + mUnifiedLoginTracker.setFlowAndStep(Flow.WORDPRESS_COM_WEB, Step.WPCOM_WEB_START); + CustomTabsIntent intent = new CustomTabsIntent.Builder() .setShareState(CustomTabsIntent.SHARE_STATE_OFF) .setStartAnimations(this, R.anim.activity_slide_up_from_bottom, R.anim.activity_slide_up_from_bottom) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginNavigationEvents.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginNavigationEvents.kt index f40cdd64de71..9fa685adf6ee 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginNavigationEvents.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginNavigationEvents.kt @@ -11,7 +11,7 @@ sealed class LoginNavigationEvents { data class SelectSite(val localId: Int) : LoginNavigationEvents() object CreateNewSite : LoginNavigationEvents() object CloseWithResultOk : LoginNavigationEvents() - object ShowEmailLoginScreen : LoginNavigationEvents() + object showWPcomLoginScreen : LoginNavigationEvents() object ShowLoginViaSiteAddressScreen : LoginNavigationEvents() object ShowJetpackIndividualPluginOverlay : LoginNavigationEvents() } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginPrologueListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginPrologueListener.kt index 9a5cb9aa42aa..98b975a38024 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginPrologueListener.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginPrologueListener.kt @@ -4,6 +4,6 @@ import android.content.Context interface LoginPrologueListener { // Login Prologue callbacks - fun showEmailLoginScreen(context: Context) + fun showWPcomLoginScreen(context: Context) fun loginViaSiteAddress() } diff --git a/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueFragment.kt b/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueFragment.kt index 446006d6e47e..cb1d7691d7cc 100644 --- a/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueFragment.kt +++ b/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueFragment.kt @@ -56,7 +56,7 @@ class LoginPrologueFragment : Fragment(R.layout.login_signup_screen) { continueWithWpcomButton.setOnClickListener { unifiedLoginTracker.trackClick(Click.CONTINUE_WITH_WORDPRESS_COM) - loginPrologueListener.showEmailLoginScreen(view.context) + loginPrologueListener.showWPcomLoginScreen(view.context) } enterYourSiteAddressButton.setOnClickListener { diff --git a/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt b/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt index 950054d9fa18..88baf3fc8eb1 100644 --- a/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt +++ b/WordPress/src/wordpress/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt @@ -47,7 +47,7 @@ class LoginPrologueRevampedFragment : Fragment() { AppThemeM2 { LoginScreenRevamped( onWpComLoginClicked = { - loginPrologueListener.showEmailLoginScreen(this.context) + loginPrologueListener.showWPcomLoginScreen(this.context) }, onSiteAddressLoginClicked = loginPrologueListener::loginViaSiteAddress, ) From 8c8a89d9662a335ff65997fc14f27f3134a924ce Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:10:39 -0700 Subject: [PATCH 04/10] Use showWPcomLoginScreen to reauthenticate --- .../java/org/wordpress/android/ui/accounts/LoginActivity.java | 2 +- .../org/wordpress/android/ui/accounts/UnifiedLoginTracker.kt | 3 ++- .../wordpress/android/ui/accounts/login/WPcomLoginHelper.kt | 4 +++- .../org/wordpress/android/analytics/AnalyticsTracker.java | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java index 61f4e55dc6b8..10b75007240a 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java @@ -197,7 +197,7 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { break; case WPCOM_REAUTHENTICATE: mUnifiedLoginTracker.setSource(Source.REAUTHENTICATION); - checkSmartLockPasswordAndStartLogin(); + showWPcomLoginScreen(getBaseContext()); break; case SHARE_INTENT: mUnifiedLoginTracker.setSource(Source.SHARE); diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/UnifiedLoginTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/UnifiedLoginTracker.kt index 58d6efde4d1f..66216876c784 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/UnifiedLoginTracker.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/UnifiedLoginTracker.kt @@ -148,7 +148,8 @@ class UnifiedLoginTracker SHOW_EMAIL_HINTS("show_email_hints"), PASSWORD_CHALLENGE("password_challenge"), NOT_A_JETPACK_SITE("not_a_jetpack_site"), - NO_JETPACK_SITES("no_jetpack_sites") + NO_JETPACK_SITES("no_jetpack_sites"), + WPCOM_WEB_START("wpcom_web_start") } enum class Click(val value: String) { diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt index 86d9b9561296..21d6c24b0f62 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt @@ -8,6 +8,7 @@ import kotlinx.coroutines.runBlocking import org.wordpress.android.BuildConfig import org.wordpress.android.fluxc.network.rest.wpapi.WPcomLoginClient import org.wordpress.android.fluxc.store.AccountStore +import org.wordpress.android.ui.accounts.UnifiedLoginTracker import org.wordpress.android.util.config.AppConfig import javax.inject.Inject import kotlin.coroutines.CoroutineContext @@ -15,7 +16,8 @@ import kotlin.coroutines.CoroutineContext class WPcomLoginHelper @Inject constructor( private val loginClient: WPcomLoginClient, private val accountStore: AccountStore, - private val appConfig: AppConfig + private val appConfig: AppConfig, + private val unifiedLoginTracker: UnifiedLoginTracker ) { private val context: CoroutineContext = Dispatchers.IO diff --git a/libs/analytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java b/libs/analytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java index 645b2d60729b..6d35395daeab 100644 --- a/libs/analytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java +++ b/libs/analytics/src/main/java/org/wordpress/android/analytics/AnalyticsTracker.java @@ -458,6 +458,7 @@ public enum Stat { LOGIN_SOCIAL_2FA_NEEDED, LOGIN_SOCIAL_ACCOUNTS_NEED_CONNECTING, LOGIN_SOCIAL_ERROR_UNKNOWN_USER, + LOGIN_WPCOM_WEBVIEW, LOGIN_WPCOM_BACKGROUND_SERVICE_UPDATE, // This stat is part of a funnel that provides critical information. Before // making ANY modification to this stat please refer to: p4qSXL-35X-p2 From ed0fa69979fdf4131576dc388a3e66bde8012624 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:17:45 -0700 Subject: [PATCH 05/10] =?UTF-8?q?Don=E2=80=99t=20compile=20if=20secrets=20?= =?UTF-8?q?are=20missing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/modules/AppConfigModule.java | 7 +++++-- .../android/ui/accounts/LoginActivity.java | 3 +++ .../ui/accounts/login/WPcomLoginHelper.kt | 11 ++++------- .../network/rest/wpapi/WPcomLoginClient.kt | 4 ++-- .../network/rest/wpcom/auth/AppSecrets.java | 18 +++++++++++++----- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java b/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java index 8845f7dbe586..7ae8ff7c5549 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java @@ -1,7 +1,9 @@ package org.wordpress.android.modules; import android.content.Context; +import android.os.Build; import android.util.Base64; +import androidx.annotation.NonNull; import com.goterl.lazysodium.utils.Key; @@ -19,12 +21,13 @@ import dagger.hilt.android.qualifiers.ApplicationContext; import dagger.hilt.components.SingletonComponent; + @InstallIn(SingletonComponent.class) @Module public class AppConfigModule { - @Provides + @NonNull @Provides public AppSecrets provideAppSecrets() { - return new AppSecrets(BuildConfig.OAUTH_APP_ID, BuildConfig.OAUTH_APP_SECRET); + return new AppSecrets(BuildConfig.OAUTH_APP_ID, BuildConfig.OAUTH_APP_SECRET, BuildConfig.OAUTH_REDIRECT_URI); } @Singleton diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java index 10b75007240a..c8e2cc2a2218 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java @@ -473,7 +473,10 @@ public void showWPcomLoginScreen(@NonNull Context context) { .setStartAnimations(this, R.anim.activity_slide_up_from_bottom, R.anim.activity_slide_up_from_bottom) .setExitAnimations(this, R.anim.activity_slide_out_to_bottom, R.anim.activity_slide_out_to_bottom) .setUrlBarHidingEnabled(true) + .setInstantAppsEnabled(false) + .setShowTitle(false) .build(); + intent.launchUrl(this, mLoginHelper.loginUri()); } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt index 21d6c24b0f62..9e5df8233f9c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt @@ -5,24 +5,21 @@ import android.util.Log import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel import kotlinx.coroutines.runBlocking -import org.wordpress.android.BuildConfig import org.wordpress.android.fluxc.network.rest.wpapi.WPcomLoginClient +import org.wordpress.android.fluxc.network.rest.wpcom.auth.AppSecrets import org.wordpress.android.fluxc.store.AccountStore -import org.wordpress.android.ui.accounts.UnifiedLoginTracker -import org.wordpress.android.util.config.AppConfig import javax.inject.Inject import kotlin.coroutines.CoroutineContext class WPcomLoginHelper @Inject constructor( private val loginClient: WPcomLoginClient, private val accountStore: AccountStore, - private val appConfig: AppConfig, - private val unifiedLoginTracker: UnifiedLoginTracker + private val appSecrets: AppSecrets ) { private val context: CoroutineContext = Dispatchers.IO fun loginUri(): Uri { - return loginClient.loginUri(BuildConfig.OAUTH_REDIRECT_URI) + return loginClient.loginUri(appSecrets.redirectUri) } fun tryLoginWithDataString(data: String?) { @@ -33,7 +30,7 @@ class WPcomLoginHelper @Inject constructor( val code = this.codeFromAuthorizationUri(data) ?: return runBlocking { - val tokenResult = loginClient.exchangeAuthCodeForToken(code, BuildConfig.OAUTH_REDIRECT_URI) + val tokenResult = loginClient.exchangeAuthCodeForToken(code) accountStore.updateAccessToken(tokenResult.getOrThrow()) Log.i("WPCOM_LOGIN", "Login Successful") } diff --git a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt index f38163d7043a..7104eee54a75 100644 --- a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt @@ -31,7 +31,7 @@ class WPcomLoginClient @Inject constructor( .build() } - suspend fun exchangeAuthCodeForToken(code: String, redirectUri: String): Result { + suspend fun exchangeAuthCodeForToken(code: String): Result { val tokenUrl = Uri.Builder() .scheme("https") .authority("public-api.wordpress.com") @@ -43,7 +43,7 @@ class WPcomLoginClient @Inject constructor( mutableMapOf( "client_id" to appSecrets.appId, - "redirect_uri" to redirectUri, + "redirect_uri" to appSecrets.redirectUri, "client_secret" to appSecrets.appSecret, "code" to code, "grant_type" to "authorization_code", diff --git a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/auth/AppSecrets.java b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/auth/AppSecrets.java index 96e966696f6a..3338dca792d7 100644 --- a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/auth/AppSecrets.java +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpcom/auth/AppSecrets.java @@ -1,19 +1,27 @@ package org.wordpress.android.fluxc.network.rest.wpcom.auth; +import androidx.annotation.NonNull; + public class AppSecrets { - private final String mAppId; - private final String mAppSecret; + @NonNull private final String mAppId; + @NonNull private final String mAppSecret; + @NonNull private final String mRedirectUri; - public AppSecrets(String appId, String appSecret) { + public AppSecrets(@NonNull String appId, @NonNull String appSecret, @NonNull String redirectUri) { mAppId = appId; mAppSecret = appSecret; + mRedirectUri = redirectUri; } - public String getAppId() { + public @NonNull String getAppId() { return mAppId; } - public String getAppSecret() { + public @NonNull String getAppSecret() { return mAppSecret; } + + public @NonNull String getRedirectUri() { + return mRedirectUri; + } } From 2ab83b1e9e34968e21eda480b90beeed635e7fbc Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Fri, 22 Nov 2024 11:37:13 -0700 Subject: [PATCH 06/10] Use the latest secrets.properties --- .configure | 4 ++-- .configure-files/secrets.properties.enc | Bin 1808 -> 1904 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.configure b/.configure index f4306f2baab6..c633c89e7acf 100644 --- a/.configure +++ b/.configure @@ -1,7 +1,7 @@ { "project_name": "WordPress-Android", "branch": "trunk", - "pinned_hash": "11fa9c59619ba8d31d0bce2b7ba4412074c00d69", + "pinned_hash": "1c83426e3f9175a6d561f4af53c69a1e2097a6ef", "files_to_copy": [ { "file": "android/WPAndroid/secrets.properties", @@ -47,4 +47,4 @@ "file_dependencies": [ ] -} +} \ No newline at end of file diff --git a/.configure-files/secrets.properties.enc b/.configure-files/secrets.properties.enc index ea962b70e4c448c391778ee3abafb297b3c4b782..481fdf15ab164934141a855533631e56a0a9d00d 100644 GIT binary patch delta 1748 zcmV;_1}piH4)6|;uz!AKJk z^ki|moyzk;04SRU{n4w;4${#JgS1FqzxBa%tnvD8*Jla5(|@MKEmErC1K|FEKugQ& zsWASBk1kz2T`BWcdu7OkSJwAe05DqxPp+P@RGmOk5MxWxQLJ-j!Ey*mFiV2#`V9_3 z;wVvXzbFS(MvXHzmn7MZ_+`bCG-uXnhVaI%q*QJ=)&sfCYRx1_oYBm5s@xO<+;a8W zCZ^l)DgL!hX@3X^<*ES;iY;8&=eN+B-;|u*ivm9m=XF5>TcRrf&*wl@l#PHe=(*Y= zo5cxy576{d=LaMHS{v?1FU!k)HRJ$mDkz;qq8%$hP9NvIIM3a`hCk=TO)iIiTZBpJ zv#erxH>Os8E^6pCZ=)sfwv$v%%JIhs(dGBIlRONQV=G^$Tolv5H#v4M@Vt0fk@H>2 zL}_~vc7J*p6z{Z|w8mw*VFry-xVIZ-I4IN8{)8dS5fReN>%+Vi-X~v+fum)E>9rMeTRiiMuIL9Ypv+%Nk$gf zcN75Bs;-)J;24fMI?fE;I!{jF_WgCOJPrLeF!Ni`#rP(*U^53J;e8}GZ4rQbJLhg^ z9st`a=s~}^^-2R1L3Nh86gwN6@KvdA*?(89Shsm}JTy{K&6t$JB&w|n8?^?H#sTyY zok&4H=p*FxYq14h8H`M-(xvl-++t)wsDLZKRHDeQ1|@r-{)K}ppc^FVWpd%m&$HtJ zGP|a${@*A0d0Js6nzPsVD*|}X>Hyu=0U6c{yP1qt`8deI)9;qZRFt`gp)5*jV1Mw5 z$c`>teFIfF;GR%crn9ioJ>v)?Q#ix} z?SFon;t~l%Ao@`y&`f9yTgP4-*sBaiIjKbCdbIiNCV16XUOVB1y8v8v-EStFdrxn7 zp!q!P@XVO zIL`#xaz=Eqc?(G}zvGrpSq_b&F%D#$12CW*i{uYCy&QPA#q-+IqPc^T|6cpJ#zn_i zhg;rZjeEe?T21jexvdNm$Ll|E$LKnUkj8li!(=r-NTj`Bxz~ts z^@c;Na%o&fw2W2$?7RZ&w~E!-zx*8kP&qE%28xfjtVZOa`jL#dmJmpa4Z8{4oZY&t z%l}&Hj*u}KGj_N>r9h<3?tiJ;(%mFhy*y5lG(p0|KLNNyq0{k{b#6M5*gVGqc*2)p(U0k*P z`<>`~_zoszsZ%gv#Jj)SEs@q#A3ZQ8HHx@8>z delta 1651 zcmV-(28{Xe4v-FzuzzB3_C^GFMp=q(GYE1f(2LFK+sjSaZ+^dKcw;Uc8D{)}lU`?r z^%-oj5y#O#&)C2zbkf|4j87*nToD8y)c+=JNOzC2R)6B2>e%%G5LIpDvKGTx z`_GJjwCwqxukQflurIlt(Ue3PuOtj(0Rswgg@_KTmRA;ZQh#g$zA%u?2bUHx=2bs- zWwHI}a%4MT?)9GV$#}wEl4y4PFwo|)g?>C%!Jx&Q(Ygq5+x&L1Pn<|5uPWmu2I`Vx zYk@ zr2<iODAqy%oj75$C zLa7&9GawTULE;72r&-lUoN45dc0 zm)KE(2Y;ZgZwZ7zgnSn}Pe|vbO+7h*&^)C2#1_z8R|*|+vNJgr_%=@}AP9i+eo#v0 z?8U&2whi^6ORpfj@AZFvqfxXEg?gsD-Dx#pCi=yM%eF^2U|Dko51-Alm=3*&CEd{h)w3^5#U=7qG-usY`5YC{BJCCT8!M-shk`SOllG6B9E`MRcJ?`(3~2s(!)rqM3Z`H;e+ z7BLJiZ>Ys=>ogK<>VtT#QX+g+NJ&0yVt?;)P(iA-&1YZ&U_+svLnkd%viE+HL&N<{ zk1kuvzgS}YiTL+jG0H37%n7G-jOptfO)k*U+px0#qVUcsgdqnAVm2bf_*(-7nAO##cuaeQPv+Y#@m!(@)6G93? z7a^#uBo{g8_2(+5w`X4~sesLJDSxUj)TzWbT4j5s9GWw)*M0xQ%IfIH^^P?M3MVp% zSN3%*w62-SpsIP|550&5n+92Wou zqW9VAjbQzeI4Wf5*wy4F`&u)b;K^LQ&13$J9JW20Qw|#?aV3x)|9{?pet#$i_KyPz zvnfU;r6y!49Lzl`c<4eXSOBRKm->RG@D!igDd|tiTi;&oulak31P?A28^w8q;?FPK zI3?K?VURHHV-!NoDz}W=Mc}uA0zoEvYJ2a}glXIP*5S*M zUR(PNfvu^=vK5P)I6d-LxN9wn#vc+^ZylNRA-khxvUOFvsbt{1{_qV&(=NbX8n!?t zs#~SnMHMM}Gsn>@r*-3jd#!C)3`rjfVUB&d(bmQqMnCH-lXCl7hiv>9P^Wl<7#)dw zeeLk#Rn(Y6K)bR+p!C*p#hIvi#^umzkxfMlcfZtAL6;ijpO&hn`Tfi4xMZTjaX{pw xK^?lb;2PX5dx}Ca6TuF0RJ6$uPgWec)l~a!z|or}2&mh%{la3zHMW=p`58yMC^P^7 From 2824d28f2ed72ab4bff499a84b9d8eb1fcae35db Mon Sep 17 00:00:00 2001 From: Nick Bradbury Date: Mon, 25 Nov 2024 15:36:40 -0500 Subject: [PATCH 07/10] Changed start and exit animations --- .../java/org/wordpress/android/ui/accounts/LoginActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java index c8e2cc2a2218..c0832377670c 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java @@ -470,8 +470,8 @@ public void showWPcomLoginScreen(@NonNull Context context) { CustomTabsIntent intent = new CustomTabsIntent.Builder() .setShareState(CustomTabsIntent.SHARE_STATE_OFF) - .setStartAnimations(this, R.anim.activity_slide_up_from_bottom, R.anim.activity_slide_up_from_bottom) - .setExitAnimations(this, R.anim.activity_slide_out_to_bottom, R.anim.activity_slide_out_to_bottom) + .setStartAnimations(this, R.anim.activity_slide_in_from_right, R.anim.activity_slide_out_to_left) + .setExitAnimations(this, R.anim.activity_slide_in_from_left, R.anim.activity_slide_out_to_right) .setUrlBarHidingEnabled(true) .setInstantAppsEnabled(false) .setShowTitle(false) From f315a0d89d5adcc7912571134539318c79f9b0e0 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:35:19 -0700 Subject: [PATCH 08/10] Preload the login page --- WordPress/src/main/AndroidManifest.xml | 3 ++ .../android/modules/AppConfigModule.java | 1 - .../android/ui/accounts/LoginActivity.java | 6 ++- .../ui/accounts/login/WPcomLoginHelper.kt | 53 +++++++++++++++++-- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/WordPress/src/main/AndroidManifest.xml b/WordPress/src/main/AndroidManifest.xml index 366619328880..7bb11829e833 100644 --- a/WordPress/src/main/AndroidManifest.xml +++ b/WordPress/src/main/AndroidManifest.xml @@ -1157,6 +1157,9 @@ + + + diff --git a/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java b/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java index 7ae8ff7c5549..b71f2adcd2ba 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java @@ -1,7 +1,6 @@ package org.wordpress.android.modules; import android.content.Context; -import android.os.Build; import android.util.Base64; import androidx.annotation.NonNull; diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java index c0832377670c..ae34dd22e879 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/LoginActivity.java @@ -152,6 +152,10 @@ protected void onCreate(@Nullable Bundle savedInstanceState) { // Attempt Login if this activity was created in response to a user confirming login mLoginHelper.tryLoginWithDataString(getIntent().getDataString()); + // Start preloading the WordPress.com login page if needed – this avoids visual hitches + // when displaying that screen + mLoginHelper.bindCustomTabsService(this); + if (mLoginHelper.isLoggedIn()) { this.loggedInAndFinish(new ArrayList(), true); return; @@ -477,7 +481,7 @@ public void showWPcomLoginScreen(@NonNull Context context) { .setShowTitle(false) .build(); - intent.launchUrl(this, mLoginHelper.loginUri()); + intent.launchUrl(this, mLoginHelper.getWpcomLoginUri()); } @Override diff --git a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt index 9e5df8233f9c..1eaf892dad40 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt @@ -1,7 +1,13 @@ package org.wordpress.android.ui.accounts.login +import android.content.ComponentName +import android.content.Context import android.net.Uri import android.util.Log +import androidx.browser.customtabs.CustomTabsCallback +import androidx.browser.customtabs.CustomTabsClient +import androidx.browser.customtabs.CustomTabsServiceConnection +import androidx.browser.customtabs.CustomTabsSession import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.cancel import kotlinx.coroutines.runBlocking @@ -14,13 +20,12 @@ import kotlin.coroutines.CoroutineContext class WPcomLoginHelper @Inject constructor( private val loginClient: WPcomLoginClient, private val accountStore: AccountStore, - private val appSecrets: AppSecrets + appSecrets: AppSecrets ) { private val context: CoroutineContext = Dispatchers.IO - fun loginUri(): Uri { - return loginClient.loginUri(appSecrets.redirectUri) - } + val wpcomLoginUri = loginClient.loginUri(appSecrets.redirectUri) + private val customTabsServiceConnection = ServiceConnection(wpcomLoginUri) fun tryLoginWithDataString(data: String?) { if (data == null) { @@ -44,7 +49,47 @@ class WPcomLoginHelper @Inject constructor( context.cancel() } + fun bindCustomTabsService(context: Context) { + customTabsServiceConnection.bind(context) + } + private fun codeFromAuthorizationUri(string: String): String? { return Uri.parse(string).getQueryParameter("code") } } + +class ServiceConnection( + var uri: Uri +): CustomTabsServiceConnection() { + private var client: CustomTabsClient? = null + private var session: CustomTabsSession? = null + + override fun onCustomTabsServiceConnected(name: ComponentName, client: CustomTabsClient) { + client.warmup(0) + this.client = client + + val session = client.newSession(CustomTabsCallback()) + session?.mayLaunchUrl(uri, null, null) + session?.mayLaunchUrl(Uri.parse("https://wordpress.com/log-in/"), null, null) + + this.session = session + } + + override fun onServiceDisconnected(name: ComponentName?) { + this.client = null + this.session = null + } + + fun bind(context: Context) { + // Do nothing if there is an existing service connection + if (this.client != null) { + return + } + + // Get the default browser package name, this will be null if + // the default browser does not provide a CustomTabsService + val packageName = CustomTabsClient.getPackageName(context, null) ?: return + + CustomTabsClient.bindCustomTabsService(context, packageName, this) + } +} From 921abfe697d160031ee719dde85cf680801b088d Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Wed, 27 Nov 2024 16:51:39 -0700 Subject: [PATCH 09/10] Fix Detekt issues --- .../fluxc/network/rest/wpapi/WPcomLoginClient.kt | 2 +- .../WPcomAuthorizationCodeResponse.kt | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt index 7104eee54a75..8ae0f0f8814b 100644 --- a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/WPcomLoginClient.kt @@ -63,7 +63,7 @@ class WPcomLoginClient @Inject constructor( } else { val json = response.body?.string() ?: return@withContext Result.failure(WPcomLoginError.InvalidResponse) val gson = Gson().fromJson(json, WPcomAuthorizationCodeResponse::class.java) - Result.success(gson.access_token) + Result.success(gson.accessToken) } } } diff --git a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/WPcomAuthorizationCodeResponse.kt b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/WPcomAuthorizationCodeResponse.kt index 6b604e78beb5..0a4f368b9420 100644 --- a/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/WPcomAuthorizationCodeResponse.kt +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/WPcomAuthorizationCodeResponse.kt @@ -1,9 +1,11 @@ package org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords +import com.google.gson.annotations.SerializedName + data class WPcomAuthorizationCodeResponse( - val access_token: String, - val token_type: String, - val blog_id: String, - val blog_url: String, + @SerializedName("access_token") val accessToken: String, + @SerializedName("token_type") val tokenType: String, + @SerializedName("blog_id") val blogId: String, + @SerializedName("blog_url") val blogUrl: String, val scope: String ) From 0fbfecd6a84618190be1ec28bafd5289b721cbdf Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Wed, 27 Nov 2024 17:18:40 -0700 Subject: [PATCH 10/10] Move redirect URI into build.grade MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s not a secret --- WordPress/build.gradle | 2 ++ .../java/org/wordpress/android/modules/AppConfigModule.java | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 64a205254217..fb63863884e1 100644 --- a/WordPress/build.gradle +++ b/WordPress/build.gradle @@ -209,6 +209,7 @@ android { buildConfigField "String", "PUSH_NOTIFICATIONS_APP_KEY", '"org.wordpress.android"' buildConfigField "boolean", "ENABLE_QRCODE_AUTH_FLOW", "false" buildConfigField "boolean", "ENABLE_OPEN_WEB_LINKS_WITH_JP_FLOW", "true" + buildConfigField "String", "WPCOM_REDIRECT_URI", '"wordpress://wpcom-authorize"' manifestPlaceholders = [magicLinkScheme:"wordpress"] } @@ -229,6 +230,7 @@ android { buildConfigField "String", "PUSH_NOTIFICATIONS_APP_KEY", '"com.jetpack.android"' buildConfigField "boolean", "ENABLE_QRCODE_AUTH_FLOW", "true" buildConfigField "boolean", "ENABLE_OPEN_WEB_LINKS_WITH_JP_FLOW", "false" + buildConfigField "String", "WPCOM_REDIRECT_URI", '"jetpack://wpcom-authorize"' manifestPlaceholders = [magicLinkScheme:"jetpack"] diff --git a/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java b/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java index b71f2adcd2ba..2b0d1d4e898e 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java @@ -2,6 +2,7 @@ import android.content.Context; import android.util.Base64; + import androidx.annotation.NonNull; import com.goterl.lazysodium.utils.Key; @@ -26,7 +27,7 @@ public class AppConfigModule { @NonNull @Provides public AppSecrets provideAppSecrets() { - return new AppSecrets(BuildConfig.OAUTH_APP_ID, BuildConfig.OAUTH_APP_SECRET, BuildConfig.OAUTH_REDIRECT_URI); + return new AppSecrets(BuildConfig.OAUTH_APP_ID, BuildConfig.OAUTH_APP_SECRET, BuildConfig.WPCOM_REDIRECT_URI); } @Singleton