Skip to content
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

Add Firebase auth emulator #510

Merged
merged 13 commits into from
Feb 11, 2021
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
9 changes: 8 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</execution>
</executions>
</plugin>

Expand Down Expand Up @@ -490,5 +490,12 @@
<version>2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<!-- Used for change env system -->
<groupId>com.github.stefanbirkner</groupId>
<artifactId>system-rules</artifactId>
<version>1.19.0</version>
7agustibm marked this conversation as resolved.
Show resolved Hide resolved
<scope>test</scope>
</dependency>
</dependencies>
</project>
18 changes: 16 additions & 2 deletions src/main/java/com/google/firebase/auth/FirebaseUserManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ final class FirebaseUserManager {

private static final String ID_TOOLKIT_URL =
"https://identitytoolkit.googleapis.com/%s/projects/%s";
private static final String ID_TOOLKIT_URL_EMULATOR =
"http://%s/identitytoolkit.googleapis.com/%s/projects/%s";

private final String userMgtBaseUrl;
private final String idpConfigMgtBaseUrl;
Expand All @@ -85,8 +87,8 @@ private FirebaseUserManager(Builder builder) {
+ "set the project ID explicitly via FirebaseOptions. Alternatively you can also "
+ "set the project ID via the GOOGLE_CLOUD_PROJECT environment variable.");
this.jsonFactory = checkNotNull(builder.jsonFactory, "JsonFactory must not be null");
final String idToolkitUrlV1 = String.format(ID_TOOLKIT_URL, "v1", projectId);
final String idToolkitUrlV2 = String.format(ID_TOOLKIT_URL, "v2", projectId);
final String idToolkitUrlV1 = getIdToolkitUrl(projectId, "v1");
final String idToolkitUrlV2 = getIdToolkitUrl(projectId, "v2");
final String tenantId = builder.tenantId;
if (tenantId == null) {
this.userMgtBaseUrl = idToolkitUrlV1;
Expand All @@ -100,6 +102,18 @@ private FirebaseUserManager(Builder builder) {
this.httpClient = new AuthHttpClient(jsonFactory, builder.requestFactory);
}

private String getIdToolkitUrl(String projectId, String version) {
String maybeEmulator = getEmulatorHost();
if (maybeEmulator != null) {
return String.format(ID_TOOLKIT_URL_EMULATOR, maybeEmulator, version, projectId);
}
return String.format(ID_TOOLKIT_URL, version, projectId);
}

private String getEmulatorHost() {
return System.getenv("FIREBASE_AUTH_EMULATOR_HOST");
}

@VisibleForTesting
void setInterceptor(HttpResponseInterceptor interceptor) {
httpClient.setInterceptor(interceptor);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ final class FirebaseTenantClient {
private static final String ID_TOOLKIT_URL =
"https://identitytoolkit.googleapis.com/%s/projects/%s";

private static final String ID_TOOLKIT_URL_EMULATOR =
"http://%s/identitytoolkit.googleapis.com/%s/projects/%s";

private final String tenantMgtBaseUrl;
private final AuthHttpClient httpClient;

Expand All @@ -58,10 +61,22 @@ final class FirebaseTenantClient {
"Project ID is required to access the auth service. Use a service account credential or "
+ "set the project ID explicitly via FirebaseOptions. Alternatively you can also "
+ "set the project ID via the GOOGLE_CLOUD_PROJECT environment variable.");
this.tenantMgtBaseUrl = String.format(ID_TOOLKIT_URL, "v2", projectId);
this.tenantMgtBaseUrl = getTenantMgtBaseUrl(projectId);
this.httpClient = new AuthHttpClient(jsonFactory, requestFactory);
}

private String getTenantMgtBaseUrl(String projectId) {
String maybeEmulator = getEmulatorHost();
if (maybeEmulator != null) {
return String.format(ID_TOOLKIT_URL_EMULATOR, maybeEmulator, "v2", projectId);
}
return String.format(ID_TOOLKIT_URL, "v2", projectId);
}

private String getEmulatorHost() {
return System.getenv("FIREBASE_AUTH_EMULATOR_HOST");
}

void setInterceptor(HttpResponseInterceptor interceptor) {
httpClient.setInterceptor(interceptor);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.EnvironmentVariables;

public class FirebaseUserManagerTest {

Expand Down Expand Up @@ -90,12 +92,20 @@ public class FirebaseUserManagerTest {

private static final String TENANTS_BASE_URL = PROJECT_BASE_URL + "/tenants";

private static final String AUTH_EMULATOR = "localhost:8000";
private static final String PROJECT_BASE_URL_EMULATOR =
"http://" + AUTH_EMULATOR + "/identitytoolkit.googleapis.com/v2/projects/test-project-id";

private static final String SAML_RESPONSE = TestUtils.loadResource("saml.json");

private static final String OIDC_RESPONSE = TestUtils.loadResource("oidc.json");

@Rule
public final EnvironmentVariables environmentVariables = new EnvironmentVariables();

@After
public void tearDown() {
environmentVariables.clear("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR);
TestOnlyImplFirebaseTrampolines.clearInstancesForTest();
}

Expand Down Expand Up @@ -1517,7 +1527,7 @@ public void testCreateOidcProviderAsync() throws Exception {
.setClientId("CLIENT_ID")
.setIssuer("https://oidc.com/issuer");

OidcProviderConfig config =
OidcProviderConfig config =
FirebaseAuth.getInstance().createOidcProviderConfigAsync(createRequest).get();

checkOidcProviderConfig(config, "oidc.provider-id");
Expand Down Expand Up @@ -2678,6 +2688,32 @@ public void testTenantAwareDeleteSamlProviderConfig() throws Exception {
checkUrl(interceptor, "DELETE", expectedUrl);
}

@Test
public void testCreateOidcProviderFromEmulatorAuth() throws Exception {
7agustibm marked this conversation as resolved.
Show resolved Hide resolved
environmentVariables.set("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR);
TestResponseInterceptor interceptor = initializeAppForUserManagement(OIDC_RESPONSE);
OidcProviderConfig.CreateRequest createRequest =
new OidcProviderConfig.CreateRequest()
.setProviderId("oidc.provider-id")
.setDisplayName("DISPLAY_NAME")
.setEnabled(true)
.setClientId("CLIENT_ID")
.setIssuer("https://oidc.com/issuer");

OidcProviderConfig config = FirebaseAuth.getInstance().createOidcProviderConfig(createRequest);

checkOidcProviderConfig(config, "oidc.provider-id");
checkRequestHeaders(interceptor);
checkUrl(interceptor, "POST", PROJECT_BASE_URL_EMULATOR + "/oauthIdpConfigs");
GenericJson parsed = parseRequestContent(interceptor);
assertEquals("DISPLAY_NAME", parsed.get("displayName"));
assertTrue((boolean) parsed.get("enabled"));
assertEquals("CLIENT_ID", parsed.get("clientId"));
assertEquals("https://oidc.com/issuer", parsed.get("issuer"));
GenericUrl url = interceptor.getResponse().getRequest().getUrl();
assertEquals("oidc.provider-id", url.getFirst("oauthIdpConfigId"));
}

private static TestResponseInterceptor initializeAppForUserManagementWithStatusCode(
int statusCode, String response) {
FirebaseApp.initializeApp(FirebaseOptions.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.EnvironmentVariables;

public class FirebaseTenantClientTest {

Expand All @@ -68,8 +71,17 @@ public class FirebaseTenantClientTest {

private static final String TENANTS_BASE_URL = PROJECT_BASE_URL + "/tenants";

private static final String AUTH_EMULATOR = "localhost:8000";
private static final String PROJECT_BASE_URL_EMULATOR =
"http://" + AUTH_EMULATOR + "/identitytoolkit.googleapis.com/v2/projects/test-project-id";
private static final String TENANTS_BASE_URL_EMULATOR = PROJECT_BASE_URL_EMULATOR + "/tenants";

@Rule
public final EnvironmentVariables environmentVariables = new EnvironmentVariables();

7agustibm marked this conversation as resolved.
Show resolved Hide resolved
@After
public void tearDown() {
public void tearDown() throws ReflectiveOperationException {
environmentVariables.clear("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR);
TestOnlyImplFirebaseTrampolines.clearInstancesForTest();
}

Expand Down Expand Up @@ -312,6 +324,19 @@ public void testDeleteTenantWithNotFoundError() {
checkUrl(interceptor, "DELETE", TENANTS_BASE_URL + "/UNKNOWN");
}

@Test
public void testGetTenantFromAuthEmulator() throws Exception {
environmentVariables.set("FIREBASE_AUTH_EMULATOR_HOST", AUTH_EMULATOR);
TestResponseInterceptor interceptor = initializeAppForTenantManagement(
TestUtils.loadResource("tenant.json"));

Tenant tenant = FirebaseAuth.getInstance().getTenantManager().getTenant("TENANT_1");

checkTenant(tenant, "TENANT_1");
checkRequestHeaders(interceptor);
checkUrl(interceptor, "GET", TENANTS_BASE_URL_EMULATOR + "/TENANT_1");
}

private static void checkTenant(Tenant tenant, String tenantId) {
assertEquals(tenantId, tenant.getTenantId());
assertEquals("DISPLAY_NAME", tenant.getDisplayName());
Expand Down