gracefully handle invalidated auth tokens #954
8 changed files with 61 additions and 13 deletions
|
@ -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) {
|
||||||
|
try {
|
||||||
Lbryio.authenticate(context);
|
Lbryio.authenticate(context);
|
||||||
|
} catch (AuthTokenInvalidatedException ex) {
|
||||||
|
// pass
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
try {
|
||||||
Lbryio.authenticate(context);
|
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.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
package io.lbry.browser.exceptions;
|
||||||
|
|
||||||
|
public class AuthTokenInvalidatedException extends Exception {
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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 {
|
||||||
|
User user = Lbryio.fetchCurrentUser(context);
|
||||||
return user != null && user.isHasVerifiedEmail();
|
return user != null && user.isHasVerifiedEmail();
|
||||||
|
} catch (AuthTokenInvalidatedException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onPostExecute(Boolean result) {
|
protected void onPostExecute(Boolean result) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue