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 ea962b70e4c4..481fdf15ab16 100644 Binary files a/.configure-files/secrets.properties.enc and b/.configure-files/secrets.properties.enc differ diff --git a/WordPress/build.gradle b/WordPress/build.gradle index 366aa3ae6cf5..7e43b5fb749f 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"] @@ -443,6 +445,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/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..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() + loginPrologueListener.showWPcomLoginScreen(this.context) }, onSiteAddressLoginClicked = { viewModel.onSiteAddressLoginClicked() diff --git a/WordPress/src/main/AndroidManifest.xml b/WordPress/src/main/AndroidManifest.xml index d89022fac6cf..1549c759becf 100644 --- a/WordPress/src/main/AndroidManifest.xml +++ b/WordPress/src/main/AndroidManifest.xml @@ -113,7 +113,18 @@ + android:windowSoftInputMode="adjustResize" + android:exported="true"> + + + + + + + + + + + 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..2b0d1d4e898e 100644 --- a/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java +++ b/WordPress/src/main/java/org/wordpress/android/modules/AppConfigModule.java @@ -3,6 +3,8 @@ import android.content.Context; import android.util.Base64; +import androidx.annotation.NonNull; + import com.goterl.lazysodium.utils.Key; import org.wordpress.android.BuildConfig; @@ -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.WPCOM_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 bb4aee4850b8..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 @@ -1,6 +1,7 @@ package org.wordpress.android.ui.accounts; import android.app.Activity; +import android.content.Context; import android.content.Intent; import android.net.Uri; import android.os.Bundle; @@ -9,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; @@ -58,8 +60,10 @@ import org.wordpress.android.ui.accounts.UnifiedLoginTracker.Click; import org.wordpress.android.ui.accounts.UnifiedLoginTracker.Flow; import org.wordpress.android.ui.accounts.UnifiedLoginTracker.Source; +import org.wordpress.android.ui.accounts.UnifiedLoginTracker.Step; import org.wordpress.android.ui.accounts.login.LoginPrologueListener; import org.wordpress.android.ui.accounts.login.LoginPrologueRevampedFragment; +import org.wordpress.android.ui.accounts.login.WPcomLoginHelper; import org.wordpress.android.ui.accounts.login.jetpack.LoginNoSitesFragment; import org.wordpress.android.ui.accounts.login.jetpack.LoginSiteCheckErrorFragment; import org.wordpress.android.ui.main.ChooseSiteActivity; @@ -130,6 +134,7 @@ private enum SmartLockHelperState { private LoginMode mLoginMode; private LoginViewModel mViewModel; + @Inject protected WPcomLoginHelper mLoginHelper; @Inject DispatchingAndroidInjector mDispatchingAndroidInjector; @Inject protected LoginAnalyticsListener mLoginAnalyticsListener; @@ -144,6 +149,18 @@ 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()); + + // 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; + } + LoginFlowThemeHelper.injectMissingCustomAttributes(getTheme()); setContentView(R.layout.login_activity); @@ -184,7 +201,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); @@ -451,9 +468,20 @@ private void startLogin() { // LoginPrologueListener implementation methods - @Override - public void showEmailLoginScreen() { - checkSmartLockPasswordAndStartLogin(); + 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_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) + .build(); + + intent.launchUrl(this, mLoginHelper.getWpcomLoginUri()); } @Override 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/UnifiedLoginTracker.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/UnifiedLoginTracker.kt index ebc0f143f3ea..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 @@ -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"), @@ -147,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/LoginPrologueListener.kt b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/LoginPrologueListener.kt index 2ea009c72b6e..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 @@ -1,7 +1,9 @@ package org.wordpress.android.ui.accounts.login +import android.content.Context + interface LoginPrologueListener { // Login Prologue callbacks - fun showEmailLoginScreen() + fun showWPcomLoginScreen(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..1eaf892dad40 --- /dev/null +++ b/WordPress/src/main/java/org/wordpress/android/ui/accounts/login/WPcomLoginHelper.kt @@ -0,0 +1,95 @@ +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 +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 javax.inject.Inject +import kotlin.coroutines.CoroutineContext + +class WPcomLoginHelper @Inject constructor( + private val loginClient: WPcomLoginClient, + private val accountStore: AccountStore, + appSecrets: AppSecrets +) { + private val context: CoroutineContext = Dispatchers.IO + + val wpcomLoginUri = loginClient.loginUri(appSecrets.redirectUri) + private val customTabsServiceConnection = ServiceConnection(wpcomLoginUri) + + fun tryLoginWithDataString(data: String?) { + if (data == null) { + return + } + + val code = this.codeFromAuthorizationUri(data) ?: return + + runBlocking { + val tokenResult = loginClient.exchangeAuthCodeForToken(code) + accountStore.updateAccessToken(tokenResult.getOrThrow()) + Log.i("WPCOM_LOGIN", "Login Successful") + } + } + + fun isLoggedIn(): Boolean { + return accountStore.hasAccessToken() + } + + fun dispose() { + 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) + } +} 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..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() + 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 0b8817da3b64..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 @@ -46,7 +46,9 @@ class LoginPrologueRevampedFragment : Fragment() { setContent { AppThemeM2 { LoginScreenRevamped( - onWpComLoginClicked = loginPrologueListener::showEmailLoginScreen, + onWpComLoginClicked = { + loginPrologueListener.showWPcomLoginScreen(this.context) + }, onSiteAddressLoginClicked = loginPrologueListener::loginViaSiteAddress, ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8b87e1fab8e9..3588abadf255 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.1' androidx-cardview = '1.0.0' androidx-compose-bom = '2024.12.01' @@ -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" } 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 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..8ae0f0f8814b --- /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): 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 appSecrets.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.accessToken) + } + } + } +} + +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..0a4f368b9420 --- /dev/null +++ b/libs/fluxc/src/main/java/org/wordpress/android/fluxc/network/rest/wpapi/applicationpasswords/WPcomAuthorizationCodeResponse.kt @@ -0,0 +1,11 @@ +package org.wordpress.android.fluxc.network.rest.wpapi.applicationpasswords + +import com.google.gson.annotations.SerializedName + +data class WPcomAuthorizationCodeResponse( + @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 +) 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; + } } 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());