diff --git a/src/main/java/com/google/firebase/auth/AbstractFirebaseAuth.java b/src/main/java/com/google/firebase/auth/AbstractFirebaseAuth.java index b9b563e69..cde7a90a1 100644 --- a/src/main/java/com/google/firebase/auth/AbstractFirebaseAuth.java +++ b/src/main/java/com/google/firebase/auth/AbstractFirebaseAuth.java @@ -31,8 +31,7 @@ import com.google.firebase.auth.FirebaseUserManager.UserImportRequest; import com.google.firebase.auth.ListUsersPage.DefaultUserSource; import com.google.firebase.auth.ListUsersPage.PageFactory; -import com.google.firebase.auth.UserRecord.CreateRequest; -import com.google.firebase.auth.UserRecord.UpdateRequest; +import com.google.firebase.auth.UserRecord; import com.google.firebase.auth.internal.FirebaseTokenFactory; import com.google.firebase.internal.CallableOperation; import com.google.firebase.internal.NonNull; @@ -320,7 +319,8 @@ private CallableOperation revokeRefreshTokensOp(fin @Override protected Void execute() throws FirebaseAuthException { int currentTimeSeconds = (int) (System.currentTimeMillis() / 1000); - UpdateRequest request = new UpdateRequest(uid).setValidSince(currentTimeSeconds); + UserRecord.UpdateRequest request = + new UserRecord.UpdateRequest(uid).setValidSince(currentTimeSeconds); userManager.updateUser(request, jsonFactory); return null; } @@ -512,32 +512,33 @@ protected ListUsersPage execute() throws FirebaseAuthException { /** * Creates a new user account with the attributes contained in the specified {@link - * CreateRequest}. + * UserRecord.CreateRequest}. * - * @param request A non-null {@link CreateRequest} instance. + * @param request A non-null {@link UserRecord.CreateRequest} instance. * @return A {@link UserRecord} instance corresponding to the newly created account. * @throws NullPointerException if the provided request is null. * @throws FirebaseAuthException if an error occurs while creating the user account. */ - public UserRecord createUser(@NonNull CreateRequest request) throws FirebaseAuthException { + public UserRecord createUser(@NonNull UserRecord.CreateRequest request) + throws FirebaseAuthException { return createUserOp(request).call(); } /** - * Similar to {@link #createUser(CreateRequest)} but performs the operation asynchronously. + * Similar to {@link #createUser} but performs the operation asynchronously. * - * @param request A non-null {@link CreateRequest} instance. + * @param request A non-null {@link UserRecord.CreateRequest} instance. * @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord} * instance corresponding to the newly created account. If an error occurs while creating the * user account, the future throws a {@link FirebaseAuthException}. * @throws NullPointerException if the provided request is null. */ - public ApiFuture createUserAsync(@NonNull CreateRequest request) { + public ApiFuture createUserAsync(@NonNull UserRecord.CreateRequest request) { return createUserOp(request).callAsync(firebaseApp); } private CallableOperation createUserOp( - final CreateRequest request) { + final UserRecord.CreateRequest request) { checkNotDestroyed(); checkNotNull(request, "create request must not be null"); final FirebaseUserManager userManager = getUserManager(); @@ -552,31 +553,32 @@ protected UserRecord execute() throws FirebaseAuthException { /** * Updates an existing user account with the attributes contained in the specified {@link - * UpdateRequest}. + * UserRecord.UpdateRequest}. * - * @param request A non-null {@link UpdateRequest} instance. + * @param request A non-null {@link UserRecord.UpdateRequest} instance. * @return A {@link UserRecord} instance corresponding to the updated user account. * @throws NullPointerException if the provided update request is null. * @throws FirebaseAuthException if an error occurs while updating the user account. */ - public UserRecord updateUser(@NonNull UpdateRequest request) throws FirebaseAuthException { + public UserRecord updateUser(@NonNull UserRecord.UpdateRequest request) + throws FirebaseAuthException { return updateUserOp(request).call(); } /** - * Similar to {@link #updateUser(UpdateRequest)} but performs the operation asynchronously. + * Similar to {@link #updateUser} but performs the operation asynchronously. * - * @param request A non-null {@link UpdateRequest} instance. + * @param request A non-null {@link UserRecord.UpdateRequest} instance. * @return An {@code ApiFuture} which will complete successfully with a {@link UserRecord} * instance corresponding to the updated user account. If an error occurs while updating the * user account, the future throws a {@link FirebaseAuthException}. */ - public ApiFuture updateUserAsync(@NonNull UpdateRequest request) { + public ApiFuture updateUserAsync(@NonNull UserRecord.UpdateRequest request) { return updateUserOp(request).callAsync(firebaseApp); } private CallableOperation updateUserOp( - final UpdateRequest request) { + final UserRecord.UpdateRequest request) { checkNotDestroyed(); checkNotNull(request, "update request must not be null"); final FirebaseUserManager userManager = getUserManager(); @@ -636,7 +638,8 @@ private CallableOperation setCustomUserClaimsOp( return new CallableOperation() { @Override protected Void execute() throws FirebaseAuthException { - final UpdateRequest request = new UpdateRequest(uid).setCustomClaims(claims); + final UserRecord.UpdateRequest request = + new UserRecord.UpdateRequest(uid).setCustomClaims(claims); userManager.updateUser(request, jsonFactory); return null; } @@ -917,18 +920,6 @@ public ApiFuture generateSignInWithEmailLinkAsync( .callAsync(firebaseApp); } - FirebaseApp getFirebaseApp() { - return this.firebaseApp; - } - - FirebaseTokenVerifier getCookieVerifier() { - return this.cookieVerifier.get(); - } - - FirebaseUserManager getUserManager() { - return this.userManager.get(); - } - private CallableOperation generateEmailActionLinkOp( final EmailLinkType type, final String email, final ActionCodeSettings settings) { checkNotDestroyed(); @@ -945,6 +936,98 @@ protected String execute() throws FirebaseAuthException { }; } + /** + * Creates a new provider OIDC Auth config with the attributes contained in the specified {@link + * OidcProviderConfig.CreateRequest}. + * + * @param request A non-null {@link OidcProviderConfig.CreateRequest} instance. + * @return An {@link OidcProviderConfig} instance corresponding to the newly created provider + * config. + * @throws NullPointerException if the provided request is null. + * @throws FirebaseAuthException if an error occurs while creating the provider config. + */ + public OidcProviderConfig createOidcProviderConfig( + @NonNull OidcProviderConfig.CreateRequest request) throws FirebaseAuthException { + return createOidcProviderConfigOp(request).call(); + } + + /** + * Similar to {@link #createOidcProviderConfig} but performs the operation asynchronously. + * + * @param request A non-null {@link OidcProviderConfig.CreateRequest} instance. + * @return An {@code ApiFuture} which will complete successfully with a {@link OidcProviderConfig} + * instance corresponding to the newly created provider config. If an error occurs while + * creating the provider config, the future throws a {@link FirebaseAuthException}. + * @throws NullPointerException if the provided request is null. + */ + public ApiFuture createOidcProviderConfigAsync( + @NonNull OidcProviderConfig.CreateRequest request) { + return createOidcProviderConfigOp(request).callAsync(firebaseApp); + } + + private CallableOperation + createOidcProviderConfigOp(final OidcProviderConfig.CreateRequest request) { + checkNotDestroyed(); + checkNotNull(request, "create request must not be null"); + final FirebaseUserManager userManager = getUserManager(); + return new CallableOperation() { + @Override + protected OidcProviderConfig execute() throws FirebaseAuthException { + return userManager.createOidcProviderConfig(request); + } + }; + } + + /** + * Deletes the provider config identified by the specified provider ID. + * + * @param providerId A provider ID string. + * @throws IllegalArgumentException If the provider ID string is null or empty. + * @throws FirebaseAuthException If an error occurs while deleting the provider config. + */ + public void deleteProviderConfig(@NonNull String providerId) throws FirebaseAuthException { + deleteProviderConfigOp(providerId).call(); + } + + /** + * Similar to {@link #deleteProviderConfig} but performs the operation asynchronously. + * + * @param providerId A provider ID string. + * @return An {@code ApiFuture} which will complete successfully when the specified provider + * config has been deleted. If an error occurs while deleting the provider config, the future + * throws a {@link FirebaseAuthException}. + * @throws IllegalArgumentException If the provider ID string is null or empty. + */ + public ApiFuture deleteProviderConfigAsync(String providerId) { + return deleteProviderConfigOp(providerId).callAsync(firebaseApp); + } + + private CallableOperation deleteProviderConfigOp( + final String providerId) { + checkNotDestroyed(); + checkArgument(!Strings.isNullOrEmpty(providerId), "provider ID must not be null or empty"); + final FirebaseUserManager userManager = getUserManager(); + return new CallableOperation() { + @Override + protected Void execute() throws FirebaseAuthException { + userManager.deleteProviderConfig(providerId); + return null; + } + }; + } + + FirebaseApp getFirebaseApp() { + return this.firebaseApp; + } + + FirebaseTokenVerifier getCookieVerifier() { + return this.cookieVerifier.get(); + } + + FirebaseUserManager getUserManager() { + return this.userManager.get(); + } + protected Supplier threadSafeMemoize(final Supplier supplier) { return Suppliers.memoize( new Supplier() { diff --git a/src/main/java/com/google/firebase/auth/FirebaseUserManager.java b/src/main/java/com/google/firebase/auth/FirebaseUserManager.java index 56ef3f326..0c031a8b9 100644 --- a/src/main/java/com/google/firebase/auth/FirebaseUserManager.java +++ b/src/main/java/com/google/firebase/auth/FirebaseUserManager.java @@ -65,6 +65,7 @@ */ class FirebaseUserManager { + static final String CONFIGURATION_NOT_FOUND = "configuration-not-found"; static final String TENANT_ID_MISMATCH_ERROR = "tenant-id-mismatch"; static final String TENANT_NOT_FOUND_ERROR = "tenant-not-found"; static final String USER_NOT_FOUND_ERROR = "user-not-found"; @@ -74,7 +75,7 @@ class FirebaseUserManager { // SDK error codes defined at: https://firebase.google.com/docs/auth/admin/errors private static final Map ERROR_CODES = ImmutableMap.builder() .put("CLAIMS_TOO_LARGE", "claims-too-large") - .put("CONFIGURATION_NOT_FOUND", "project-not-found") + .put("CONFIGURATION_NOT_FOUND", CONFIGURATION_NOT_FOUND) .put("INSUFFICIENT_PERMISSION", "insufficient-permission") .put("DUPLICATE_EMAIL", "email-already-exists") .put("DUPLICATE_LOCAL_ID", "uid-already-exists") @@ -106,6 +107,7 @@ class FirebaseUserManager { private static final String CLIENT_VERSION_HEADER = "X-Client-Version"; private final String userMgtBaseUrl; + private final String idpConfigMgtBaseUrl; private final String tenantMgtBaseUrl; private final JsonFactory jsonFactory; private final HttpRequestFactory requestFactory; @@ -120,15 +122,18 @@ class FirebaseUserManager { "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."); - String tenantId = builder.tenantId; - if (builder.tenantId == null) { - this.userMgtBaseUrl = String.format(ID_TOOLKIT_URL, "v1", projectId); + final String idToolkitUrlV1 = String.format(ID_TOOLKIT_URL, "v1", projectId); + final String idToolkitUrlV2 = String.format(ID_TOOLKIT_URL, "v2", projectId); + final String tenantId = builder.tenantId; + if (tenantId == null) { + this.userMgtBaseUrl = idToolkitUrlV1; + this.idpConfigMgtBaseUrl = idToolkitUrlV2; } else { checkArgument(!tenantId.isEmpty(), "tenant ID must not be empty"); - this.userMgtBaseUrl = - String.format(ID_TOOLKIT_URL, "v1", projectId) + getTenantUrlSuffix(tenantId); + this.userMgtBaseUrl = idToolkitUrlV1 + getTenantUrlSuffix(tenantId); + this.idpConfigMgtBaseUrl = idToolkitUrlV2 + getTenantUrlSuffix(tenantId); } - this.tenantMgtBaseUrl = String.format(ID_TOOLKIT_URL, "v2", projectId); + this.tenantMgtBaseUrl = idToolkitUrlV2; this.jsonFactory = app.getOptions().getJsonFactory(); this.requestFactory = builder.requestFactory == null ? ApiClientUtils.newAuthorizedRequestFactory(app) : builder.requestFactory; @@ -316,6 +321,20 @@ String getEmailActionLink(EmailLinkType type, String email, throw new FirebaseAuthException(INTERNAL_ERROR, "Failed to create email action link"); } + OidcProviderConfig createOidcProviderConfig( + OidcProviderConfig.CreateRequest request) throws FirebaseAuthException { + GenericUrl url = new GenericUrl(idpConfigMgtBaseUrl + "/oauthIdpConfigs"); + String providerId = request.getProviderId(); + checkArgument(!Strings.isNullOrEmpty(providerId), "provider ID must not be null or empty"); + url.set("oauthIdpConfigId", providerId); + return sendRequest("POST", url, request.getProperties(), OidcProviderConfig.class); + } + + void deleteProviderConfig(String providerId) throws FirebaseAuthException { + GenericUrl url = new GenericUrl(idpConfigMgtBaseUrl + "/oauthIdpConfigs/" + providerId); + sendRequest("DELETE", url, null, GenericJson.class); + } + private static String getTenantUrlSuffix(String tenantId) { checkArgument(!Strings.isNullOrEmpty(tenantId)); return "/tenants/" + tenantId; diff --git a/src/test/java/com/google/firebase/auth/FirebaseAuthIT.java b/src/test/java/com/google/firebase/auth/FirebaseAuthIT.java index bb9838938..98168dacc 100644 --- a/src/test/java/com/google/firebase/auth/FirebaseAuthIT.java +++ b/src/test/java/com/google/firebase/auth/FirebaseAuthIT.java @@ -959,6 +959,69 @@ public void testGenerateSignInWithEmailLink() throws Exception { } } + @Test + public void testOidcProviderConfigLifecycle() throws Exception { + // Create config provider + String providerId = "oidc.provider-id"; + OidcProviderConfig.CreateRequest createRequest = + new OidcProviderConfig.CreateRequest() + .setProviderId(providerId) + .setDisplayName("DisplayName") + .setEnabled(true) + .setClientId("ClientId") + .setIssuer("https://oidc.com/issuer"); + OidcProviderConfig config = auth.createOidcProviderConfigAsync(createRequest).get(); + assertEquals(providerId, config.getProviderId()); + assertEquals("DisplayName", config.getDisplayName()); + assertEquals("ClientId", config.getClientId()); + assertEquals("https://oidc.com/issuer", config.getIssuer()); + + // TODO(micahstairs): Test getOidcProviderConfig and updateProviderConfig operations. + + // Delete config provider + auth.deleteProviderConfigAsync(providerId).get(); + // TODO(micahstairs): Once getOidcProviderConfig operation is implemented, add a check here to + // double-check that the config provider was deleted. + } + + @Test + public void testTenantAwareOidcProviderConfigLifecycle() throws Exception { + // Create tenant to use. + TenantManager tenantManager = auth.getTenantManager(); + Tenant.CreateRequest tenantCreateRequest = + new Tenant.CreateRequest().setDisplayName("DisplayName"); + String tenantId = tenantManager.createTenant(tenantCreateRequest).getTenantId(); + + try { + // Create config provider + TenantAwareFirebaseAuth tenantAwareAuth = auth.getTenantManager().getAuthForTenant(tenantId); + String providerId = "oidc.provider-id"; + OidcProviderConfig.CreateRequest createRequest = + new OidcProviderConfig.CreateRequest() + .setProviderId(providerId) + .setDisplayName("DisplayName") + .setEnabled(true) + .setClientId("ClientId") + .setIssuer("https://oidc.com/issuer"); + OidcProviderConfig config = + tenantAwareAuth.createOidcProviderConfigAsync(createRequest).get(); + assertEquals(providerId, config.getProviderId()); + assertEquals("DisplayName", config.getDisplayName()); + assertEquals("ClientId", config.getClientId()); + assertEquals("https://oidc.com/issuer", config.getIssuer()); + + // TODO(micahstairs): Test getOidcProviderConfig and updateProviderConfig operations. + + // Delete config provider + tenantAwareAuth.deleteProviderConfigAsync(providerId).get(); + // TODO(micahstairs): Once getOidcProviderConfig operation is implemented, add a check here to + // double-check that the config provider was deleted. + } finally { + // Delete tenant. + tenantManager.deleteTenantAsync(tenantId).get(); + } + } + private Map parseLinkParameters(String link) throws Exception { Map result = new HashMap<>(); int queryBegin = link.indexOf('?'); diff --git a/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java b/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java index 20eb56222..13b77f832 100644 --- a/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java +++ b/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java @@ -65,6 +65,7 @@ public class FirebaseUserManagerTest { private static final JsonFactory JSON_FACTORY = Utils.getDefaultJsonFactory(); private static final String TEST_TOKEN = "token"; private static final GoogleCredentials credentials = new MockGoogleCredentials(TEST_TOKEN); + private static final ActionCodeSettings ACTION_CODE_SETTINGS = ActionCodeSettings.builder() .setUrl("https://example.dynamic.link") .setHandleCodeInApp(true) @@ -76,8 +77,10 @@ public class FirebaseUserManagerTest { .build(); private static final Map ACTION_CODE_SETTINGS_MAP = ACTION_CODE_SETTINGS.getProperties(); - private static final String TENANTS_BASE_URL = - "https://identitytoolkit.googleapis.com/v2/projects/test-project-id/tenants"; + + private static final String PROJECT_BASE_URL = + "https://identitytoolkit.googleapis.com/v2/projects/test-project-id"; + private static final String TENANTS_BASE_URL = PROJECT_BASE_URL + "/tenants"; @After public void tearDown() { @@ -1383,6 +1386,149 @@ public void testUnexpectedHttpError() { } } + @Test + public void testCreateOidcProvider() throws Exception { + TestResponseInterceptor interceptor = initializeAppForUserManagement( + TestUtils.loadResource("oidc.json")); + 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); + checkRequestHeaders(interceptor); + checkUrl(interceptor, "POST", PROJECT_BASE_URL + "/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")); + } + + @Test + public void testCreateOidcProviderMinimal() throws Exception { + TestResponseInterceptor interceptor = initializeAppForUserManagement( + TestUtils.loadResource("oidc.json")); + // Only the 'enabled' field can be omitted from an OIDC provider config creation request. + OidcProviderConfig.CreateRequest createRequest = + new OidcProviderConfig.CreateRequest() + .setProviderId("oidc.provider-id") + .setDisplayName("DISPLAY_NAME") + .setClientId("CLIENT_ID") + .setIssuer("https://oidc.com/issuer"); + + FirebaseAuth.getInstance().createOidcProviderConfig(createRequest); + checkRequestHeaders(interceptor); + checkUrl(interceptor, "POST", PROJECT_BASE_URL + "/oauthIdpConfigs"); + GenericJson parsed = parseRequestContent(interceptor); + assertEquals("DISPLAY_NAME", parsed.get("displayName")); + assertNull(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")); + } + + @Test + public void testCreateOidcProviderError() throws Exception { + TestResponseInterceptor interceptor = + initializeAppForUserManagementWithStatusCode(404, + "{\"error\": {\"message\": \"INTERNAL_ERROR\"}}"); + OidcProviderConfig.CreateRequest createRequest = + new OidcProviderConfig.CreateRequest().setProviderId("oidc.provider-id"); + try { + FirebaseAuth.getInstance().createOidcProviderConfig(createRequest); + fail("No error thrown for invalid response"); + } catch (FirebaseAuthException e) { + assertEquals(FirebaseUserManager.INTERNAL_ERROR, e.getErrorCode()); + } + checkUrl(interceptor, "POST", PROJECT_BASE_URL + "/oauthIdpConfigs"); + } + + @Test + public void testCreateOidcProviderMissingId() throws Exception { + TestResponseInterceptor interceptor = initializeAppForUserManagement( + TestUtils.loadResource("oidc.json")); + OidcProviderConfig.CreateRequest createRequest = + new OidcProviderConfig.CreateRequest() + .setDisplayName("DISPLAY_NAME") + .setEnabled(true) + .setClientId("CLIENT_ID") + .setIssuer("https://oidc.com/issuer"); + try { + FirebaseAuth.getInstance().createOidcProviderConfig(createRequest); + fail("No error thrown for invalid response"); + } catch (IllegalArgumentException e) { + // Expected. + } + } + + @Test + public void testTenantAwareCreateOidcProvider() throws Exception { + TestResponseInterceptor interceptor = initializeAppForTenantAwareUserManagement( + "TENANT_ID", + TestUtils.loadResource("oidc.json")); + OidcProviderConfig.CreateRequest createRequest = + new OidcProviderConfig.CreateRequest() + .setProviderId("oidc.provider-id") + .setDisplayName("DISPLAY_NAME") + .setEnabled(true) + .setClientId("CLIENT_ID") + .setIssuer("https://oidc.com/issuer"); + TenantAwareFirebaseAuth tenantAwareAuth = + FirebaseAuth.getInstance().getTenantManager().getAuthForTenant("TENANT_ID"); + + OidcProviderConfig config = tenantAwareAuth.createOidcProviderConfig(createRequest); + + checkRequestHeaders(interceptor); + checkUrl(interceptor, "POST", TENANTS_BASE_URL + "/TENANT_ID/oauthIdpConfigs"); + } + + @Test + public void testDeleteProviderConfig() throws Exception { + TestResponseInterceptor interceptor = initializeAppForUserManagement("{}"); + + FirebaseAuth.getInstance().deleteProviderConfig("PROVIDER_ID"); + + checkRequestHeaders(interceptor); + checkUrl(interceptor, "DELETE", PROJECT_BASE_URL + "/oauthIdpConfigs/PROVIDER_ID"); + } + + @Test + public void testDeleteProviderConfigWithNotFoundError() throws Exception { + TestResponseInterceptor interceptor = + initializeAppForUserManagementWithStatusCode(404, + "{\"error\": {\"message\": \"CONFIGURATION_NOT_FOUND\"}}"); + try { + FirebaseAuth.getInstance().deleteProviderConfig("UNKNOWN"); + fail("No error thrown for invalid response"); + } catch (FirebaseAuthException e) { + assertEquals(FirebaseUserManager.CONFIGURATION_NOT_FOUND, e.getErrorCode()); + } + checkUrl(interceptor, "DELETE", PROJECT_BASE_URL + "/oauthIdpConfigs/UNKNOWN"); + } + + @Test + public void testTenantAwareDeleteProviderConfig() throws Exception { + TestResponseInterceptor interceptor = initializeAppForTenantAwareUserManagement( + "TENANT_ID", + "{}"); + TenantAwareFirebaseAuth tenantAwareAuth = + FirebaseAuth.getInstance().getTenantManager().getAuthForTenant("TENANT_ID"); + + tenantAwareAuth.deleteProviderConfig("PROVIDER_ID"); + + checkRequestHeaders(interceptor); + checkUrl(interceptor, "DELETE", TENANTS_BASE_URL + "/TENANT_ID/oauthIdpConfigs/PROVIDER_ID"); + } + private static TestResponseInterceptor initializeAppForUserManagementWithStatusCode( int statusCode, String response) { FirebaseApp.initializeApp(new FirebaseOptions.Builder() @@ -1397,7 +1543,24 @@ private static TestResponseInterceptor initializeAppForUserManagementWithStatusC return interceptor; } + private static TestResponseInterceptor initializeAppForTenantAwareUserManagement( + String tenantId, + String... responses) { + initializeAppWithResponses(responses); + TestResponseInterceptor interceptor = new TestResponseInterceptor(); + TenantManager tenantManager = FirebaseAuth.getInstance().getTenantManager(); + tenantManager.getAuthForTenant(tenantId).getUserManager().setInterceptor(interceptor); + return interceptor; + } + private static TestResponseInterceptor initializeAppForUserManagement(String... responses) { + initializeAppWithResponses(responses); + TestResponseInterceptor interceptor = new TestResponseInterceptor(); + FirebaseAuth.getInstance().getUserManager().setInterceptor(interceptor); + return interceptor; + } + + private static void initializeAppWithResponses(String... responses) { List mocks = new ArrayList<>(); for (String response : responses) { mocks.add(new MockLowLevelHttpResponse().setContent(response)); @@ -1408,9 +1571,6 @@ private static TestResponseInterceptor initializeAppForUserManagement(String... .setHttpTransport(transport) .setProjectId("test-project-id") .build()); - TestResponseInterceptor interceptor = new TestResponseInterceptor(); - FirebaseAuth.getInstance().getUserManager().setInterceptor(interceptor); - return interceptor; } private static GenericJson parseRequestContent(TestResponseInterceptor interceptor) @@ -1485,6 +1645,14 @@ private static void checkTenant(Tenant tenant, String tenantId) { assertFalse(tenant.isEmailLinkSignInEnabled()); } + private static void checkOidcProviderConfig(OidcProviderConfig config) { + assertEquals("oidc.provider-id", config.getProviderId()); + assertEquals("DISPLAY_NAME", config.getDisplayName()); + assertTrue(config.isEnabled()); + assertEquals("CLIENT_ID", config.getClientId()); + assertEquals("https://oidc.com/issuer", config.getIssuer()); + } + private static void checkRequestHeaders(TestResponseInterceptor interceptor) { HttpHeaders headers = interceptor.getResponse().getRequest().getHeaders(); String auth = "Bearer " + TEST_TOKEN; diff --git a/src/test/resources/oidc.json b/src/test/resources/oidc.json new file mode 100644 index 000000000..e2f1845de --- /dev/null +++ b/src/test/resources/oidc.json @@ -0,0 +1,7 @@ +{ + "name": "projects/projectId/oauthIdpConfigs/oidc.provider-id", + "displayName" : "DISPLAY_NAME", + "enabled" : true, + "clientId" : "CLIENT_ID", + "issuer" : "https://oidc.com/issuer" +}