mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 980478 - Generate assertions with no iat and exp: 9999999999999L. r=rnewman
This commit is contained in:
parent
c0e309ea5c
commit
f8696e1593
@ -9,7 +9,9 @@ import java.io.UnsupportedEncodingException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.mozilla.apache.commons.codec.binary.Base64;
|
||||
import org.mozilla.apache.commons.codec.binary.StringUtils;
|
||||
@ -28,6 +30,7 @@ import org.mozilla.gecko.sync.Utils;
|
||||
public class JSONWebTokenUtils {
|
||||
public static final long DEFAULT_CERTIFICATE_DURATION_IN_MILLISECONDS = 60 * 60 * 1000;
|
||||
public static final long DEFAULT_ASSERTION_DURATION_IN_MILLISECONDS = 60 * 60 * 1000;
|
||||
public static final long DEFAULT_FUTURE_EXPIRES_AT_IN_MILLISECONDS = 9999999999999L;
|
||||
public static final String DEFAULT_CERTIFICATE_ISSUER = "127.0.0.1";
|
||||
public static final String DEFAULT_ASSERTION_ISSUER = "127.0.0.1";
|
||||
|
||||
@ -70,8 +73,12 @@ public class JSONWebTokenUtils {
|
||||
return payload;
|
||||
}
|
||||
|
||||
protected static String getPayloadString(String payloadString, String issuer,
|
||||
long issuedAt, String audience, long expiresAt) throws NonObjectJSONException,
|
||||
/**
|
||||
* Public for testing.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static String getPayloadString(String payloadString, String audience, String issuer,
|
||||
Long issuedAt, long expiresAt) throws NonObjectJSONException,
|
||||
IOException, ParseException {
|
||||
ExtendedJSONObject payload;
|
||||
if (payloadString != null) {
|
||||
@ -79,13 +86,16 @@ public class JSONWebTokenUtils {
|
||||
} else {
|
||||
payload = new ExtendedJSONObject();
|
||||
}
|
||||
payload.put("iss", issuer);
|
||||
payload.put("iat", issuedAt);
|
||||
if (audience != null) {
|
||||
payload.put("aud", audience);
|
||||
}
|
||||
payload.put("iss", issuer);
|
||||
if (issuedAt != null) {
|
||||
payload.put("iat", issuedAt);
|
||||
}
|
||||
payload.put("exp", expiresAt);
|
||||
return payload.toJSONString();
|
||||
// TreeMap so that keys are sorted. A small attempt to keep output stable over time.
|
||||
return JSONObject.toJSONString(new TreeMap<Object, Object>(payload.object));
|
||||
}
|
||||
|
||||
protected static String getCertificatePayloadString(VerifyingPublicKey publicKeyToSign, String email) throws NonObjectJSONException, IOException, ParseException {
|
||||
@ -100,33 +110,42 @@ public class JSONWebTokenUtils {
|
||||
public static String createCertificate(VerifyingPublicKey publicKeyToSign, String email,
|
||||
String issuer, long issuedAt, long expiresAt, SigningPrivateKey privateKey) throws NonObjectJSONException, IOException, ParseException, GeneralSecurityException {
|
||||
String certificatePayloadString = getCertificatePayloadString(publicKeyToSign, email);
|
||||
String payloadString = getPayloadString(certificatePayloadString, issuer, issuedAt, null, expiresAt);
|
||||
String payloadString = getPayloadString(certificatePayloadString, null, issuer, issuedAt, expiresAt);
|
||||
return JSONWebTokenUtils.encode(payloadString, privateKey);
|
||||
}
|
||||
|
||||
public static String createCertificate(VerifyingPublicKey publicKeyToSign, String email, SigningPrivateKey privateKey) throws NonObjectJSONException, IOException, ParseException, GeneralSecurityException {
|
||||
String issuer = DEFAULT_CERTIFICATE_ISSUER;
|
||||
long issuedAt = System.currentTimeMillis();
|
||||
long durationInMilliseconds = DEFAULT_CERTIFICATE_DURATION_IN_MILLISECONDS;
|
||||
return createCertificate(publicKeyToSign, email, issuer, issuedAt, issuedAt + durationInMilliseconds, privateKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Browser ID assertion.
|
||||
*
|
||||
* @param privateKeyToSignWith
|
||||
* private key to sign assertion with.
|
||||
* @param certificate
|
||||
* to include in assertion; no attempt is made to ensure the
|
||||
* certificate is valid, or corresponds to the private key, or any
|
||||
* other condition.
|
||||
* @param audience
|
||||
* to produce assertion for.
|
||||
* @param issuer
|
||||
* to produce assertion for.
|
||||
* @param issuedAt
|
||||
* timestamp for assertion, in milliseconds since the epoch; if null,
|
||||
* no timestamp is included.
|
||||
* @param expiresAt
|
||||
* expiration timestamp for assertion, in milliseconds since the epoch.
|
||||
* @return assertion.
|
||||
* @throws NonObjectJSONException
|
||||
* @throws IOException
|
||||
* @throws ParseException
|
||||
* @throws GeneralSecurityException
|
||||
*/
|
||||
public static String createAssertion(SigningPrivateKey privateKeyToSignWith, String certificate, String audience,
|
||||
String issuer, long issuedAt, long durationInMilliseconds) throws NonObjectJSONException, IOException, ParseException, GeneralSecurityException {
|
||||
long expiresAt = issuedAt + durationInMilliseconds;
|
||||
String issuer, Long issuedAt, long expiresAt) throws NonObjectJSONException, IOException, ParseException, GeneralSecurityException {
|
||||
String emptyAssertionPayloadString = "{}";
|
||||
String payloadString = getPayloadString(emptyAssertionPayloadString, issuer, issuedAt, audience, expiresAt);
|
||||
String payloadString = getPayloadString(emptyAssertionPayloadString, audience, issuer, issuedAt, expiresAt);
|
||||
String signature = JSONWebTokenUtils.encode(payloadString, privateKeyToSignWith);
|
||||
return certificate + "~" + signature;
|
||||
}
|
||||
|
||||
public static String createAssertion(SigningPrivateKey privateKeyToSignWith, String certificate, String audience) throws NonObjectJSONException, IOException, ParseException, GeneralSecurityException {
|
||||
String issuer = DEFAULT_ASSERTION_ISSUER;
|
||||
long issuedAt = System.currentTimeMillis();
|
||||
long durationInMilliseconds = DEFAULT_ASSERTION_DURATION_IN_MILLISECONDS;
|
||||
return createAssertion(privateKeyToSignWith, certificate, audience, issuer, issuedAt, durationInMilliseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* For debugging only!
|
||||
*
|
||||
|
@ -40,18 +40,17 @@ public class MockMyIDTokenFactory {
|
||||
* sign username@mockmyid.com
|
||||
* @param issuedAt
|
||||
* timestamp for certificate, in milliseconds since the epoch.
|
||||
* @param durationInMilliseconds
|
||||
* lifespan of certificate, in milliseconds.
|
||||
* @param expiresAt
|
||||
* expiration timestamp for certificate, in milliseconds since the epoch.
|
||||
* @return encoded certificate string.
|
||||
* @throws Exception
|
||||
*/
|
||||
public String createMockMyIDCertificate(final VerifyingPublicKey publicKeyToSign, String username,
|
||||
final long issuedAt, final long durationInMilliseconds)
|
||||
final long issuedAt, final long expiresAt)
|
||||
throws Exception {
|
||||
if (!username.endsWith("@mockmyid.com")) {
|
||||
username = username + "@mockmyid.com";
|
||||
}
|
||||
long expiresAt = issuedAt + durationInMilliseconds;
|
||||
SigningPrivateKey mockMyIdPrivateKey = getMockMyIDPrivateKey();
|
||||
return JSONWebTokenUtils.createCertificate(publicKeyToSign, username, "mockmyid.com", issuedAt, expiresAt, mockMyIdPrivateKey);
|
||||
}
|
||||
@ -69,8 +68,9 @@ public class MockMyIDTokenFactory {
|
||||
*/
|
||||
public String createMockMyIDCertificate(final VerifyingPublicKey publicKeyToSign, final String username)
|
||||
throws Exception {
|
||||
return createMockMyIDCertificate(publicKeyToSign, username,
|
||||
System.currentTimeMillis(), JSONWebTokenUtils.DEFAULT_CERTIFICATE_DURATION_IN_MILLISECONDS );
|
||||
long ciat = System.currentTimeMillis();
|
||||
long cexp = ciat + JSONWebTokenUtils.DEFAULT_CERTIFICATE_DURATION_IN_MILLISECONDS;
|
||||
return createMockMyIDCertificate(publicKeyToSign, username, ciat, cexp);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -84,23 +84,24 @@ public class MockMyIDTokenFactory {
|
||||
* sign username@mockmyid.com.
|
||||
* @param certificateIssuedAt
|
||||
* timestamp for certificate, in milliseconds since the epoch.
|
||||
* @param certificateDurationInMilliseconds
|
||||
* lifespan of certificate, in milliseconds.
|
||||
* @param certificateExpiresAt
|
||||
* expiration timestamp for certificate, in milliseconds since the epoch.
|
||||
* @param assertionIssuedAt
|
||||
* timestamp for assertion, in milliseconds since the epoch.
|
||||
* @param assertionDurationInMilliseconds
|
||||
* lifespan of assertion, in milliseconds.
|
||||
* timestamp for assertion, in milliseconds since the epoch; if null,
|
||||
* no timestamp is included.
|
||||
* @param assertionExpiresAt
|
||||
* expiration timestamp for assertion, in milliseconds since the epoch.
|
||||
* @return encoded assertion string.
|
||||
* @throws Exception
|
||||
*/
|
||||
public String createMockMyIDAssertion(BrowserIDKeyPair keyPair, String username, String audience,
|
||||
long certificateIssuedAt, long certificateDurationInMilliseconds,
|
||||
long assertionIssuedAt, long assertionDurationInMilliseconds)
|
||||
long certificateIssuedAt, long certificateExpiresAt,
|
||||
Long assertionIssuedAt, long assertionExpiresAt)
|
||||
throws Exception {
|
||||
String certificate = createMockMyIDCertificate(keyPair.getPublic(), username,
|
||||
certificateIssuedAt, certificateDurationInMilliseconds);
|
||||
certificateIssuedAt, certificateExpiresAt);
|
||||
return JSONWebTokenUtils.createAssertion(keyPair.getPrivate(), certificate, audience,
|
||||
JSONWebTokenUtils.DEFAULT_ASSERTION_ISSUER, assertionIssuedAt, assertionDurationInMilliseconds);
|
||||
JSONWebTokenUtils.DEFAULT_ASSERTION_ISSUER, assertionIssuedAt, assertionExpiresAt);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,9 +118,11 @@ public class MockMyIDTokenFactory {
|
||||
*/
|
||||
public String createMockMyIDAssertion(BrowserIDKeyPair keyPair, String username, String audience)
|
||||
throws Exception {
|
||||
long now = System.currentTimeMillis();
|
||||
long ciat = System.currentTimeMillis();
|
||||
long cexp = ciat + JSONWebTokenUtils.DEFAULT_CERTIFICATE_DURATION_IN_MILLISECONDS;
|
||||
long aiat = ciat + 1;
|
||||
long aexp = aiat + JSONWebTokenUtils.DEFAULT_ASSERTION_DURATION_IN_MILLISECONDS;
|
||||
return createMockMyIDAssertion(keyPair, username, audience,
|
||||
now, JSONWebTokenUtils.DEFAULT_CERTIFICATE_DURATION_IN_MILLISECONDS,
|
||||
now + 1, JSONWebTokenUtils.DEFAULT_ASSERTION_DURATION_IN_MILLISECONDS);
|
||||
ciat, cexp, aiat, aexp);
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ public class FxAccountConstants {
|
||||
public static final String DEFAULT_AUTH_SERVER_ENDPOINT = "https://api.accounts.firefox.com/v1";
|
||||
public static final String DEFAULT_TOKEN_SERVER_ENDPOINT = "https://token.services.mozilla.com/1.0/sync/1.5";
|
||||
|
||||
public static final String STAGE_TOKEN_SERVER_ENDPOINT = "https://token.stage.mozaws.net/1.0/sync/1.5";
|
||||
|
||||
// For extra debugging. Not final so it can be changed from Fennec, or from
|
||||
// an add-on.
|
||||
public static boolean LOG_PERSONAL_INFORMATION = false;
|
||||
|
@ -56,8 +56,11 @@ public class Married extends TokensAndKeysState {
|
||||
delegate.handleTransition(new LogMessage("staying married"), this);
|
||||
}
|
||||
|
||||
public String generateAssertion(String audience, String issuer, long issuedAt, long durationInMilliseconds) throws NonObjectJSONException, IOException, ParseException, GeneralSecurityException {
|
||||
String assertion = JSONWebTokenUtils.createAssertion(keyPair.getPrivate(), certificate, audience, issuer, issuedAt, durationInMilliseconds);
|
||||
public String generateAssertion(String audience, String issuer) throws NonObjectJSONException, IOException, ParseException, GeneralSecurityException {
|
||||
// We generate assertions with no iat and an exp after 2050 to avoid
|
||||
// invalid-timestamp errors from the token server.
|
||||
final long expiresAt = JSONWebTokenUtils.DEFAULT_FUTURE_EXPIRES_AT_IN_MILLISECONDS;
|
||||
String assertion = JSONWebTokenUtils.createAssertion(keyPair.getPrivate(), certificate, audience, issuer, null, expiresAt);
|
||||
if (!FxAccountConstants.LOG_PERSONAL_INFORMATION) {
|
||||
return assertion;
|
||||
}
|
||||
|
@ -347,9 +347,9 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
// skew adjustment that the HawkAuthHeaderProvider uses to adjust its
|
||||
// timestamps. Eventually we might want this to adapt within the scope of a
|
||||
// global session.
|
||||
final SkewHandler tokenServerSkewHandler = SkewHandler.getSkewHandlerForHostname(storageHostname);
|
||||
final long tokenServerSkew = tokenServerSkewHandler.getSkewInSeconds();
|
||||
final AuthHeaderProvider authHeaderProvider = new HawkAuthHeaderProvider(token.id, token.key.getBytes("UTF-8"), false, tokenServerSkew);
|
||||
final SkewHandler storageServerSkewHandler = SkewHandler.getSkewHandlerForHostname(storageHostname);
|
||||
final long storageServerSkew = storageServerSkewHandler.getSkewInSeconds();
|
||||
final AuthHeaderProvider authHeaderProvider = new HawkAuthHeaderProvider(token.id, token.key.getBytes("UTF-8"), false, storageServerSkew);
|
||||
|
||||
final Context context = getContext();
|
||||
final SyncConfiguration syncConfig = new SyncConfiguration(token.uid, authHeaderProvider, sharedPrefs, syncKeyBundle);
|
||||
@ -503,11 +503,7 @@ public class FxAccountSyncAdapter extends AbstractThreadedSyncAdapter {
|
||||
}
|
||||
|
||||
final Married married = (Married) state;
|
||||
SkewHandler skewHandler = SkewHandler.getSkewHandlerFromEndpointString(tokenServerEndpoint);
|
||||
final long now = System.currentTimeMillis();
|
||||
final long issuedAtMillis = now + skewHandler.getSkewInMillis();
|
||||
final long assertionDurationMillis = this.getAssertionDurationInMilliseconds();
|
||||
final String assertion = married.generateAssertion(audience, JSONWebTokenUtils.DEFAULT_ASSERTION_ISSUER, issuedAtMillis, assertionDurationMillis);
|
||||
final String assertion = married.generateAssertion(audience, JSONWebTokenUtils.DEFAULT_ASSERTION_ISSUER);
|
||||
|
||||
/*
|
||||
* At this point we're in the correct state to sync, and we're ready to fetch
|
||||
|
Loading…
Reference in New Issue
Block a user