Skip to content

Commit f36fcf8

Browse files
authored
Setting X-Client-Version Header in HTTP Requests Made by User Management API (firebase#43)
* Setting X-Client-Version header when calling identity toolkit REST API * Newline at EoF
1 parent d854f62 commit f36fcf8

5 files changed

Lines changed: 129 additions & 24 deletions

File tree

src/main/java/com/google/firebase/auth/FirebaseUserManager.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,21 @@
2323
import com.google.api.client.http.HttpRequest;
2424
import com.google.api.client.http.HttpRequestFactory;
2525
import com.google.api.client.http.HttpResponse;
26+
import com.google.api.client.http.HttpResponseInterceptor;
2627
import com.google.api.client.http.HttpTransport;
2728
import com.google.api.client.http.json.JsonHttpContent;
2829
import com.google.api.client.json.GenericJson;
2930
import com.google.api.client.json.JsonFactory;
3031
import com.google.api.client.json.JsonObjectParser;
32+
import com.google.common.annotations.VisibleForTesting;
3133
import com.google.common.base.Strings;
3234
import com.google.common.collect.ImmutableList;
3335
import com.google.common.collect.ImmutableMap;
3436
import com.google.firebase.auth.UserRecord.CreateRequest;
3537
import com.google.firebase.auth.UserRecord.UpdateRequest;
3638
import com.google.firebase.auth.internal.GetAccountInfoResponse;
3739

40+
import com.google.firebase.internal.SdkUtils;
3841
import java.io.IOException;
3942
import java.util.Map;
4043

@@ -55,9 +58,13 @@ class FirebaseUserManager {
5558

5659
private static final String ID_TOOLKIT_URL =
5760
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/";
61+
private static final String CLIENT_VERSION_HEADER = "X-Client-Version";
5862

5963
private final JsonFactory jsonFactory;
6064
private final HttpRequestFactory requestFactory;
65+
private final String clientVersion = "Java/Admin/" + SdkUtils.getVersion();
66+
67+
private HttpResponseInterceptor interceptor;
6168

6269
/**
6370
* Creates a new FirebaseUserManager instance.
@@ -70,6 +77,11 @@ class FirebaseUserManager {
7077
this.requestFactory = transport.createRequestFactory();
7178
}
7279

80+
@VisibleForTesting
81+
void setInterceptor(HttpResponseInterceptor interceptor) {
82+
this.interceptor = interceptor;
83+
}
84+
7385
UserRecord getUserById(String uid, String token) throws FirebaseAuthException {
7486
final Map<String, Object> payload = ImmutableMap.<String, Object>of(
7587
"localId", ImmutableList.of(uid));
@@ -165,7 +177,9 @@ private <T> T post(String path, String token, Object content, Class<T> clazz) th
165177
HttpRequest request = requestFactory.buildPostRequest(url,
166178
new JsonHttpContent(jsonFactory, content));
167179
request.setParser(new JsonObjectParser(jsonFactory));
168-
request.getHeaders().setAuthorization("Bearer " + token);
180+
request.getHeaders().setAuthorization("Bearer " + token)
181+
.set(CLIENT_VERSION_HEADER, clientVersion);
182+
request.setResponseInterceptor(interceptor);
169183
HttpResponse response = request.execute();
170184
try {
171185
return response.parseAs(clazz);

src/main/java/com/google/firebase/database/FirebaseDatabase.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,10 @@
3232
import com.google.firebase.database.utilities.Validation;
3333
import com.google.firebase.internal.FirebaseService;
3434

35-
import java.io.IOException;
36-
import java.io.InputStream;
35+
import com.google.firebase.internal.SdkUtils;
3736
import java.util.Collections;
3837
import java.util.HashMap;
3938
import java.util.Map;
40-
import java.util.Properties;
4139
import java.util.concurrent.atomic.AtomicBoolean;
4240

4341
/**
@@ -47,9 +45,6 @@
4745
*/
4846
public class FirebaseDatabase {
4947

50-
private static final String ADMIN_SDK_PROPERTIES = "admin_sdk.properties";
51-
private static final String SDK_VERSION = loadSdkVersion();
52-
5348
private final FirebaseApp app;
5449
private final RepoInfo repoInfo;
5550
private final DatabaseConfig config;
@@ -165,7 +160,7 @@ static FirebaseDatabase createForTests(
165160
* @return The version for this build of the Firebase Database client
166161
*/
167162
public static String getSdkVersion() {
168-
return SDK_VERSION;
163+
return SdkUtils.getVersion();
169164
}
170165

171166
/**
@@ -370,17 +365,6 @@ void destroy() {
370365
}
371366
}
372367

373-
private static String loadSdkVersion() {
374-
try (InputStream in = FirebaseDatabase.class.getClassLoader()
375-
.getResourceAsStream(ADMIN_SDK_PROPERTIES)) {
376-
Properties properties = new Properties();
377-
properties.load(checkNotNull(in, "Failed to load: " + ADMIN_SDK_PROPERTIES));
378-
return properties.getProperty("sdk.version");
379-
} catch (IOException e) {
380-
throw new RuntimeException(e);
381-
}
382-
}
383-
384368
private static final String SERVICE_ID = FirebaseDatabase.class.getName();
385369

386370
private static class DatabaseInstances {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2017 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.internal;
18+
19+
import static com.google.common.base.Preconditions.checkNotNull;
20+
21+
import java.io.IOException;
22+
import java.io.InputStream;
23+
import java.util.Properties;
24+
25+
/**
26+
* A collection of internal utilities that can be used anywhere in the Admin SDK.
27+
*/
28+
public class SdkUtils {
29+
30+
private static final String ADMIN_SDK_PROPERTIES = "admin_sdk.properties";
31+
private static final String SDK_VERSION = loadSdkVersion();
32+
33+
/**
34+
* Returns the version of this Admin SDK distribution.
35+
*
36+
* @return A semver version string.
37+
*/
38+
public static String getVersion() {
39+
return SDK_VERSION;
40+
}
41+
42+
private static String loadSdkVersion() {
43+
try (InputStream in = SdkUtils.class.getClassLoader()
44+
.getResourceAsStream(ADMIN_SDK_PROPERTIES)) {
45+
Properties properties = new Properties();
46+
properties.load(checkNotNull(in, "Failed to load: " + ADMIN_SDK_PROPERTIES));
47+
return properties.getProperty("sdk.version");
48+
} catch (IOException e) {
49+
throw new RuntimeException(e);
50+
}
51+
}
52+
53+
}

src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@
2121
import static org.junit.Assert.assertTrue;
2222
import static org.junit.Assert.fail;
2323

24+
import com.google.api.client.http.HttpHeaders;
25+
import com.google.api.client.http.HttpResponse;
26+
import com.google.api.client.http.HttpResponseInterceptor;
2427
import com.google.api.client.json.gson.GsonFactory;
2528
import com.google.api.client.testing.http.MockHttpTransport;
2629
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
2730
import com.google.common.collect.ImmutableList;
2831
import com.google.firebase.auth.UserRecord.CreateRequest;
2932
import com.google.firebase.auth.UserRecord.UpdateRequest;
33+
import com.google.firebase.internal.SdkUtils;
3034
import com.google.firebase.testing.TestUtils;
3135

3236
import java.io.IOException;
@@ -35,6 +39,7 @@
3539

3640
public class FirebaseUserManagerTest {
3741

42+
private static final String TEST_TOKEN = "token";
3843
private static final GsonFactory gson = new GsonFactory();
3944

4045
@Test
@@ -45,8 +50,11 @@ public void testGetUser() throws Exception {
4550
.setLowLevelHttpResponse(response)
4651
.build();
4752
FirebaseUserManager userManager = new FirebaseUserManager(gson, transport);
48-
UserRecord userRecord = userManager.getUserById("testuser", "token");
53+
TestResponseInterceptor interceptor = new TestResponseInterceptor();
54+
userManager.setInterceptor(interceptor);
55+
UserRecord userRecord = userManager.getUserById("testuser", TEST_TOKEN);
4956
checkUserRecord(userRecord);
57+
checkRequestHeaders(interceptor);
5058
}
5159

5260
@Test
@@ -58,7 +66,7 @@ public void testGetUserWithNotFoundError() throws Exception {
5866
.build();
5967
FirebaseUserManager userManager = new FirebaseUserManager(gson, transport);
6068
try {
61-
userManager.getUserById("testuser", "token");
69+
userManager.getUserById("testuser", TEST_TOKEN);
6270
fail("No error thrown for invalid response");
6371
} catch (FirebaseAuthException e) {
6472
assertEquals(FirebaseUserManager.USER_NOT_FOUND_ERROR, e.getErrorCode());
@@ -73,8 +81,11 @@ public void testGetUserByEmail() throws Exception {
7381
.setLowLevelHttpResponse(response)
7482
.build();
7583
FirebaseUserManager userManager = new FirebaseUserManager(gson, transport);
76-
UserRecord userRecord = userManager.getUserByEmail("[email protected]", "token");
84+
TestResponseInterceptor interceptor = new TestResponseInterceptor();
85+
userManager.setInterceptor(interceptor);
86+
UserRecord userRecord = userManager.getUserByEmail("[email protected]", TEST_TOKEN);
7787
checkUserRecord(userRecord);
88+
checkRequestHeaders(interceptor);
7889
}
7990

8091
@Test
@@ -85,8 +96,11 @@ public void testCreateUser() throws Exception {
8596
.setLowLevelHttpResponse(response)
8697
.build();
8798
FirebaseUserManager userManager = new FirebaseUserManager(gson, transport);
88-
String uid = userManager.createUser(new CreateRequest(), "token");
99+
TestResponseInterceptor interceptor = new TestResponseInterceptor();
100+
userManager.setInterceptor(interceptor);
101+
String uid = userManager.createUser(new CreateRequest(), TEST_TOKEN);
89102
assertEquals("testuser", uid);
103+
checkRequestHeaders(interceptor);
90104
}
91105

92106
@Test
@@ -97,8 +111,26 @@ public void testUpdateUser() throws Exception {
97111
.setLowLevelHttpResponse(response)
98112
.build();
99113
FirebaseUserManager userManager = new FirebaseUserManager(gson, transport);
114+
TestResponseInterceptor interceptor = new TestResponseInterceptor();
115+
userManager.setInterceptor(interceptor);
116+
// should not throw
117+
userManager.updateUser(new UpdateRequest("testuser"), TEST_TOKEN);
118+
checkRequestHeaders(interceptor);
119+
}
120+
121+
@Test
122+
public void testDeleteUser() throws Exception {
123+
MockLowLevelHttpResponse response = new MockLowLevelHttpResponse();
124+
response.setContent(TestUtils.loadResource("deleteUser.json"));
125+
MockHttpTransport transport = new MockHttpTransport.Builder()
126+
.setLowLevelHttpResponse(response)
127+
.build();
128+
FirebaseUserManager userManager = new FirebaseUserManager(gson, transport);
129+
TestResponseInterceptor interceptor = new TestResponseInterceptor();
130+
userManager.setInterceptor(interceptor);
100131
// should not throw
101-
userManager.updateUser(new UpdateRequest("testuser"), "token");
132+
userManager.deleteUser("testuser", TEST_TOKEN);
133+
checkRequestHeaders(interceptor);
102134
}
103135

104136
@Test
@@ -381,4 +413,23 @@ private void checkUserRecord(UserRecord userRecord) {
381413
assertEquals("password", provider.getProviderId());
382414
}
383415

416+
private void checkRequestHeaders(TestResponseInterceptor interceptor) {
417+
HttpHeaders headers = interceptor.response.getRequest().getHeaders();
418+
String auth = "Bearer " + TEST_TOKEN;
419+
assertEquals(auth, headers.getFirstHeaderStringValue("Authorization"));
420+
421+
String clientVersion = "Java/Admin/" + SdkUtils.getVersion();
422+
assertEquals(clientVersion, headers.getFirstHeaderStringValue("X-Client-Version"));
423+
}
424+
425+
private static class TestResponseInterceptor implements HttpResponseInterceptor {
426+
427+
private HttpResponse response;
428+
429+
@Override
430+
public void interceptResponse(HttpResponse response) throws IOException {
431+
this.response = response;
432+
}
433+
}
434+
384435
}

src/test/resources/deleteUser.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"kind" : "identitytoolkit#DeleteUserResponse"
3+
}

0 commit comments

Comments
 (0)