зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1147275 - Delete cached OAuth tokens when Firefox Account is removed. r=nalexander
========a31f669a88
Author: vivek <vivekb.balakrishnan@gmail.com> Bug 1147275 - Part 3: Try to delete cached OAuth tokens when account is removed. ========d33fbcaa80
Author: vivek <vivekb.balakrishnan@gmail.com> Date: Mon Apr 6 21:27:45 2015 +0300 Bug 1147275 - Part 2: Include cached OAuth tokens in deleted account intent. ========71230ab56a
Author: vivek <vivekb.balakrishnan@gmail.com> Date: Mon Apr 6 20:41:20 2015 +0300 Bug 1147275 - Part 1: Add token deletion API to OAuth client. ========93b6d074c1
Author: vivek <vivekb.balakrishnan@gmail.com> Date: Mon Apr 6 17:44:17 2015 +0300 Bug 1147275 - Pre: Extract getOAuthServerURI. --HG-- extra : rebase_source : de772d7102ebb29b7a058549e07a619dbecc085c
This commit is contained in:
Родитель
87ca3080b6
Коммит
7d82c01981
|
@ -32,6 +32,7 @@ public class FxAccountOAuthClient10 extends FxAccountAbstractClient {
|
|||
protected static final String JSON_KEY_RESPONSE_TYPE = "response_type";
|
||||
protected static final String JSON_KEY_SCOPE = "scope";
|
||||
protected static final String JSON_KEY_STATE = "state";
|
||||
protected static final String JSON_KEY_TOKEN = "token";
|
||||
protected static final String JSON_KEY_TOKEN_TYPE = "token_type";
|
||||
|
||||
// access_token: A string that can be used for authorized requests to service providers.
|
||||
|
@ -98,4 +99,31 @@ public class FxAccountOAuthClient10 extends FxAccountAbstractClient {
|
|||
|
||||
post(resource, requestBody, delegate);
|
||||
}
|
||||
|
||||
public void deleteToken(final String token, final RequestDelegate<Void> delegate) {
|
||||
final BaseResource resource;
|
||||
try {
|
||||
resource = new BaseResource(new URI(serverURI + "destroy"));
|
||||
} catch (URISyntaxException e) {
|
||||
invokeHandleError(delegate, e);
|
||||
return;
|
||||
}
|
||||
|
||||
resource.delegate = new ResourceDelegate<Void>(resource, delegate) {
|
||||
@Override
|
||||
public void handleSuccess(int status, HttpResponse response, ExtendedJSONObject body) {
|
||||
try {
|
||||
delegate.handleSuccess(null);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
delegate.handleError(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final ExtendedJSONObject requestBody = new ExtendedJSONObject();
|
||||
requestBody.put(JSON_KEY_TOKEN, token);
|
||||
post(resource, requestBody, delegate);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ public class FxAccountConstants {
|
|||
* can be received only by Firefox channels sharing the same Android Firefox
|
||||
* Account type.
|
||||
* <p>
|
||||
* See {@link org.mozilla.gecko.fxa.AndroidFxAccount#makeDeletedAccountIntent(android.content.Context, android.accounts.Account)}
|
||||
* See {@link org.mozilla.gecko.fxa.AndroidFxAccount#makeDeletedAccountIntent()}
|
||||
* for contents of the intent.
|
||||
*
|
||||
* See bug 790931 for additional information in the context of Sync.
|
||||
|
@ -66,6 +66,8 @@ public class FxAccountConstants {
|
|||
|
||||
public static final String ACCOUNT_DELETED_INTENT_VERSION_KEY = "account_deleted_intent_version";
|
||||
public static final String ACCOUNT_DELETED_INTENT_ACCOUNT_KEY = "account_deleted_intent_account";
|
||||
public static final String ACCOUNT_OAUTH_SERVICE_ENDPOINT_KEY = "account_oauth_service_endpoint";
|
||||
public static final String ACCOUNT_DELETED_INTENT_ACCOUNT_AUTH_TOKENS = "account_deleted_intent_auth_tokens";
|
||||
|
||||
/**
|
||||
* This signing-level permission protects broadcast intents that should be
|
||||
|
|
|
@ -11,11 +11,13 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.background.ReadingListConstants;
|
||||
import org.mozilla.gecko.background.common.GlobalConstants;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
|
@ -73,6 +75,19 @@ public class AndroidFxAccount {
|
|||
public static final String BUNDLE_KEY_STATE_LABEL = "stateLabel";
|
||||
public static final String BUNDLE_KEY_STATE = "state";
|
||||
|
||||
// Services may request OAuth tokens from the Firefox Account dynamically.
|
||||
// Each such token is prefixed with "oauth::" and a service-dependent scope.
|
||||
// Such tokens should be destroyed when the account is removed from the device.
|
||||
// This list collects all the known "oauth::" token types in order to delete them when necessary.
|
||||
private static final List<String> KNOWN_OAUTH_TOKEN_TYPES;
|
||||
static {
|
||||
final List<String> list = new ArrayList<>();
|
||||
if (AppConstants.MOZ_ANDROID_READING_LIST_SERVICE) {
|
||||
list.add(ReadingListConstants.AUTH_TOKEN_TYPE);
|
||||
}
|
||||
KNOWN_OAUTH_TOKEN_TYPES = Collections.unmodifiableList(list);
|
||||
}
|
||||
|
||||
public static final Map<String, Boolean> DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP;
|
||||
static {
|
||||
final HashMap<String, Boolean> m = new HashMap<String, Boolean>();
|
||||
|
@ -281,6 +296,15 @@ public class AndroidFxAccount {
|
|||
return accountManager.getUserData(account, ACCOUNT_KEY_TOKEN_SERVER);
|
||||
}
|
||||
|
||||
public String getOAuthServerURI() {
|
||||
// Allow testing against stage.
|
||||
if (FxAccountConstants.STAGE_AUTH_SERVER_ENDPOINT.equals(getAccountServerURI())) {
|
||||
return FxAccountConstants.STAGE_OAUTH_SERVER_ENDPOINT;
|
||||
} else {
|
||||
return FxAccountConstants.DEFAULT_OAUTH_SERVER_ENDPOINT;
|
||||
}
|
||||
}
|
||||
|
||||
private String constructPrefsPath(String product, long version, String extra) throws GeneralSecurityException, UnsupportedEncodingException {
|
||||
String profile = getProfile();
|
||||
String username = account.name;
|
||||
|
@ -599,18 +623,29 @@ public class AndroidFxAccount {
|
|||
/**
|
||||
* Create an intent announcing that a Firefox account will be deleted.
|
||||
*
|
||||
* @param context
|
||||
* Android context.
|
||||
* @param account
|
||||
* Android account being removed.
|
||||
* @return <code>Intent</code> to broadcast.
|
||||
*/
|
||||
public static Intent makeDeletedAccountIntent(final Context context, final Account account) {
|
||||
public Intent makeDeletedAccountIntent() {
|
||||
final Intent intent = new Intent(FxAccountConstants.ACCOUNT_DELETED_ACTION);
|
||||
final List<String> tokens = new ArrayList<>();
|
||||
|
||||
intent.putExtra(FxAccountConstants.ACCOUNT_DELETED_INTENT_VERSION_KEY,
|
||||
Long.valueOf(FxAccountConstants.ACCOUNT_DELETED_INTENT_VERSION));
|
||||
intent.putExtra(FxAccountConstants.ACCOUNT_DELETED_INTENT_ACCOUNT_KEY, account.name);
|
||||
|
||||
// Get the tokens from AccountManager. Note: currently, only reading list service supports OAuth. The following logic will
|
||||
// be extended in future to support OAuth for other services.
|
||||
for (String tokenKey : KNOWN_OAUTH_TOKEN_TYPES) {
|
||||
final String authToken = accountManager.peekAuthToken(account, tokenKey);
|
||||
if (authToken != null) {
|
||||
tokens.add(authToken);
|
||||
}
|
||||
}
|
||||
|
||||
// Update intent with tokens and service URI.
|
||||
intent.putExtra(FxAccountConstants.ACCOUNT_OAUTH_SERVICE_ENDPOINT_KEY, getOAuthServerURI());
|
||||
// Deleted broadcasts are package-private, so there's no security risk include the tokens in the extras
|
||||
intent.putExtra(FxAccountConstants.ACCOUNT_DELETED_INTENT_ACCOUNT_AUTH_TOKENS, tokens.toArray(new String[tokens.size()]));
|
||||
return intent;
|
||||
}
|
||||
|
||||
|
|
|
@ -182,15 +182,7 @@ public class FxAccountAuthenticator extends AbstractAccountAuthenticator {
|
|||
Logger.info(LOG_TAG, "Fetching oauth token with scope: " + scope);
|
||||
|
||||
final Responder responder = new Responder(response, fxAccount);
|
||||
|
||||
// Allow testing against stage.
|
||||
final boolean usingStageAuthServer = FxAccountConstants.STAGE_AUTH_SERVER_ENDPOINT.equals(fxAccount.getAccountServerURI());
|
||||
final String oauthServerUri;
|
||||
if (usingStageAuthServer) {
|
||||
oauthServerUri = FxAccountConstants.STAGE_OAUTH_SERVER_ENDPOINT;
|
||||
} else {
|
||||
oauthServerUri = FxAccountConstants.DEFAULT_OAUTH_SERVER_ENDPOINT;
|
||||
}
|
||||
final String oauthServerUri = fxAccount.getOAuthServerURI();
|
||||
|
||||
final String audience;
|
||||
try {
|
||||
|
@ -360,7 +352,8 @@ public class FxAccountAuthenticator extends AbstractAccountAuthenticator {
|
|||
//
|
||||
// Broadcast intents protected with permissions are secure, so it's okay
|
||||
// to include private information such as a password.
|
||||
final Intent intent = AndroidFxAccount.makeDeletedAccountIntent(context, account);
|
||||
final AndroidFxAccount androidFxAccount = new AndroidFxAccount(context, account);
|
||||
final Intent intent = androidFxAccount.makeDeletedAccountIntent();
|
||||
Logger.info(LOG_TAG, "Account named " + account.name + " being removed; " +
|
||||
"broadcasting secure intent " + intent.getAction() + ".");
|
||||
context.sendBroadcast(intent, FxAccountConstants.PER_ACCOUNT_TYPE_PERMISSION);
|
||||
|
|
|
@ -4,7 +4,12 @@
|
|||
|
||||
package org.mozilla.gecko.fxa.receivers;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.oauth.FxAccountAbstractClient;
|
||||
import org.mozilla.gecko.background.fxa.oauth.FxAccountAbstractClientException.FxAccountAbstractClientRemoteException;
|
||||
import org.mozilla.gecko.background.fxa.oauth.FxAccountOAuthClient10;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.sync.FxAccountNotificationManager;
|
||||
import org.mozilla.gecko.fxa.sync.FxAccountSyncAdapter;
|
||||
|
@ -108,6 +113,47 @@ public class FxAccountDeletedService extends IntentService {
|
|||
// Bug 1147275: Delete cached oauth tokens. There's no way to query all
|
||||
// oauth tokens from Android, so this is tricky to do comprehensively. We
|
||||
// can query, individually, for specific oauth tokens to delete, however.
|
||||
final String oauthServerURI = intent.getStringExtra(FxAccountConstants.ACCOUNT_OAUTH_SERVICE_ENDPOINT_KEY);
|
||||
final String[] tokens = intent.getStringArrayExtra(FxAccountConstants.ACCOUNT_DELETED_INTENT_ACCOUNT_AUTH_TOKENS);
|
||||
if (oauthServerURI != null && tokens != null) {
|
||||
final Executor directExecutor = new Executor() {
|
||||
@Override
|
||||
public void execute(Runnable runnable) {
|
||||
runnable.run();
|
||||
}
|
||||
};
|
||||
|
||||
final FxAccountOAuthClient10 oauthClient = new FxAccountOAuthClient10(oauthServerURI, directExecutor);
|
||||
|
||||
for (String token : tokens) {
|
||||
if (token == null) {
|
||||
Logger.error(LOG_TAG, "Cached OAuth token is null; should never happen. Ignoring.");
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
oauthClient.deleteToken(token, new FxAccountAbstractClient.RequestDelegate<Void>() {
|
||||
@Override
|
||||
public void handleSuccess(Void result) {
|
||||
Logger.info(LOG_TAG, "Successfully deleted cached OAuth token.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleError(Exception e) {
|
||||
Logger.error(LOG_TAG, "Failed to delete cached OAuth token; ignoring.", e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(FxAccountAbstractClientRemoteException e) {
|
||||
Logger.error(LOG_TAG, "Exception during cached OAuth token deletion; ignoring.", e);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Logger.error(LOG_TAG, "Exception during cached OAuth token deletion; ignoring.", e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Logger.error(LOG_TAG, "Cached OAuth server URI is null or cached OAuth tokens are null; ignoring.");
|
||||
}
|
||||
}
|
||||
|
||||
public static void deletePickle(final Context context) {
|
||||
|
|
До Ширина: | Высота: | Размер: 540 B После Ширина: | Высота: | Размер: 540 B |
До Ширина: | Высота: | Размер: 2.2 KiB После Ширина: | Высота: | Размер: 2.2 KiB |
Загрузка…
Ссылка в новой задаче