gracefully handle invalidated auth tokens #954

Merged
akinwale merged 1 commit from invalidated-auth into master 2020-07-05 20:07:22 +02:00
8 changed files with 61 additions and 13 deletions
Showing only changes of commit 74d10e4199 - Show all commits

View file

@ -15,6 +15,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.core.text.HtmlCompat; import androidx.core.text.HtmlCompat;
import androidx.preference.PreferenceManager; import androidx.preference.PreferenceManager;
import io.lbry.browser.exceptions.AuthTokenInvalidatedException;
import io.lbry.browser.utils.Helper; import io.lbry.browser.utils.Helper;
import io.lbry.browser.utils.Lbry; import io.lbry.browser.utils.Lbry;
import io.lbry.browser.utils.LbryAnalytics; import io.lbry.browser.utils.LbryAnalytics;
@ -139,7 +140,11 @@ public class FirstRunActivity extends AppCompatActivity {
this.context = context; this.context = context;
} }
protected Void doInBackground(Void... params) { protected Void doInBackground(Void... params) {
Lbryio.authenticate(context); try {
Lbryio.authenticate(context);
} catch (AuthTokenInvalidatedException ex) {
// pass
}
return null; return null;
} }
} }

View file

@ -117,6 +117,7 @@ import io.lbry.browser.adapter.NavigationMenuAdapter;
import io.lbry.browser.adapter.UrlSuggestionListAdapter; import io.lbry.browser.adapter.UrlSuggestionListAdapter;
import io.lbry.browser.data.DatabaseHelper; import io.lbry.browser.data.DatabaseHelper;
import io.lbry.browser.dialog.ContentScopeDialogFragment; import io.lbry.browser.dialog.ContentScopeDialogFragment;
import io.lbry.browser.exceptions.AuthTokenInvalidatedException;
import io.lbry.browser.exceptions.LbryUriException; import io.lbry.browser.exceptions.LbryUriException;
import io.lbry.browser.listener.CameraPermissionListener; import io.lbry.browser.listener.CameraPermissionListener;
import io.lbry.browser.listener.DownloadActionListener; 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); 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) { if (Lbryio.currentUser == null) {
throw new Exception("Did not retrieve authenticated user."); throw new Exception("Did not retrieve authenticated user.");
} }

View file

@ -167,7 +167,7 @@ public class VerificationActivity extends FragmentActivity implements SignInList
// only sign in required, don't do anything else // only sign in required, don't do anything else
showLoading(); showLoading();
FetchCurrentUserTask task = new FetchCurrentUserTask(new FetchCurrentUserTask.FetchUserTaskHandler() { FetchCurrentUserTask task = new FetchCurrentUserTask(this, new FetchCurrentUserTask.FetchUserTaskHandler() {
@Override @Override
public void onSuccess(User user) { public void onSuccess(User user) {
Lbryio.currentUser = user; Lbryio.currentUser = user;
@ -185,7 +185,7 @@ public class VerificationActivity extends FragmentActivity implements SignInList
} else { } else {
// change pager view depending on flow // change pager view depending on flow
showLoading(); showLoading();
FetchCurrentUserTask task = new FetchCurrentUserTask(new FetchCurrentUserTask.FetchUserTaskHandler() { FetchCurrentUserTask task = new FetchCurrentUserTask(this, new FetchCurrentUserTask.FetchUserTaskHandler() {
@Override @Override
public void onSuccess(User user) { public void onSuccess(User user) {
hideLoading(); hideLoading();
@ -229,7 +229,7 @@ public class VerificationActivity extends FragmentActivity implements SignInList
@Override @Override
public void onPhoneVerified() { public void onPhoneVerified() {
showLoading(); showLoading();
FetchCurrentUserTask task = new FetchCurrentUserTask(new FetchCurrentUserTask.FetchUserTaskHandler() { FetchCurrentUserTask task = new FetchCurrentUserTask(this, new FetchCurrentUserTask.FetchUserTaskHandler() {
@Override @Override
public void onSuccess(User user) { public void onSuccess(User user) {
Lbryio.currentUser = user; Lbryio.currentUser = user;

View file

@ -0,0 +1,4 @@
package io.lbry.browser.exceptions;
public class AuthTokenInvalidatedException extends Exception {
}

View file

@ -1,20 +1,23 @@
package io.lbry.browser.tasks.lbryinc; package io.lbry.browser.tasks.lbryinc;
import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import io.lbry.browser.model.lbryinc.User; import io.lbry.browser.model.lbryinc.User;
import io.lbry.browser.utils.Lbryio; import io.lbry.browser.utils.Lbryio;
public class FetchCurrentUserTask extends AsyncTask<Void, Void, User> { public class FetchCurrentUserTask extends AsyncTask<Void, Void, User> {
private Context context;
private Exception error; private Exception error;
private FetchUserTaskHandler handler; private FetchUserTaskHandler handler;
public FetchCurrentUserTask(FetchUserTaskHandler handler) { public FetchCurrentUserTask(Context context, FetchUserTaskHandler handler) {
this.context = context;
this.handler = handler; this.handler = handler;
} }
protected User doInBackground(Void... params) { protected User doInBackground(Void... params) {
try { try {
return Lbryio.fetchCurrentUser(null); return Lbryio.fetchCurrentUser(context);
} catch (Exception ex) { } catch (Exception ex) {
error = ex; error = ex;
return null; return null;

View file

@ -1,20 +1,28 @@
package io.lbry.browser.tasks.verification; package io.lbry.browser.tasks.verification;
import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import io.lbry.browser.exceptions.AuthTokenInvalidatedException;
import io.lbry.browser.model.lbryinc.User; import io.lbry.browser.model.lbryinc.User;
import io.lbry.browser.utils.Lbryio; import io.lbry.browser.utils.Lbryio;
public class CheckUserEmailVerifiedTask extends AsyncTask<Void, Void, Boolean> { public class CheckUserEmailVerifiedTask extends AsyncTask<Void, Void, Boolean> {
private Context context;
private CheckUserEmailVerifiedHandler handler; private CheckUserEmailVerifiedHandler handler;
public CheckUserEmailVerifiedTask(CheckUserEmailVerifiedHandler handler) { public CheckUserEmailVerifiedTask(Context context, CheckUserEmailVerifiedHandler handler) {
this.context = context;
this.handler = handler; this.handler = handler;
} }
protected Boolean doInBackground(Void... params) { protected Boolean doInBackground(Void... params) {
User user = Lbryio.fetchCurrentUser(null); try {
return user != null && user.isHasVerifiedEmail(); User user = Lbryio.fetchCurrentUser(context);
return user != null && user.isHasVerifiedEmail();
} catch (AuthTokenInvalidatedException ex) {
return false;
}
} }
protected void onPostExecute(Boolean result) { protected void onPostExecute(Boolean result) {

View file

@ -165,7 +165,8 @@ public class EmailVerificationFragment extends Fragment {
} }
private void checkEmailVerified() { private void checkEmailVerified() {
CheckUserEmailVerifiedTask task = new CheckUserEmailVerifiedTask(new CheckUserEmailVerifiedTask.CheckUserEmailVerifiedHandler() { Context context = getContext();
CheckUserEmailVerifiedTask task = new CheckUserEmailVerifiedTask(context, new CheckUserEmailVerifiedTask.CheckUserEmailVerifiedHandler() {
@Override @Override
public void onUserEmailVerified() { public void onUserEmailVerified() {
if (listener != null) { if (listener != null) {

View file

@ -2,11 +2,14 @@ package io.lbry.browser.utils;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.net.Uri; import android.net.Uri;
import android.util.Log; import android.util.Log;
import androidx.preference.PreferenceManager;
import com.google.gson.FieldNamingPolicy; import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
@ -27,6 +30,7 @@ import java.util.concurrent.TimeUnit;
import io.lbry.browser.BuildConfig; import io.lbry.browser.BuildConfig;
import io.lbry.browser.MainActivity; import io.lbry.browser.MainActivity;
import io.lbry.browser.exceptions.AuthTokenInvalidatedException;
import io.lbry.browser.exceptions.LbryioRequestException; import io.lbry.browser.exceptions.LbryioRequestException;
import io.lbry.browser.exceptions.LbryioResponseException; import io.lbry.browser.exceptions.LbryioResponseException;
import io.lbry.browser.model.Claim; 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 { try {
Response response = Lbryio.call("user", "me", context); Response response = Lbryio.call("user", "me", context);
JSONObject object = (JSONObject) parseResponse(response); JSONObject object = (JSONObject) parseResponse(response);
@ -210,6 +214,22 @@ public final class Lbryio {
return user; return user;
} catch (LbryioRequestException | LbryioResponseException | ClassCastException | IllegalStateException ex) { } catch (LbryioRequestException | LbryioResponseException | ClassCastException | IllegalStateException ex) {
LbryAnalytics.logError(String.format("/user/me failed: %s", ex.getMessage()), ex.getClass().getName()); 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); android.util.Log.e(TAG, "Could not retrieve the current user", ex);
return null; return null;
} }
@ -256,7 +276,7 @@ public final class Lbryio {
return currentUser != null && currentUser.isHasVerifiedEmail(); return currentUser != null && currentUser.isHasVerifiedEmail();
} }
public static void authenticate(Context context) { public static void authenticate(Context context) throws AuthTokenInvalidatedException {
User user = fetchCurrentUser(context); User user = fetchCurrentUser(context);
if (user != null) { if (user != null) {
currentUser = user; currentUser = user;