Skip to content

Adding iidMigrationToken in the create installation request header. #1096

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion firebase-installations/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ package com.google.firebase.installations.remote {

public class FirebaseInstallationServiceClient {
ctor public FirebaseInstallationServiceClient(@NonNull android.content.Context, @Nullable com.google.firebase.platforminfo.UserAgentPublisher, @Nullable com.google.firebase.heartbeatinfo.HeartBeatInfo);
method @NonNull public com.google.firebase.installations.remote.InstallationResponse createFirebaseInstallation(@NonNull String, @NonNull String, @NonNull String, @NonNull String) throws java.io.IOException;
method @NonNull public com.google.firebase.installations.remote.InstallationResponse createFirebaseInstallation(@NonNull String, @NonNull String, @NonNull String, @NonNull String, @Nullable String) throws java.io.IOException;
method @NonNull public void deleteFirebaseInstallation(@NonNull String, @NonNull String, @NonNull String, @NonNull String) throws com.google.firebase.FirebaseException, java.io.IOException;
method @NonNull public com.google.firebase.installations.remote.TokenResult generateAuthToken(@NonNull String, @NonNull String, @NonNull String, @NonNull String) throws java.io.IOException;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,8 +307,8 @@ private final void doRegistrationInternal(boolean forceRefresh) {
* been persisted.
*/
private PersistedInstallationEntry getPrefsWithGeneratedIdMultiProcessSafe() {
CrossProcessLock lock = CrossProcessLock
.acquire(firebaseApp.getApplicationContext(), LOCKFILE_NAME_GENERATE_FID);
CrossProcessLock lock =
CrossProcessLock.acquire(firebaseApp.getApplicationContext(), LOCKFILE_NAME_GENERATE_FID);
try {
synchronized (lockGenerateFid) {
PersistedInstallationEntry prefs =
Expand Down Expand Up @@ -354,7 +354,8 @@ private PersistedInstallationEntry registerFidWithServer(PersistedInstallationEn
/*apiKey= */ firebaseApp.getOptions().getApiKey(),
/*fid= */ prefs.getFirebaseInstallationId(),
/*projectID= */ firebaseApp.getOptions().getProjectId(),
/*appId= */ getApplicationId());
/*appId= */ getApplicationId(),
/* migration-header= */ null);

switch (response.getResponseCode()) {
case OK:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public class FirebaseInstallationServiceClient {
private static final String X_ANDROID_PACKAGE_HEADER_KEY = "X-Android-Package";
private static final String X_ANDROID_CERT_HEADER_KEY = "X-Android-Cert";

private static final String X_ANDROID_IID_MIGRATION_KEY = "x-goog-fis-android-iid-migration-auth";

private static final int NETWORK_TIMEOUT_MILLIS = 10000;

private static final Pattern EXPIRATION_TIMESTAMP_PATTERN = Pattern.compile("[0-9]+s");
Expand All @@ -87,10 +89,10 @@ public class FirebaseInstallationServiceClient {
public FirebaseInstallationServiceClient(
@NonNull Context context,
@Nullable UserAgentPublisher publisher,
@Nullable HeartBeatInfo heartBeatInfo) {
@Nullable HeartBeatInfo heartbeatInfo) {
this.context = context;
this.userAgentPublisher = publisher;
this.heartbeatInfo = heartBeatInfo;
this.heartbeatInfo = heartbeatInfo;
}

/**
Expand All @@ -100,6 +102,8 @@ public FirebaseInstallationServiceClient(
* @param fid Firebase Installation Identifier
* @param projectID Project Id
* @param appId the identifier of a Firebase application
* @param iidToken the identifier token of a Firebase application with instance id. It is set to
* null for a FID.
* @return {@link InstallationResponse} generated from the response body
* <ul>
* <li>400: return response with status BAD_CONFIG
Expand All @@ -111,7 +115,11 @@ public FirebaseInstallationServiceClient(
*/
@NonNull
public InstallationResponse createFirebaseInstallation(
@NonNull String apiKey, @NonNull String fid, @NonNull String projectID, @NonNull String appId)
@NonNull String apiKey,
@NonNull String fid,
@NonNull String projectID,
@NonNull String appId,
@Nullable String iidToken)
throws IOException {
String resourceName = String.format(CREATE_REQUEST_RESOURCE_NAME_FORMAT, projectID);
int retryCount = 0;
Expand All @@ -128,6 +136,11 @@ public InstallationResponse createFirebaseInstallation(
httpsURLConnection.setRequestMethod("POST");
httpsURLConnection.setDoOutput(true);

// Note: Set the iid token header for authenticating the Instance-ID migrating to FIS.
if (iidToken != null) {
httpsURLConnection.addRequestProperty(X_ANDROID_IID_MIGRATION_KEY, iidToken);
}

GZIPOutputStream gzipOutputStream =
new GZIPOutputStream(httpsURLConnection.getOutputStream());
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Mockito.doAnswer;
Expand Down Expand Up @@ -178,7 +179,8 @@ public void cleanUp() {
*/
@Test
public void testGetId_noNetwork_noIid() throws Exception {
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenThrow(new IOException());
when(mockBackend.generateAuthToken(anyString(), anyString(), anyString(), anyString()))
.thenThrow(new IOException());
Expand Down Expand Up @@ -207,7 +209,8 @@ public void testGetId_noNetwork_noIid() throws Exception {

@Test
public void testGetId_noNetwork_iidPresent() throws Exception {
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenThrow(new IOException());
when(mockBackend.generateAuthToken(anyString(), anyString(), anyString(), anyString()))
.thenThrow(new IOException());
Expand Down Expand Up @@ -236,7 +239,8 @@ public void testGetId_noNetwork_iidPresent() throws Exception {

@Test
public void testGetId_noNetwork_fidAlreadyGenerated() throws Exception {
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenThrow(new IOException());
when(mockBackend.generateAuthToken(anyString(), anyString(), anyString(), anyString()))
.thenThrow(new IOException());
Expand Down Expand Up @@ -303,7 +307,7 @@ public void testGetId_ValidIdAndToken_NoBackendCalls() throws Exception {
@Test
public void testGetId_UnRegisteredId_IssueCreateIdCall() throws Exception {
when(mockBackend.createFirebaseInstallation(
anyString(), matches(TEST_FID_1), anyString(), anyString()))
anyString(), matches(TEST_FID_1), anyString(), anyString(), any()))
.thenReturn(TEST_INSTALLATION_RESPONSE);
persistedInstallation.insertOrUpdatePersistedInstallationEntry(
PersistedInstallationEntry.INSTANCE.withUnregisteredFid(TEST_FID_1));
Expand All @@ -322,7 +326,8 @@ public void testGetId_UnRegisteredId_IssueCreateIdCall() throws Exception {
// check that the mockClient didn't get invoked at all, since the fid is already registered
// and the authtoken is present and not expired
verify(mockBackend)
.createFirebaseInstallation(anyString(), matches(TEST_FID_1), anyString(), anyString());
.createFirebaseInstallation(
anyString(), matches(TEST_FID_1), anyString(), anyString(), any());
verify(mockBackend, never())
.generateAuthToken(anyString(), anyString(), anyString(), anyString());

Expand All @@ -335,7 +340,8 @@ public void testGetId_UnRegisteredId_IssueCreateIdCall() throws Exception {
@Test
public void testGetId_migrateIid_successful() throws Exception {
when(mockIidStore.readIid()).thenReturn(TEST_INSTANCE_ID_1);
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenReturn(TEST_INSTALLATION_RESPONSE_WITH_IID);

// Do the actual getId() call under test.
Expand All @@ -361,7 +367,8 @@ public void testGetId_migrateIid_successful() throws Exception {
@Test
public void testGetId_multipleCalls_sameFIDReturned() throws Exception {
when(mockIidStore.readIid()).thenReturn(null);
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenReturn(TEST_INSTALLATION_RESPONSE);

// Call getId multiple times
Expand All @@ -384,7 +391,7 @@ public void testGetId_multipleCalls_sameFIDReturned() throws Exception {
.that(task2.getResult())
.isEqualTo(TEST_FID_1);
verify(mockBackend, times(1))
.createFirebaseInstallation(TEST_API_KEY, TEST_FID_1, TEST_PROJECT_ID, TEST_APP_ID_1);
.createFirebaseInstallation(TEST_API_KEY, TEST_FID_1, TEST_PROJECT_ID, TEST_APP_ID_1, null);
PersistedInstallationEntry entry = persistedInstallation.readPersistedInstallationEntryValue();
assertThat(entry.getFirebaseInstallationId(), equalTo(TEST_FID_1));
assertTrue("the entry isn't doesn't have a registered fid: " + entry, entry.isRegistered());
Expand All @@ -399,7 +406,8 @@ public void testGetId_unregistered_replacesFidWithResponse() throws Exception {
// Update local storage with installation entry that has invalid fid.
persistedInstallation.insertOrUpdatePersistedInstallationEntry(
PersistedInstallationEntry.INSTANCE.withUnregisteredFid("tobereplaced"));
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenReturn(TEST_INSTALLATION_RESPONSE);

// The first call will return the existing FID, "tobereplaced"
Expand Down Expand Up @@ -435,7 +443,8 @@ public void testGetId_ServerError_UnregisteredFID() throws Exception {
PersistedInstallationEntry.INSTANCE.withUnregisteredFid(TEST_FID_1));

// have the server return a server error for the registration
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenReturn(
InstallationResponse.builder().setResponseCode(ResponseCode.BAD_CONFIG).build());

Expand Down Expand Up @@ -469,7 +478,8 @@ public void testGetId_fidRegistrationUncheckedException_statusUpdated() throws E
PersistedInstallationEntry.INSTANCE.withUnregisteredFid(TEST_FID_1));

// Mocking unchecked exception on FIS createFirebaseInstallation
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenThrow(new IOException());

TestOnCompleteListener<String> onCompleteListener = new TestOnCompleteListener<>();
Expand Down Expand Up @@ -569,14 +579,15 @@ public void testGetId_expiredAuthToken_refreshesAuthToken() throws Exception {
.isEqualTo(TEST_AUTH_TOKEN_2);

verify(mockBackend, never())
.createFirebaseInstallation(TEST_API_KEY, TEST_FID_1, TEST_PROJECT_ID, TEST_APP_ID_1);
.createFirebaseInstallation(TEST_API_KEY, TEST_FID_1, TEST_PROJECT_ID, TEST_APP_ID_1, null);
verify(mockBackend, times(1))
.generateAuthToken(TEST_API_KEY, TEST_FID_1, TEST_PROJECT_ID, TEST_REFRESH_TOKEN);
}

@Test
public void testGetAuthToken_fidDoesNotExist_successful() throws Exception {
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenReturn(TEST_INSTALLATION_RESPONSE);

TestOnCompleteListener<InstallationTokenResult> onCompleteListener =
Expand Down Expand Up @@ -650,7 +661,8 @@ public void testGetToken_unregisteredFid_fetchedNewTokenFromFIS() throws Excepti
// calls getId to ensure FID registration and returns a valid auth token.
persistedInstallation.insertOrUpdatePersistedInstallationEntry(
PersistedInstallationEntry.INSTANCE.withUnregisteredFid(TEST_FID_1));
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenReturn(TEST_INSTALLATION_RESPONSE);

TestOnCompleteListener<InstallationTokenResult> onCompleteListener =
Expand Down Expand Up @@ -859,7 +871,8 @@ public void testDelete_registeredFID_successful() throws Exception {
utils.currentTimeInSecs(),
TEST_AUTH_TOKEN,
TEST_TOKEN_EXPIRATION_TIMESTAMP));
when(mockBackend.createFirebaseInstallation(anyString(), anyString(), anyString(), anyString()))
when(mockBackend.createFirebaseInstallation(
anyString(), anyString(), anyString(), anyString(), any()))
.thenReturn(TEST_INSTALLATION_RESPONSE);

TestOnCompleteListener<Void> onCompleteListener = new TestOnCompleteListener<>();
Expand Down