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

View file

@ -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) {
try {
Lbryio.authenticate(context);
} catch (AuthTokenInvalidatedException ex) {
// pass
}
return null;
}
}

View file

@ -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);
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.");
}

View file

@ -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;

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;
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<Void, Void, User> {
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;

View file

@ -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<Void, Void, Boolean> {
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);
try {
User user = Lbryio.fetchCurrentUser(context);
return user != null && user.isHasVerifiedEmail();
} catch (AuthTokenInvalidatedException ex) {
return false;
}
}
protected void onPostExecute(Boolean result) {

View file

@ -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) {

View file

@ -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;