Skip to content

Commit 21dbf78

Browse files
authored
Rename OIDC delete operation and refactor integration tests. (#411)
I've renamed the delete operation since we need separate methods for deleting OIDC and SAML provider configs. I've also created a ProviderConfigTestUtils class to house shared logic between TenantAwareFirebaseAuthIT and FirebaseAuthIT, and I've added a TemporaryProviderConfig class to make it easier for provider configs to be cleaned up automatically. I've structured this class in such a way that we can easily tack on logic to cleanup SAML provider configs as well. I've also decided to remove testGetUserWithMultipleTenantIds. I initially wrote this test to understand how tenant-aware auths and tenant-agnostic auths interacted with one another. In its existing state, it appears to be leaking created users, and in order to resolve this with TemporaryUser, we would need to declare multiple TemporaryUser objects as rules. I think it's better to avoid this complexity and remove this test. After all, this integration test is mainly making assertions about the server's behavior and not our behavior.
1 parent bfac46a commit 21dbf78

File tree

6 files changed

+251
-235
lines changed

6 files changed

+251
-235
lines changed

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

+12-12
Original file line numberDiff line numberDiff line change
@@ -970,7 +970,7 @@ public ApiFuture<OidcProviderConfig> createOidcProviderConfigAsync(
970970
private CallableOperation<OidcProviderConfig, FirebaseAuthException>
971971
createOidcProviderConfigOp(final OidcProviderConfig.CreateRequest request) {
972972
checkNotDestroyed();
973-
checkNotNull(request, "create request must not be null");
973+
checkNotNull(request, "Create request must not be null.");
974974
final FirebaseUserManager userManager = getUserManager();
975975
return new CallableOperation<OidcProviderConfig, FirebaseAuthException>() {
976976
@Override
@@ -1010,7 +1010,7 @@ public ApiFuture<OidcProviderConfig> updateOidcProviderConfigAsync(
10101010
private CallableOperation<OidcProviderConfig, FirebaseAuthException> updateOidcProviderConfigOp(
10111011
final OidcProviderConfig.UpdateRequest request) {
10121012
checkNotDestroyed();
1013-
checkNotNull(request, "update request must not be null");
1013+
checkNotNull(request, "Update request must not be null.");
10141014
final FirebaseUserManager userManager = getUserManager();
10151015
return new CallableOperation<OidcProviderConfig, FirebaseAuthException>() {
10161016
@Override
@@ -1051,7 +1051,7 @@ public ApiFuture<OidcProviderConfig> getOidcProviderConfigAsync(@NonNull String
10511051
private CallableOperation<OidcProviderConfig, FirebaseAuthException>
10521052
getOidcProviderConfigOp(final String providerId) {
10531053
checkNotDestroyed();
1054-
checkArgument(!Strings.isNullOrEmpty(providerId), "provider ID must not be null or empty");
1054+
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
10551055
final FirebaseUserManager userManager = getUserManager();
10561056
return new CallableOperation<OidcProviderConfig, FirebaseAuthException>() {
10571057
@Override
@@ -1149,38 +1149,38 @@ protected ListProviderConfigsPage<OidcProviderConfig> execute()
11491149
}
11501150

11511151
/**
1152-
* Deletes the provider config identified by the specified provider ID.
1152+
* Deletes the OIDC Auth provider config identified by the specified provider ID.
11531153
*
11541154
* @param providerId A provider ID string.
11551155
* @throws IllegalArgumentException If the provider ID string is null or empty.
11561156
* @throws FirebaseAuthException If an error occurs while deleting the provider config.
11571157
*/
1158-
public void deleteProviderConfig(@NonNull String providerId) throws FirebaseAuthException {
1159-
deleteProviderConfigOp(providerId).call();
1158+
public void deleteOidcProviderConfig(@NonNull String providerId) throws FirebaseAuthException {
1159+
deleteOidcProviderConfigOp(providerId).call();
11601160
}
11611161

11621162
/**
1163-
* Similar to {@link #deleteProviderConfig} but performs the operation asynchronously.
1163+
* Similar to {@link #deleteOidcProviderConfig} but performs the operation asynchronously.
11641164
*
11651165
* @param providerId A provider ID string.
11661166
* @return An {@code ApiFuture} which will complete successfully when the specified provider
11671167
* config has been deleted. If an error occurs while deleting the provider config, the future
11681168
* throws a {@link FirebaseAuthException}.
11691169
* @throws IllegalArgumentException If the provider ID string is null or empty.
11701170
*/
1171-
public ApiFuture<Void> deleteProviderConfigAsync(String providerId) {
1172-
return deleteProviderConfigOp(providerId).callAsync(firebaseApp);
1171+
public ApiFuture<Void> deleteOidcProviderConfigAsync(String providerId) {
1172+
return deleteOidcProviderConfigOp(providerId).callAsync(firebaseApp);
11731173
}
11741174

1175-
private CallableOperation<Void, FirebaseAuthException> deleteProviderConfigOp(
1175+
private CallableOperation<Void, FirebaseAuthException> deleteOidcProviderConfigOp(
11761176
final String providerId) {
11771177
checkNotDestroyed();
1178-
checkArgument(!Strings.isNullOrEmpty(providerId), "provider ID must not be null or empty");
1178+
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
11791179
final FirebaseUserManager userManager = getUserManager();
11801180
return new CallableOperation<Void, FirebaseAuthException>() {
11811181
@Override
11821182
protected Void execute() throws FirebaseAuthException {
1183-
userManager.deleteProviderConfig(providerId);
1183+
userManager.deleteOidcProviderConfig(providerId);
11841184
return null;
11851185
}
11861186
};

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

+6-6
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ OidcProviderConfig createOidcProviderConfig(
319319
OidcProviderConfig.CreateRequest request) throws FirebaseAuthException {
320320
GenericUrl url = new GenericUrl(idpConfigMgtBaseUrl + "/oauthIdpConfigs");
321321
String providerId = request.getProviderId();
322-
checkArgument(!Strings.isNullOrEmpty(providerId), "provider ID must not be null or empty");
322+
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
323323
url.set("oauthIdpConfigId", providerId);
324324
return sendRequest("POST", url, request.getProperties(), OidcProviderConfig.class);
325325
}
@@ -328,7 +328,7 @@ OidcProviderConfig updateOidcProviderConfig(OidcProviderConfig.UpdateRequest req
328328
throws FirebaseAuthException {
329329
Map<String, Object> properties = request.getProperties();
330330
checkArgument(!properties.isEmpty(),
331-
"provider config update must have at least one property set");
331+
"Provider config update must have at least one property set.");
332332
GenericUrl url =
333333
new GenericUrl(idpConfigMgtBaseUrl + getOidcUrlSuffix(request.getProviderId()));
334334
url.put("updateMask", generateMask(properties));
@@ -346,7 +346,7 @@ ListOidcProviderConfigsResponse listOidcProviderConfigs(int maxResults, String p
346346
ImmutableMap.<String, Object>builder().put("pageSize", maxResults);
347347
if (pageToken != null) {
348348
checkArgument(!pageToken.equals(
349-
ListTenantsPage.END_OF_LIST), "invalid end of list page token");
349+
ListTenantsPage.END_OF_LIST), "Invalid end of list page token.");
350350
builder.put("nextPageToken", pageToken);
351351
}
352352

@@ -360,7 +360,7 @@ ListOidcProviderConfigsResponse listOidcProviderConfigs(int maxResults, String p
360360
return response;
361361
}
362362

363-
void deleteProviderConfig(String providerId) throws FirebaseAuthException {
363+
void deleteOidcProviderConfig(String providerId) throws FirebaseAuthException {
364364
GenericUrl url = new GenericUrl(idpConfigMgtBaseUrl + getOidcUrlSuffix(providerId));
365365
sendRequest("DELETE", url, null, GenericJson.class);
366366
}
@@ -374,12 +374,12 @@ private static String generateMask(Map<String, Object> properties) {
374374
}
375375

376376
private static String getTenantUrlSuffix(String tenantId) {
377-
checkArgument(!Strings.isNullOrEmpty(tenantId), "tenant ID must not be null or empty");
377+
checkArgument(!Strings.isNullOrEmpty(tenantId), "Tenant ID must not be null or empty.");
378378
return "/tenants/" + tenantId;
379379
}
380380

381381
private static String getOidcUrlSuffix(String providerId) {
382-
checkArgument(!Strings.isNullOrEmpty(providerId), "provider ID must not be null or empty");
382+
checkArgument(!Strings.isNullOrEmpty(providerId), "Provider ID must not be null or empty.");
383383
return "/oauthIdpConfigs/" + providerId;
384384
}
385385

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

+83-104
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import com.google.firebase.FirebaseApp;
4747
import com.google.firebase.FirebaseOptions;
4848
import com.google.firebase.ImplFirebaseTrampolines;
49+
import com.google.firebase.auth.ProviderConfigTestUtils.TemporaryProviderConfig;
4950
import com.google.firebase.auth.hash.Scrypt;
5051
import com.google.firebase.internal.Nullable;
5152
import com.google.firebase.testing.IntegrationTestUtils;
@@ -84,8 +85,9 @@ public class FirebaseAuthIT {
8485
private static final FirebaseAuth auth = FirebaseAuth.getInstance(
8586
IntegrationTestUtils.ensureDefaultApp());
8687

87-
@Rule
88-
public final TemporaryUser temporaryUser = new TemporaryUser();
88+
@Rule public final TemporaryUser temporaryUser = new TemporaryUser();
89+
@Rule public final TemporaryProviderConfig temporaryProviderConfig =
90+
new TemporaryProviderConfig(auth);
8991

9092
@Test
9193
public void testGetNonExistingUser() throws Exception {
@@ -563,124 +565,113 @@ public void testGenerateSignInWithEmailLink() throws Exception {
563565
public void testOidcProviderConfigLifecycle() throws Exception {
564566
// Create config provider
565567
String providerId = "oidc.provider-id";
566-
OidcProviderConfig.CreateRequest createRequest =
568+
OidcProviderConfig config = temporaryProviderConfig.createOidcProviderConfig(
567569
new OidcProviderConfig.CreateRequest()
568570
.setProviderId(providerId)
569571
.setDisplayName("DisplayName")
570572
.setEnabled(true)
571573
.setClientId("ClientId")
572-
.setIssuer("https://oidc.com/issuer");
573-
OidcProviderConfig config = auth.createOidcProviderConfigAsync(createRequest).get();
574+
.setIssuer("https://oidc.com/issuer"));
574575
assertEquals(providerId, config.getProviderId());
575576
assertEquals("DisplayName", config.getDisplayName());
576577
assertTrue(config.isEnabled());
577578
assertEquals("ClientId", config.getClientId());
578579
assertEquals("https://oidc.com/issuer", config.getIssuer());
579580

580-
try {
581-
// Get config provider
582-
config = auth.getOidcProviderConfigAsync(providerId).get();
583-
assertEquals(providerId, config.getProviderId());
584-
assertEquals("DisplayName", config.getDisplayName());
585-
assertTrue(config.isEnabled());
586-
assertEquals("ClientId", config.getClientId());
587-
assertEquals("https://oidc.com/issuer", config.getIssuer());
581+
// Get config provider
582+
config = auth.getOidcProviderConfigAsync(providerId).get();
583+
assertEquals(providerId, config.getProviderId());
584+
assertEquals("DisplayName", config.getDisplayName());
585+
assertTrue(config.isEnabled());
586+
assertEquals("ClientId", config.getClientId());
587+
assertEquals("https://oidc.com/issuer", config.getIssuer());
588588

589-
// Update config provider
590-
OidcProviderConfig.UpdateRequest updateRequest =
591-
new OidcProviderConfig.UpdateRequest(providerId)
592-
.setDisplayName("NewDisplayName")
593-
.setEnabled(false)
594-
.setClientId("NewClientId")
595-
.setIssuer("https://oidc.com/new-issuer");
596-
config = auth.updateOidcProviderConfigAsync(updateRequest).get();
597-
assertEquals(providerId, config.getProviderId());
598-
assertEquals("NewDisplayName", config.getDisplayName());
599-
assertFalse(config.isEnabled());
600-
assertEquals("NewClientId", config.getClientId());
601-
assertEquals("https://oidc.com/new-issuer", config.getIssuer());
602-
} finally {
603-
// Delete config provider
604-
auth.deleteProviderConfigAsync(providerId).get();
605-
}
589+
// Update config provider
590+
OidcProviderConfig.UpdateRequest updateRequest =
591+
new OidcProviderConfig.UpdateRequest(providerId)
592+
.setDisplayName("NewDisplayName")
593+
.setEnabled(false)
594+
.setClientId("NewClientId")
595+
.setIssuer("https://oidc.com/new-issuer");
596+
config = auth.updateOidcProviderConfigAsync(updateRequest).get();
597+
assertEquals(providerId, config.getProviderId());
598+
assertEquals("NewDisplayName", config.getDisplayName());
599+
assertFalse(config.isEnabled());
600+
assertEquals("NewClientId", config.getClientId());
601+
assertEquals("https://oidc.com/new-issuer", config.getIssuer());
606602

607-
assertOidcProviderConfigDoesNotExist(auth, providerId);
603+
// Delete config provider
604+
auth.deleteOidcProviderConfigAsync(providerId).get();
605+
ProviderConfigTestUtils.assertOidcProviderConfigDoesNotExist(auth, providerId);
608606
}
609607

610608
@Test
611609
public void testListOidcProviderConfigs() throws Exception {
612610
final List<String> providerIds = new ArrayList<>();
613611

614-
try {
615-
// Create provider configs
616-
for (int i = 0; i < 3; i++) {
617-
String providerId = "oidc.provider-id" + i;
618-
providerIds.add(providerId);
619-
OidcProviderConfig.CreateRequest createRequest = new OidcProviderConfig.CreateRequest()
612+
// Create provider configs
613+
for (int i = 0; i < 3; i++) {
614+
String providerId = "oidc.provider-id" + i;
615+
providerIds.add(providerId);
616+
OidcProviderConfig config = temporaryProviderConfig.createOidcProviderConfig(
617+
new OidcProviderConfig.CreateRequest()
620618
.setProviderId(providerId)
621619
.setClientId("CLIENT_ID")
622-
.setIssuer("https://oidc.com/issuer");
623-
auth.createOidcProviderConfig(createRequest);
624-
}
625-
626-
// Test list by batches
627-
final AtomicInteger collected = new AtomicInteger(0);
628-
ListProviderConfigsPage<OidcProviderConfig> page =
629-
auth.listOidcProviderConfigsAsync(null).get();
630-
while (page != null) {
631-
for (OidcProviderConfig providerConfig : page.getValues()) {
632-
if (checkProviderConfig(providerIds, providerConfig)) {
633-
collected.incrementAndGet();
634-
}
635-
}
636-
page = page.getNextPage();
637-
}
638-
assertEquals(providerIds.size(), collected.get());
620+
.setIssuer("https://oidc.com/issuer"));
621+
}
639622

640-
// Test iterate all
641-
collected.set(0);
642-
page = auth.listOidcProviderConfigsAsync(null).get();
643-
for (OidcProviderConfig providerConfig : page.iterateAll()) {
623+
// Test list by batches
624+
final AtomicInteger collected = new AtomicInteger(0);
625+
ListProviderConfigsPage<OidcProviderConfig> page =
626+
auth.listOidcProviderConfigsAsync(null).get();
627+
while (page != null) {
628+
for (OidcProviderConfig providerConfig : page.getValues()) {
644629
if (checkProviderConfig(providerIds, providerConfig)) {
645630
collected.incrementAndGet();
646631
}
647632
}
648-
assertEquals(providerIds.size(), collected.get());
649-
650-
// Test iterate async
651-
collected.set(0);
652-
final Semaphore semaphore = new Semaphore(0);
653-
final AtomicReference<Throwable> error = new AtomicReference<>();
654-
ApiFuture<ListProviderConfigsPage<OidcProviderConfig>> pageFuture =
655-
auth.listOidcProviderConfigsAsync(null);
656-
ApiFutures.addCallback(
657-
pageFuture,
658-
new ApiFutureCallback<ListProviderConfigsPage<OidcProviderConfig>>() {
659-
@Override
660-
public void onFailure(Throwable t) {
661-
error.set(t);
662-
semaphore.release();
663-
}
633+
page = page.getNextPage();
634+
}
635+
assertEquals(providerIds.size(), collected.get());
664636

665-
@Override
666-
public void onSuccess(ListProviderConfigsPage<OidcProviderConfig> result) {
667-
for (OidcProviderConfig providerConfig : result.iterateAll()) {
668-
if (checkProviderConfig(providerIds, providerConfig)) {
669-
collected.incrementAndGet();
670-
}
671-
}
672-
semaphore.release();
673-
}
674-
}, MoreExecutors.directExecutor());
675-
semaphore.acquire();
676-
assertEquals(providerIds.size(), collected.get());
677-
assertNull(error.get());
678-
} finally {
679-
// Delete provider configs
680-
for (String providerId : providerIds) {
681-
auth.deleteProviderConfigAsync(providerId).get();
637+
// Test iterate all
638+
collected.set(0);
639+
page = auth.listOidcProviderConfigsAsync(null).get();
640+
for (OidcProviderConfig providerConfig : page.iterateAll()) {
641+
if (checkProviderConfig(providerIds, providerConfig)) {
642+
collected.incrementAndGet();
682643
}
683644
}
645+
assertEquals(providerIds.size(), collected.get());
646+
647+
// Test iterate async
648+
collected.set(0);
649+
final Semaphore semaphore = new Semaphore(0);
650+
final AtomicReference<Throwable> error = new AtomicReference<>();
651+
ApiFuture<ListProviderConfigsPage<OidcProviderConfig>> pageFuture =
652+
auth.listOidcProviderConfigsAsync(null);
653+
ApiFutures.addCallback(
654+
pageFuture,
655+
new ApiFutureCallback<ListProviderConfigsPage<OidcProviderConfig>>() {
656+
@Override
657+
public void onFailure(Throwable t) {
658+
error.set(t);
659+
semaphore.release();
660+
}
661+
662+
@Override
663+
public void onSuccess(ListProviderConfigsPage<OidcProviderConfig> result) {
664+
for (OidcProviderConfig providerConfig : result.iterateAll()) {
665+
if (checkProviderConfig(providerIds, providerConfig)) {
666+
collected.incrementAndGet();
667+
}
668+
}
669+
semaphore.release();
670+
}
671+
}, MoreExecutors.directExecutor());
672+
semaphore.acquire();
673+
assertEquals(providerIds.size(), collected.get());
674+
assertNull(error.get());
684675
}
685676

686677
private Map<String, String> parseLinkParameters(String link) throws Exception {
@@ -823,23 +814,11 @@ private boolean checkProviderConfig(List<String> providerIds, OidcProviderConfig
823814
}
824815

825816

826-
private static void assertOidcProviderConfigDoesNotExist(
827-
AbstractFirebaseAuth firebaseAuth, String providerId) throws Exception {
828-
try {
829-
firebaseAuth.getOidcProviderConfigAsync(providerId).get();
830-
fail("No error thrown for getting a deleted provider config");
831-
} catch (ExecutionException e) {
832-
assertTrue(e.getCause() instanceof FirebaseAuthException);
833-
assertEquals(FirebaseUserManager.CONFIGURATION_NOT_FOUND_ERROR,
834-
((FirebaseAuthException) e.getCause()).getErrorCode());
835-
}
836-
}
837-
838817
private static void assertUserDoesNotExist(AbstractFirebaseAuth firebaseAuth, String uid)
839818
throws Exception {
840819
try {
841820
firebaseAuth.getUserAsync(uid).get();
842-
fail("No error thrown for getting a user which was expected to be absent");
821+
fail("No error thrown for getting a user which was expected to be absent.");
843822
} catch (ExecutionException e) {
844823
assertTrue(e.getCause() instanceof FirebaseAuthException);
845824
assertEquals(FirebaseUserManager.USER_NOT_FOUND_ERROR,

0 commit comments

Comments
 (0)