mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 962320 - User per-profile prefs for FxA, and store token server in account object. r=nalexander
This commit is contained in:
parent
a8b7a9e312
commit
50fdd76d57
@ -12,9 +12,9 @@ public class FxAccountConstants {
|
||||
public static final String ACCOUNT_TYPE = "@MOZ_ANDROID_SHARED_FXACCOUNT_TYPE@";
|
||||
|
||||
public static final String DEFAULT_IDP_ENDPOINT = "https://api-accounts-onepw.dev.lcip.org";
|
||||
public static final String DEFAULT_AUTH_ENDPOINT = "http://auth.oldsync.dev.lcip.org";
|
||||
|
||||
public static final String PREFS_PATH = "fxa.v1";
|
||||
public static final String DEFAULT_TOKEN_SERVER_ENDPOINT = "http://auth.oldsync.dev.lcip.org";
|
||||
public static final String DEFAULT_TOKEN_SERVER_URI = DEFAULT_TOKEN_SERVER_ENDPOINT +
|
||||
(DEFAULT_TOKEN_SERVER_ENDPOINT.endsWith("/") ? "" : "/") + "1.0/sync/1.1";
|
||||
|
||||
// For extra debugging. Not final so it can be changed from Fennec, or from
|
||||
// an add-on.
|
||||
|
@ -162,8 +162,12 @@ public class FxAccountCreateAccountActivity extends FxAccountAbstractSetupActivi
|
||||
Account account;
|
||||
try {
|
||||
final String profile = Constants.DEFAULT_PROFILE;
|
||||
final String tokenServerURI = FxAccountConstants.DEFAULT_TOKEN_SERVER_URI;
|
||||
account = AndroidFxAccount.addAndroidAccount(activity, email, password,
|
||||
profile, serverURI, null, null, false);
|
||||
profile,
|
||||
serverURI,
|
||||
tokenServerURI,
|
||||
null, null, false);
|
||||
if (account == null) {
|
||||
throw new RuntimeException("XXX what?");
|
||||
}
|
||||
|
@ -131,8 +131,11 @@ public class FxAccountSignInActivity extends FxAccountAbstractSetupActivity {
|
||||
Account account;
|
||||
try {
|
||||
final String profile = Constants.DEFAULT_PROFILE;
|
||||
final String tokenServerURI = FxAccountConstants.DEFAULT_TOKEN_SERVER_URI;
|
||||
account = AndroidFxAccount.addAndroidAccount(activity, email, password,
|
||||
serverURI, profile, result.sessionToken, result.keyFetchToken, result.verified);
|
||||
serverURI,
|
||||
tokenServerURI,
|
||||
profile, result.sessionToken, result.keyFetchToken, result.verified);
|
||||
if (account == null) {
|
||||
throw new RuntimeException("XXX what?");
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public interface AbstractFxAccount {
|
||||
* Get the Firefox Account auth server URI that this account login flow should
|
||||
* talk to.
|
||||
*/
|
||||
public String getServerURI();
|
||||
public String getAccountServerURI();
|
||||
|
||||
/**
|
||||
* @return the profile name associated with the account, such as "default".
|
||||
|
@ -5,10 +5,13 @@
|
||||
package org.mozilla.gecko.fxa.authenticator;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.mozilla.gecko.background.common.GlobalConstants;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.browserid.BrowserIDKeyPair;
|
||||
@ -33,9 +36,16 @@ import android.os.Bundle;
|
||||
public class AndroidFxAccount implements AbstractFxAccount {
|
||||
protected static final String LOG_TAG = AndroidFxAccount.class.getSimpleName();
|
||||
|
||||
public static final int CURRENT_ACCOUNT_VERSION = 2;
|
||||
public static final int CURRENT_PREFS_VERSION = 1;
|
||||
|
||||
public static final int CURRENT_ACCOUNT_VERSION = 3;
|
||||
public static final String ACCOUNT_KEY_ACCOUNT_VERSION = "version";
|
||||
public static final String ACCOUNT_KEY_PROFILE = "profile";
|
||||
public static final String ACCOUNT_KEY_IDP_SERVER = "idpServerURI";
|
||||
|
||||
// The audience should always be a prefix of the token server URI.
|
||||
public static final String ACCOUNT_KEY_AUDIENCE = "audience"; // Sync-specific.
|
||||
public static final String ACCOUNT_KEY_TOKEN_SERVER = "tokenServerURI"; // Sync-specific.
|
||||
public static final String ACCOUNT_KEY_DESCRIPTOR = "descriptor";
|
||||
|
||||
public static final int CURRENT_BUNDLE_VERSION = 1;
|
||||
@ -43,7 +53,6 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
||||
public static final String BUNDLE_KEY_ASSERTION = "assertion";
|
||||
public static final String BUNDLE_KEY_CERTIFICATE = "certificate";
|
||||
public static final String BUNDLE_KEY_INVALID = "invalid";
|
||||
public static final String BUNDLE_KEY_SERVERURI = "serverURI";
|
||||
public static final String BUNDLE_KEY_SESSION_TOKEN = "sessionToken";
|
||||
public static final String BUNDLE_KEY_KEY_FETCH_TOKEN = "keyFetchToken";
|
||||
public static final String BUNDLE_KEY_VERIFIED = "verified";
|
||||
@ -196,6 +205,50 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
||||
return accountManager.getUserData(account, ACCOUNT_KEY_PROFILE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getAccountServerURI() {
|
||||
return accountManager.getUserData(account, ACCOUNT_KEY_IDP_SERVER);
|
||||
}
|
||||
|
||||
public String getAudience() {
|
||||
return accountManager.getUserData(account, ACCOUNT_KEY_AUDIENCE);
|
||||
}
|
||||
|
||||
public String getTokenServerURI() {
|
||||
return accountManager.getUserData(account, ACCOUNT_KEY_TOKEN_SERVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* This needs to return a string because of the tortured prefs access in GlobalSession.
|
||||
*/
|
||||
public String getSyncPrefsPath() throws GeneralSecurityException, UnsupportedEncodingException {
|
||||
String profile = getProfile();
|
||||
String username = account.name;
|
||||
|
||||
if (profile == null ||
|
||||
username == null) {
|
||||
throw new IllegalStateException("Missing profile or username. Cannot fetch prefs.");
|
||||
}
|
||||
|
||||
final String tokenServerURI = getTokenServerURI();
|
||||
if (tokenServerURI == null) {
|
||||
throw new IllegalStateException("No token server URI. Cannot fetch prefs.");
|
||||
}
|
||||
|
||||
final String fxaServerURI = getAccountServerURI();
|
||||
if (fxaServerURI == null) {
|
||||
throw new IllegalStateException("No account server URI. Cannot fetch prefs.");
|
||||
}
|
||||
|
||||
final String product = GlobalConstants.BROWSER_INTENT_PACKAGE + ".fxa";
|
||||
final long version = CURRENT_PREFS_VERSION;
|
||||
|
||||
// This is unique for each syncing 'view' of the account.
|
||||
final String serverURLThing = fxaServerURI + "!" + tokenServerURI;
|
||||
return Utils.getPrefsPath(product, username, serverURLThing, profile, version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setQuickStretchedPW(byte[] quickStretchedPW) {
|
||||
accountManager.setPassword(account, quickStretchedPW == null ? null : Utils.byte2Hex(quickStretchedPW));
|
||||
@ -208,11 +261,6 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
||||
return quickStretchedPW == null ? null : Utils.hex2Byte(quickStretchedPW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerURI() {
|
||||
return getBundleData(BUNDLE_KEY_SERVERURI);
|
||||
}
|
||||
|
||||
protected byte[] getUserDataBytes(String key) {
|
||||
String data = accountManager.getUserData(account, key);
|
||||
if (data == null) {
|
||||
@ -343,17 +391,28 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
||||
return o;
|
||||
}
|
||||
|
||||
public static Account addAndroidAccount(Context context, String email, String password, String profile,
|
||||
String serverURI, byte[] sessionToken, byte[] keyFetchToken, boolean verified)
|
||||
throws UnsupportedEncodingException, GeneralSecurityException {
|
||||
public static Account addAndroidAccount(
|
||||
Context context,
|
||||
String email,
|
||||
String password,
|
||||
String profile,
|
||||
String idpServerURI,
|
||||
String tokenServerURI,
|
||||
byte[] sessionToken,
|
||||
byte[] keyFetchToken,
|
||||
boolean verified)
|
||||
throws UnsupportedEncodingException, GeneralSecurityException, URISyntaxException {
|
||||
if (email == null) {
|
||||
throw new IllegalArgumentException("email must not be null");
|
||||
}
|
||||
if (password == null) {
|
||||
throw new IllegalArgumentException("password must not be null");
|
||||
}
|
||||
if (serverURI == null) {
|
||||
throw new IllegalArgumentException("serverURI must not be null");
|
||||
if (idpServerURI == null) {
|
||||
throw new IllegalArgumentException("idpServerURI must not be null");
|
||||
}
|
||||
if (tokenServerURI == null) {
|
||||
throw new IllegalArgumentException("tokenServerURI must not be null");
|
||||
}
|
||||
// sessionToken and keyFetchToken are allowed to be null; they can be
|
||||
// fetched via /account/login from the password. These tokens are generated
|
||||
@ -371,10 +430,12 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
||||
|
||||
Bundle userdata = new Bundle();
|
||||
userdata.putInt(ACCOUNT_KEY_ACCOUNT_VERSION, CURRENT_ACCOUNT_VERSION);
|
||||
userdata.putString(ACCOUNT_KEY_IDP_SERVER, idpServerURI);
|
||||
userdata.putString(ACCOUNT_KEY_TOKEN_SERVER, tokenServerURI);
|
||||
userdata.putString(ACCOUNT_KEY_AUDIENCE, computeAudience(tokenServerURI));
|
||||
|
||||
ExtendedJSONObject descriptor = new ExtendedJSONObject();
|
||||
descriptor.put(BUNDLE_KEY_BUNDLE_VERSION, CURRENT_BUNDLE_VERSION);
|
||||
descriptor.put(BUNDLE_KEY_SERVERURI, serverURI);
|
||||
descriptor.put(BUNDLE_KEY_SESSION_TOKEN, sessionToken == null ? null : Utils.byte2Hex(sessionToken));
|
||||
descriptor.put(BUNDLE_KEY_KEY_FETCH_TOKEN, keyFetchToken == null ? null : Utils.byte2Hex(keyFetchToken));
|
||||
descriptor.put(BUNDLE_KEY_VERIFIED, Boolean.valueOf(verified).toString());
|
||||
@ -392,6 +453,12 @@ public class AndroidFxAccount implements AbstractFxAccount {
|
||||
return account;
|
||||
}
|
||||
|
||||
// TODO: this is shit.
|
||||
private static String computeAudience(String tokenServerURI) throws URISyntaxException {
|
||||
URI uri = new URI(tokenServerURI);
|
||||
return new URI(uri.getScheme(), uri.getHost(), null, null).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
// Boolean.valueOf only returns true for the string "true"; this errors in
|
||||
|
@ -56,7 +56,7 @@ public class FxAccountAuthenticator extends AbstractAccountAuthenticator {
|
||||
userData.putString(JSON_KEY_KA, kA);
|
||||
userData.putString(JSON_KEY_KB, kB);
|
||||
userData.putString(JSON_KEY_IDP_ENDPOINT, FxAccountConstants.DEFAULT_IDP_ENDPOINT);
|
||||
userData.putString(JSON_KEY_AUTH_ENDPOINT, FxAccountConstants.DEFAULT_AUTH_ENDPOINT);
|
||||
userData.putString(JSON_KEY_AUTH_ENDPOINT, FxAccountConstants.DEFAULT_TOKEN_SERVER_ENDPOINT);
|
||||
if (!accountManager.addAccountExplicitly(account, sessionToken, userData)) {
|
||||
Logger.warn(LOG_TAG, "Error adding account named " + account.name + " of type " + account.type);
|
||||
return null;
|
||||
|
@ -54,7 +54,7 @@ public class FxAccountLoginPolicy {
|
||||
}
|
||||
|
||||
protected FxAccountClient makeFxAccountClient() {
|
||||
String serverURI = fxAccount.getServerURI();
|
||||
String serverURI = fxAccount.getAccountServerURI();
|
||||
return new FxAccountClient20(serverURI, executor);
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ public class FxAccountLoginPolicy {
|
||||
};
|
||||
|
||||
public AccountState getAccountState(AbstractFxAccount fxAccount) {
|
||||
String serverURI = fxAccount.getServerURI();
|
||||
String serverURI = fxAccount.getAccountServerURI();
|
||||
byte[] emailUTF8 = fxAccount.getEmailUTF8();
|
||||
byte[] quickStretchedPW = fxAccount.getQuickStretchedPW();
|
||||
if (!fxAccount.isValid() || serverURI == null || emailUTF8 == null || quickStretchedPW == null) {
|
||||
|
@ -23,6 +23,7 @@ import org.mozilla.gecko.fxa.authenticator.FxAccountLoginPolicy;
|
||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.sync.GlobalSession;
|
||||
import org.mozilla.gecko.sync.SharedPreferencesClientsDataDelegate;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.crypto.KeyBundle;
|
||||
import org.mozilla.gecko.sync.delegates.BaseGlobalSessionCallback;
|
||||
import org.mozilla.gecko.sync.delegates.ClientsDataDelegate;
|
||||
@ -157,26 +158,30 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
final BaseGlobalSessionCallback callback = new SessionCallback(latch, syncResult);
|
||||
|
||||
|
||||
try {
|
||||
final String authEndpoint = FxAccountConstants.DEFAULT_AUTH_ENDPOINT;
|
||||
final String tokenServerEndpoint = authEndpoint + (authEndpoint.endsWith("/") ? "" : "/") + "1.0/sync/1.1";
|
||||
final URI tokenServerEndpointURI = new URI(tokenServerEndpoint);
|
||||
|
||||
final AndroidFxAccount fxAccount = new AndroidFxAccount(getContext(), account);
|
||||
final Context context = getContext();
|
||||
final AndroidFxAccount fxAccount = new AndroidFxAccount(context, account);
|
||||
|
||||
if (FxAccountConstants.LOG_PERSONAL_INFORMATION) {
|
||||
fxAccount.dump();
|
||||
}
|
||||
|
||||
final SharedPreferences sharedPrefs = getContext().getSharedPreferences(FxAccountConstants.PREFS_PATH, Context.MODE_PRIVATE); // TODO Ensure preferences are per-Account.
|
||||
final String prefsPath = fxAccount.getSyncPrefsPath();
|
||||
|
||||
final FxAccountLoginPolicy loginPolicy = new FxAccountLoginPolicy(getContext(), fxAccount, executor);
|
||||
// This will be the same chunk of SharedPreferences that GlobalSession/SyncConfiguration will later create.
|
||||
final SharedPreferences sharedPrefs = context.getSharedPreferences(prefsPath, Utils.SHARED_PREFERENCES_MODE);
|
||||
|
||||
final String audience = fxAccount.getAudience();
|
||||
final String tokenServerEndpoint = fxAccount.getTokenServerURI();
|
||||
final URI tokenServerEndpointURI = new URI(tokenServerEndpoint);
|
||||
|
||||
// TODO: why doesn't the loginPolicy extract the audience from the account?
|
||||
final FxAccountLoginPolicy loginPolicy = new FxAccountLoginPolicy(context, fxAccount, executor);
|
||||
loginPolicy.certificateDurationInMilliseconds = 20 * 60 * 1000;
|
||||
loginPolicy.assertionDurationInMilliseconds = 15 * 60 * 1000;
|
||||
Logger.info(LOG_TAG, "Asking for certificates to expire after 20 minutes and assertions to expire after 15 minutes.");
|
||||
|
||||
loginPolicy.login(authEndpoint, new FxAccountLoginDelegate() {
|
||||
loginPolicy.login(audience, new FxAccountLoginDelegate() {
|
||||
@Override
|
||||
public void handleSuccess(final String assertion) {
|
||||
TokenServerClient tokenServerclient = new TokenServerClient(tokenServerEndpointURI, executor);
|
||||
@ -201,7 +206,7 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
final long tokenServerSkew = tokenServerSkewHandler.getSkewInSeconds();
|
||||
AuthHeaderProvider authHeaderProvider = new HawkAuthHeaderProvider(token.id, token.key.getBytes("UTF-8"), false, tokenServerSkew);
|
||||
|
||||
globalSession = new FxAccountGlobalSession(token.endpoint, token.uid, authHeaderProvider, FxAccountConstants.PREFS_PATH, syncKeyBundle, callback, getContext(), extras, clientsDataDelegate);
|
||||
globalSession = new FxAccountGlobalSession(token.endpoint, token.uid, authHeaderProvider, prefsPath, syncKeyBundle, callback, context, extras, clientsDataDelegate);
|
||||
globalSession.start();
|
||||
} catch (Exception e) {
|
||||
callback.handleError(globalSession, e);
|
||||
|
Loading…
Reference in New Issue
Block a user