From 74d10e4199f2f0a48878268136536de0253fe946 Mon Sep 17 00:00:00 2001 From: Akinwale Ariwodola Date: Sun, 5 Jul 2020 18:40:31 +0100 Subject: [PATCH] gracefully handle invalidated auth tokens --- .../io/lbry/browser/FirstRunActivity.java | 7 +++++- .../java/io/lbry/browser/MainActivity.java | 9 ++++++- .../io/lbry/browser/VerificationActivity.java | 6 ++--- .../AuthTokenInvalidatedException.java | 4 ++++ .../tasks/lbryinc/FetchCurrentUserTask.java | 7 ++++-- .../CheckUserEmailVerifiedTask.java | 14 ++++++++--- .../EmailVerificationFragment.java | 3 ++- .../java/io/lbry/browser/utils/Lbryio.java | 24 +++++++++++++++++-- 8 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/io/lbry/browser/exceptions/AuthTokenInvalidatedException.java diff --git a/app/src/main/java/io/lbry/browser/FirstRunActivity.java b/app/src/main/java/io/lbry/browser/FirstRunActivity.java index df618fe5..ad10a6ef 100644 --- a/app/src/main/java/io/lbry/browser/FirstRunActivity.java +++ b/app/src/main/java/io/lbry/browser/FirstRunActivity.java @@ -15,6 +15,7 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.core.text.HtmlCompat; import androidx.preference.PreferenceManager; +import io.lbry.browser.exceptions.AuthTokenInvalidatedException; import io.lbry.browser.utils.Helper; import io.lbry.browser.utils.Lbry; import io.lbry.browser.utils.LbryAnalytics; @@ -139,7 +140,11 @@ public class FirstRunActivity extends AppCompatActivity { this.context = context; } protected Void doInBackground(Void... params) { - Lbryio.authenticate(context); + try { + Lbryio.authenticate(context); + } catch (AuthTokenInvalidatedException ex) { + // pass + } return null; } } diff --git a/app/src/main/java/io/lbry/browser/MainActivity.java b/app/src/main/java/io/lbry/browser/MainActivity.java index a31597de..a6abf1c7 100644 --- a/app/src/main/java/io/lbry/browser/MainActivity.java +++ b/app/src/main/java/io/lbry/browser/MainActivity.java @@ -117,6 +117,7 @@ import io.lbry.browser.adapter.NavigationMenuAdapter; import io.lbry.browser.adapter.UrlSuggestionListAdapter; import io.lbry.browser.data.DatabaseHelper; import io.lbry.browser.dialog.ContentScopeDialogFragment; +import io.lbry.browser.exceptions.AuthTokenInvalidatedException; import io.lbry.browser.exceptions.LbryUriException; import io.lbry.browser.listener.CameraPermissionListener; import io.lbry.browser.listener.DownloadActionListener; @@ -2384,7 +2385,13 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener } startupStages.put(STARTUP_STAGE_EXCHANGE_RATE_LOADED, true); - Lbryio.authenticate(context); + try { + Lbryio.authenticate(context); + } catch (AuthTokenInvalidatedException ex) { + // if this happens, attempt to authenticate again, so that we can obtain a new auth token + // this will also result in the user having to sign in again + Lbryio.authenticate(context); + } if (Lbryio.currentUser == null) { throw new Exception("Did not retrieve authenticated user."); } diff --git a/app/src/main/java/io/lbry/browser/VerificationActivity.java b/app/src/main/java/io/lbry/browser/VerificationActivity.java index ac489ce3..f332b25d 100644 --- a/app/src/main/java/io/lbry/browser/VerificationActivity.java +++ b/app/src/main/java/io/lbry/browser/VerificationActivity.java @@ -167,7 +167,7 @@ public class VerificationActivity extends FragmentActivity implements SignInList // only sign in required, don't do anything else showLoading(); - FetchCurrentUserTask task = new FetchCurrentUserTask(new FetchCurrentUserTask.FetchUserTaskHandler() { + FetchCurrentUserTask task = new FetchCurrentUserTask(this, new FetchCurrentUserTask.FetchUserTaskHandler() { @Override public void onSuccess(User user) { Lbryio.currentUser = user; @@ -185,7 +185,7 @@ public class VerificationActivity extends FragmentActivity implements SignInList } else { // change pager view depending on flow showLoading(); - FetchCurrentUserTask task = new FetchCurrentUserTask(new FetchCurrentUserTask.FetchUserTaskHandler() { + FetchCurrentUserTask task = new FetchCurrentUserTask(this, new FetchCurrentUserTask.FetchUserTaskHandler() { @Override public void onSuccess(User user) { hideLoading(); @@ -229,7 +229,7 @@ public class VerificationActivity extends FragmentActivity implements SignInList @Override public void onPhoneVerified() { showLoading(); - FetchCurrentUserTask task = new FetchCurrentUserTask(new FetchCurrentUserTask.FetchUserTaskHandler() { + FetchCurrentUserTask task = new FetchCurrentUserTask(this, new FetchCurrentUserTask.FetchUserTaskHandler() { @Override public void onSuccess(User user) { Lbryio.currentUser = user; diff --git a/app/src/main/java/io/lbry/browser/exceptions/AuthTokenInvalidatedException.java b/app/src/main/java/io/lbry/browser/exceptions/AuthTokenInvalidatedException.java new file mode 100644 index 00000000..f1e768af --- /dev/null +++ b/app/src/main/java/io/lbry/browser/exceptions/AuthTokenInvalidatedException.java @@ -0,0 +1,4 @@ +package io.lbry.browser.exceptions; + +public class AuthTokenInvalidatedException extends Exception { +} diff --git a/app/src/main/java/io/lbry/browser/tasks/lbryinc/FetchCurrentUserTask.java b/app/src/main/java/io/lbry/browser/tasks/lbryinc/FetchCurrentUserTask.java index 3be8e03e..eef296d3 100644 --- a/app/src/main/java/io/lbry/browser/tasks/lbryinc/FetchCurrentUserTask.java +++ b/app/src/main/java/io/lbry/browser/tasks/lbryinc/FetchCurrentUserTask.java @@ -1,20 +1,23 @@ package io.lbry.browser.tasks.lbryinc; +import android.content.Context; import android.os.AsyncTask; import io.lbry.browser.model.lbryinc.User; import io.lbry.browser.utils.Lbryio; public class FetchCurrentUserTask extends AsyncTask { + private Context context; private Exception error; private FetchUserTaskHandler handler; - public FetchCurrentUserTask(FetchUserTaskHandler handler) { + public FetchCurrentUserTask(Context context, FetchUserTaskHandler handler) { + this.context = context; this.handler = handler; } protected User doInBackground(Void... params) { try { - return Lbryio.fetchCurrentUser(null); + return Lbryio.fetchCurrentUser(context); } catch (Exception ex) { error = ex; return null; diff --git a/app/src/main/java/io/lbry/browser/tasks/verification/CheckUserEmailVerifiedTask.java b/app/src/main/java/io/lbry/browser/tasks/verification/CheckUserEmailVerifiedTask.java index f058b7b5..fdf54524 100644 --- a/app/src/main/java/io/lbry/browser/tasks/verification/CheckUserEmailVerifiedTask.java +++ b/app/src/main/java/io/lbry/browser/tasks/verification/CheckUserEmailVerifiedTask.java @@ -1,20 +1,28 @@ package io.lbry.browser.tasks.verification; +import android.content.Context; import android.os.AsyncTask; +import io.lbry.browser.exceptions.AuthTokenInvalidatedException; import io.lbry.browser.model.lbryinc.User; import io.lbry.browser.utils.Lbryio; public class CheckUserEmailVerifiedTask extends AsyncTask { + private Context context; private CheckUserEmailVerifiedHandler handler; - public CheckUserEmailVerifiedTask(CheckUserEmailVerifiedHandler handler) { + public CheckUserEmailVerifiedTask(Context context, CheckUserEmailVerifiedHandler handler) { + this.context = context; this.handler = handler; } protected Boolean doInBackground(Void... params) { - User user = Lbryio.fetchCurrentUser(null); - return user != null && user.isHasVerifiedEmail(); + try { + User user = Lbryio.fetchCurrentUser(context); + return user != null && user.isHasVerifiedEmail(); + } catch (AuthTokenInvalidatedException ex) { + return false; + } } protected void onPostExecute(Boolean result) { diff --git a/app/src/main/java/io/lbry/browser/ui/verification/EmailVerificationFragment.java b/app/src/main/java/io/lbry/browser/ui/verification/EmailVerificationFragment.java index f8ffeb3b..277aba59 100644 --- a/app/src/main/java/io/lbry/browser/ui/verification/EmailVerificationFragment.java +++ b/app/src/main/java/io/lbry/browser/ui/verification/EmailVerificationFragment.java @@ -165,7 +165,8 @@ public class EmailVerificationFragment extends Fragment { } private void checkEmailVerified() { - CheckUserEmailVerifiedTask task = new CheckUserEmailVerifiedTask(new CheckUserEmailVerifiedTask.CheckUserEmailVerifiedHandler() { + Context context = getContext(); + CheckUserEmailVerifiedTask task = new CheckUserEmailVerifiedTask(context, new CheckUserEmailVerifiedTask.CheckUserEmailVerifiedHandler() { @Override public void onUserEmailVerified() { if (listener != null) { diff --git a/app/src/main/java/io/lbry/browser/utils/Lbryio.java b/app/src/main/java/io/lbry/browser/utils/Lbryio.java index 3beb53ae..0b3561ac 100644 --- a/app/src/main/java/io/lbry/browser/utils/Lbryio.java +++ b/app/src/main/java/io/lbry/browser/utils/Lbryio.java @@ -2,11 +2,14 @@ package io.lbry.browser.utils; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.net.Uri; import android.util.Log; +import androidx.preference.PreferenceManager; + import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -27,6 +30,7 @@ import java.util.concurrent.TimeUnit; import io.lbry.browser.BuildConfig; import io.lbry.browser.MainActivity; +import io.lbry.browser.exceptions.AuthTokenInvalidatedException; import io.lbry.browser.exceptions.LbryioRequestException; import io.lbry.browser.exceptions.LbryioResponseException; import io.lbry.browser.model.Claim; @@ -200,7 +204,7 @@ public final class Lbryio { } } - public static User fetchCurrentUser(Context context) { + public static User fetchCurrentUser(Context context) throws AuthTokenInvalidatedException { try { Response response = Lbryio.call("user", "me", context); JSONObject object = (JSONObject) parseResponse(response); @@ -210,6 +214,22 @@ public final class Lbryio { return user; } catch (LbryioRequestException | LbryioResponseException | ClassCastException | IllegalStateException ex) { LbryAnalytics.logError(String.format("/user/me failed: %s", ex.getMessage()), ex.getClass().getName()); + + if (ex instanceof LbryioResponseException) { + LbryioResponseException error = (LbryioResponseException) ex; + if (error.getStatusCode() == 403) { + // auth token invalidated + AUTH_TOKEN = null; + // remove the cached auth token + if (context != null) { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); + sp.edit().remove(MainActivity.PREFERENCE_KEY_AUTH_TOKEN).apply(); + } + + throw new AuthTokenInvalidatedException(); + } + } + android.util.Log.e(TAG, "Could not retrieve the current user", ex); return null; } @@ -256,7 +276,7 @@ public final class Lbryio { return currentUser != null && currentUser.isHasVerifiedEmail(); } - public static void authenticate(Context context) { + public static void authenticate(Context context) throws AuthTokenInvalidatedException { User user = fetchCurrentUser(context); if (user != null) { currentUser = user;