Repository: firebase/firebase-admin-java
Pull request #532 (2021-04-27 23:58:13)

feat(auth): enables OIDC auth code flow
Provides an option for developers to specify the OAuth response type for their OIDC provider (either one of these can be set:):

- id_token
- code (if set, must also set the client secret)


Patch:
diff --git a/src/main/java/com/google/firebase/auth/OidcProviderConfig.java b/src/main/java/com/google/firebase/auth/OidcProviderConfig.java
index 2693178..0a4f7c0 100644
--- a/src/main/java/com/google/firebase/auth/OidcProviderConfig.java
+++ b/src/main/java/com/google/firebase/auth/OidcProviderConfig.java
@@ -18,8 +18,11 @@ package com.google.firebase.auth;
 
 import static com.google.common.base.Preconditions.checkArgument;
 
+import com.google.api.client.json.GenericJson;
 import com.google.api.client.util.Key;
 import com.google.common.base.Strings;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Contains metadata associated with an OIDC Auth provider.
@@ -31,17 +34,35 @@ public final class OidcProviderConfig extends ProviderConfig {
   @Key("clientId")
   private String clientId;
 
+  @Key("clientSecret")
+  private String clientSecret;
+
   @Key("issuer")
   private String issuer;
 
+  @Key("responseType")
+  private GenericJson responseType;
+
   public String getClientId() {
     return clientId;
   }
 
+  public String getClientSecret() {
+    return clientSecret;
+  }
+
   public String getIssuer() {
     return issuer;
   }
 
+  public boolean isCodeResponseType() {
+    return (responseType.containsKey("code") && (boolean) responseType.get("code"));
+  }
+
+  public boolean isIdTokenResponseType() {
+    return (responseType.containsKey("idToken") && (boolean) responseType.get("idToken"));
+  }
+
   /**
    * Returns a new {@link UpdateRequest}, which can be used to update the attributes of this
    * provider config.
@@ -58,6 +79,13 @@ public final class OidcProviderConfig extends ProviderConfig {
         "Invalid OIDC provider ID (must be prefixed with 'oidc.'): " + providerId);
   }
 
+  static Map<String, Boolean> ensureResponseType(Map<String,Object> properties) {
+    if (properties.get("responseType") == null) {
+      properties.put("responseType", new HashMap<String, Boolean>());
+    }
+    return (Map<String, Boolean>) properties.get("responseType");
+  }
+
   /**
    * A specification class for creating a new OIDC Auth provider.
    *
@@ -99,6 +127,19 @@ public final class OidcProviderConfig extends ProviderConfig {
       return this;
     }
 
+    /**
+     * Sets the client secret for the new provider. This is required for the code flow.
+     *
+     * @param clientSecret A non-null, non-empty client secret string.
+     * @throws IllegalArgumentException If the client secret is null or empty.
+     */
+    public CreateRequest setClientSecret(String clientSecret) {
+      checkArgument(!Strings.isNullOrEmpty(clientSecret),
+          "Client Secret must not be null or empty.");
+      properties.put("clientSecret", clientSecret);
+      return this;
+    }
+
     /**
      * Sets the issuer for the new provider.
      *
@@ -113,6 +154,36 @@ public final class OidcProviderConfig extends ProviderConfig {
       return this;
     }
 
+    /**
+     * Sets whether to enable the code response flow for the new provider. By default, this is not
+     * enabled if no response type is specified.
+     *
+     * <p>A client secret must be set for this response type.
+     *
+     * <p>Having both the code and ID token response flows is currently not supported.
+     *
+     * @param enabled A boolean signifying whether the code response type is supported.
+     */
+    public CreateRequest setCodeResponseType(boolean enabled) {
+      Map<String, Boolean> map = ensureResponseType(properties);
+      map.put("code", enabled);
+      return this;
+    }
+
+    /**
+     * Sets whether to enable the ID token response flow for the new provider. By default, this is
+     * enabled if no response type is specified.
+     *
+     * <p>Having both the code and ID token response flows is currently not supported.
+     *
+     * @param enabled A boolean signifying whether the ID token response type is supported.
+     */
+    public CreateRequest setIdTokenResponseType(boolean enabled) {
+      Map<String, Boolean> map = ensureResponseType(properties);
+      map.put("idToken", enabled);
+      return this;
+    }
+
     CreateRequest getThis() {
       return this;
     }
@@ -156,6 +227,19 @@ public final class OidcProviderConfig extends ProviderConfig {
       return this;
     }
 
+    /**
+     * Sets the client secret for the new provider. This is required for the code flow.
+     *
+     * @param clientSecret A non-null, non-empty client secret string.
+     * @throws IllegalArgumentException If the client secret is null or empty.
+     */
+    public UpdateRequest setClientSecret(String clientSecret) {
+      checkArgument(!Strings.isNullOrEmpty(clientSecret),
+          "Client Secret must not be null or empty.");
+      properties.put("clientSecret", clientSecret);
+      return this;
+    }
+
     /**
      * Sets the issuer for the existing provider.
      *
@@ -170,6 +254,36 @@ public final class OidcProviderConfig extends ProviderConfig {
       return this;
     }
 
+    /**
+     * Sets whether to enable the code response flow for the new provider. By default, this is not
+     * enabled if no response type is specified.
+     *
+     * <p>A client secret must be set for this response type.
+     *
+     * <p>Having both the code and ID token response flows is currently not supported.
+     *
+     * @param enabled A boolean signifying whether the code response type is supported.
+     */
+    public UpdateRequest setCodeResponseType(boolean enabled) {
+      Map<String, Boolean> map = ensureResponseType(properties);
+      map.put("code", enabled);
+      return this;
+    }
+
+    /**
+     * Sets whether to enable the ID token response flow for the new provider. By default, this is
+     * enabled if no response type is specified.
+     *
+     * <p>Having both the code and ID token response flows is currently not supported.
+     *
+     * @param enabled A boolean signifying whether the ID token response type is supported.
+     */
+    public UpdateRequest setIdTokenResponseType(boolean enabled) {
+      Map<String, Boolean> map = ensureResponseType(properties);
+      map.put("idToken", enabled);
+      return this;
+    }
+
     UpdateRequest getThis() {
       return this;
     }


Test patch:
diff --git a/src/test/java/com/google/firebase/auth/FirebaseAuthIT.java b/src/test/java/com/google/firebase/auth/FirebaseAuthIT.java
index 7d02d35..0d65d51 100644
--- a/src/test/java/com/google/firebase/auth/FirebaseAuthIT.java
+++ b/src/test/java/com/google/firebase/auth/FirebaseAuthIT.java
@@ -792,12 +792,19 @@ public class FirebaseAuthIT {
             .setDisplayName("DisplayName")
             .setEnabled(true)
             .setClientId("ClientId")
-            .setIssuer("https://oidc.com/issuer"));
+            .setClientSecret("ClientSecret")
+            .setIssuer("https://oidc.com/issuer")
+            .setCodeResponseType(true)
+            .setIdTokenResponseType(false));
+
     assertEquals(providerId, config.getProviderId());
     assertEquals("DisplayName", config.getDisplayName());
     assertTrue(config.isEnabled());
     assertEquals("ClientId", config.getClientId());
+    assertEquals("ClientSecret", config.getClientSecret());
     assertEquals("https://oidc.com/issuer", config.getIssuer());
+    assertTrue(config.isCodeResponseType());
+    assertFalse(config.isIdTokenResponseType());
 
     // Get provider config
     config = auth.getOidcProviderConfigAsync(providerId).get();
@@ -805,7 +812,10 @@ public class FirebaseAuthIT {
     assertEquals("DisplayName", config.getDisplayName());
     assertTrue(config.isEnabled());
     assertEquals("ClientId", config.getClientId());
+    assertEquals("ClientSecret", config.getClientSecret());
     assertEquals("https://oidc.com/issuer", config.getIssuer());
+    assertTrue(config.isCodeResponseType());
+    assertFalse(config.isIdTokenResponseType());
 
     // Update provider config
     OidcProviderConfig.UpdateRequest updateRequest =
@@ -813,13 +823,20 @@ public class FirebaseAuthIT {
             .setDisplayName("NewDisplayName")
             .setEnabled(false)
             .setClientId("NewClientId")
-            .setIssuer("https://oidc.com/new-issuer");
+            .setClientSecret("NewClientSecret")
+            .setIssuer("https://oidc.com/new-issuer")
+            .setCodeResponseType(false)
+            .setIdTokenResponseType(true);
+
     config = auth.updateOidcProviderConfigAsync(updateRequest).get();
     assertEquals(providerId, config.getProviderId());
     assertEquals("NewDisplayName", config.getDisplayName());
     assertFalse(config.isEnabled());
     assertEquals("NewClientId", config.getClientId());
+    assertEquals("NewClientSecret", config.getClientSecret());
     assertEquals("https://oidc.com/new-issuer", config.getIssuer());
+    assertTrue(config.isIdTokenResponseType());
+    assertFalse(config.isCodeResponseType());
 
     // Delete provider config
     temporaryProviderConfig.deleteOidcProviderConfig(providerId);
diff --git a/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java b/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java
index bbe8b2e..4014e05 100644
--- a/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java
+++ b/src/test/java/com/google/firebase/auth/FirebaseUserManagerTest.java
@@ -1615,7 +1615,10 @@ public class FirebaseUserManagerTest {
             .setDisplayName("DISPLAY_NAME")
             .setEnabled(true)
             .setClientId("CLIENT_ID")
-            .setIssuer("https://oidc.com/issuer");
+            .setClientSecret("CLIENT_SECRET")
+            .setIssuer("https://oidc.com/issuer")
+            .setCodeResponseType(true)
+            .setIdTokenResponseType(true);
 
     OidcProviderConfig config = FirebaseAuth.getInstance().createOidcProviderConfig(createRequest);
 
@@ -1626,7 +1629,13 @@ public class FirebaseUserManagerTest {
     assertEquals("DISPLAY_NAME", parsed.get("displayName"));
     assertTrue((boolean) parsed.get("enabled"));
     assertEquals("CLIENT_ID", parsed.get("clientId"));
+    assertEquals("CLIENT_SECRET", parsed.get("clientSecret"));
     assertEquals("https://oidc.com/issuer", parsed.get("issuer"));
+
+    Map<String, Boolean> responseType = (Map<String, Boolean>) parsed.get("responseType");
+    assertTrue(responseType.get("code"));
+    assertTrue(responseType.get("idToken"));
+
     GenericUrl url = interceptor.getResponse().getRequest().getUrl();
     assertEquals("oidc.provider-id", url.getFirst("oauthIdpConfigId"));
   }
@@ -1640,7 +1649,10 @@ public class FirebaseUserManagerTest {
             .setDisplayName("DISPLAY_NAME")
             .setEnabled(true)
             .setClientId("CLIENT_ID")
-            .setIssuer("https://oidc.com/issuer");
+            .setClientSecret("CLIENT_SECRET")
+            .setIssuer("https://oidc.com/issuer")
+            .setCodeResponseType(true)
+            .setIdTokenResponseType(true);
 
     OidcProviderConfig config =
         FirebaseAuth.getInstance().createOidcProviderConfigAsync(createRequest).get();
@@ -1652,7 +1664,13 @@ public class FirebaseUserManagerTest {
     assertEquals("DISPLAY_NAME", parsed.get("displayName"));
     assertTrue((boolean) parsed.get("enabled"));
     assertEquals("CLIENT_ID", parsed.get("clientId"));
+    assertEquals("CLIENT_SECRET", parsed.get("clientSecret"));
     assertEquals("https://oidc.com/issuer", parsed.get("issuer"));
+
+    Map<String, Boolean> responseType = (Map<String, Boolean>) parsed.get("responseType");
+    assertTrue(responseType.get("code"));
+    assertTrue(responseType.get("idToken"));
+
     GenericUrl url = interceptor.getResponse().getRequest().getUrl();
     assertEquals("oidc.provider-id", url.getFirst("oauthIdpConfigId"));
   }
@@ -1855,7 +1873,10 @@ public class FirebaseUserManagerTest {
             .setDisplayName("DISPLAY_NAME")
             .setEnabled(true)
             .setClientId("CLIENT_ID")
-            .setIssuer("https://oidc.com/issuer");
+            .setClientSecret("CLIENT_SECRET")
+            .setIssuer("https://oidc.com/issuer")
+            .setCodeResponseType(true)
+            .setIdTokenResponseType(true);
 
     OidcProviderConfig config = tenantAwareAuth.updateOidcProviderConfig(request);
 
@@ -1864,12 +1885,18 @@ public class FirebaseUserManagerTest {
     String expectedUrl = TENANTS_BASE_URL + "/TENANT_ID/oauthIdpConfigs/oidc.provider-id";
     checkUrl(interceptor, "PATCH", expectedUrl);
     GenericUrl url = interceptor.getResponse().getRequest().getUrl();
-    assertEquals("clientId,displayName,enabled,issuer", url.getFirst("updateMask"));
+    assertEquals("clientId,clientSecret,displayName,enabled,issuer,responseType.code,"
+        + "responseType.idToken", url.getFirst("updateMask"));
     GenericJson parsed = parseRequestContent(interceptor);
     assertEquals("DISPLAY_NAME", parsed.get("displayName"));
     assertTrue((boolean) parsed.get("enabled"));
     assertEquals("CLIENT_ID", parsed.get("clientId"));
+    assertEquals("CLIENT_SECRET", parsed.get("clientSecret"));
     assertEquals("https://oidc.com/issuer", parsed.get("issuer"));
+
+    Map<String, Boolean> responseType = (Map<String, Boolean>) parsed.get("responseType");
+    assertTrue(responseType.get("code"));
+    assertTrue(responseType.get("idToken"));
   }
 
   @Test
@@ -2948,7 +2975,10 @@ public class FirebaseUserManagerTest {
     assertEquals("DISPLAY_NAME", config.getDisplayName());
     assertTrue(config.isEnabled());
     assertEquals("CLIENT_ID", config.getClientId());
+    assertEquals("CLIENT_SECRET", config.getClientSecret());
     assertEquals("https://oidc.com/issuer", config.getIssuer());
+    assertTrue(config.isCodeResponseType());
+    assertFalse(config.isIdTokenResponseType());
   }
 
   private static void checkSamlProviderConfig(SamlProviderConfig config, String providerId) {
@@ -2980,5 +3010,4 @@ public class FirebaseUserManagerTest {
   private interface UserManagerOp {
     void call(FirebaseAuth auth) throws Exception;
   }
-
 }
diff --git a/src/test/java/com/google/firebase/auth/OidcProviderConfigTest.java b/src/test/java/com/google/firebase/auth/OidcProviderConfigTest.java
index 1fb4ca3..b8a5d50 100644
--- a/src/test/java/com/google/firebase/auth/OidcProviderConfigTest.java
+++ b/src/test/java/com/google/firebase/auth/OidcProviderConfigTest.java
@@ -18,11 +18,13 @@ package com.google.firebase.auth;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import com.google.api.client.googleapis.util.Utils;
 import com.google.api.client.json.JsonFactory;
 import java.io.IOException;
+import java.util.HashMap;
 import java.util.Map;
 import org.junit.Test;
 
@@ -36,7 +38,12 @@ public class OidcProviderConfigTest {
         + "  'displayName': 'DISPLAY_NAME',"
         + "  'enabled':      true,"
         + "  'clientId':    'CLIENT_ID',"
-        + "  'issuer':      'https://oidc.com/issuer'"
+        + "  'clientSecret':'CLIENT_SECRET',"
+        + "  'issuer':      'https://oidc.com/issuer',"
+        + "  'responseType': {"
+        + "    'code':  true,"
+        + "    'idToken': false"
+        + "   }"
         + "}").replace("'", "\"");
 
   @Test
@@ -47,7 +54,35 @@ public class OidcProviderConfigTest {
     assertEquals("DISPLAY_NAME", config.getDisplayName());
     assertTrue(config.isEnabled());
     assertEquals("CLIENT_ID", config.getClientId());
+    assertEquals("CLIENT_SECRET", config.getClientSecret());
     assertEquals("https://oidc.com/issuer", config.getIssuer());
+    assertTrue(config.isCodeResponseType());
+    assertFalse(config.isIdTokenResponseType());
+  }
+
+  @Test
+  public void testEnsureResponseType() {
+    Map<String, Object> properties = new HashMap<>();
+
+    Map<String, Boolean> responseType = OidcProviderConfig.ensureResponseType(properties);
+
+    assertNotNull(responseType);
+    assertEquals(responseType, properties.get("responseType"));
+  }
+
+  @Test
+  public void testEnsureResponseTypeAlreadyPresent() {
+    Map<String, Object> properties = new HashMap<>();
+    Map<String, Boolean> responseType = new HashMap<>();
+    responseType.put("code", true);
+    properties.put("responseType", responseType);
+
+    Map<String, Boolean> returnedResponseType = OidcProviderConfig.ensureResponseType(properties);
+
+    assertEquals(responseType, returnedResponseType);
+    assertTrue(returnedResponseType.get("code"));
+    assertEquals(returnedResponseType.size(), 1);
+    assertEquals(responseType, properties.get("responseType"));
   }
 
   @Test
@@ -58,15 +93,23 @@ public class OidcProviderConfigTest {
       .setDisplayName("DISPLAY_NAME")
       .setEnabled(false)
       .setClientId("CLIENT_ID")
-      .setIssuer("https://oidc.com/issuer");
+      .setClientSecret("CLIENT_SECRET")
+      .setIssuer("https://oidc.com/issuer")
+      .setCodeResponseType(true)
+      .setIdTokenResponseType(false);
 
     assertEquals("oidc.provider-id", createRequest.getProviderId());
     Map<String,Object> properties = createRequest.getProperties();
-    assertEquals(properties.size(), 4);
+    assertEquals(properties.size(), 6);
     assertEquals("DISPLAY_NAME", (String) properties.get("displayName"));
     assertFalse((boolean) properties.get("enabled"));
     assertEquals("CLIENT_ID", (String) properties.get("clientId"));
+    assertEquals("CLIENT_SECRET", properties.get("clientSecret"));
     assertEquals("https://oidc.com/issuer", (String) properties.get("issuer"));
+
+    Map<String, Boolean> responseType = (Map<String, Boolean>) properties.get("responseType");
+    assertTrue(responseType.get("code"));
+    assertFalse(responseType.get("idToken"));
   }
 
   @Test(expected = IllegalArgumentException.class)
@@ -99,6 +142,16 @@ public class OidcProviderConfigTest {
     new OidcProviderConfig.CreateRequest().setIssuer("not a valid url");
   }
 
+  @Test(expected = IllegalArgumentException.class)
+  public void testCreateRequestMissingClientSecret() {
+    new OidcProviderConfig.CreateRequest().setClientSecret(null);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testCreateRequestEmptyClientSecret() {
+    new OidcProviderConfig.CreateRequest().setClientSecret("");
+  }
+
   @Test
   public void testUpdateRequestFromOidcProviderConfig() throws IOException {
     OidcProviderConfig config = jsonFactory.fromString(OIDC_JSON_STRING, OidcProviderConfig.class);
@@ -117,15 +170,23 @@ public class OidcProviderConfigTest {
       .setDisplayName("DISPLAY_NAME")
       .setEnabled(false)
       .setClientId("CLIENT_ID")
-      .setIssuer("https://oidc.com/issuer");
+      .setClientSecret("CLIENT_SECRET")
+      .setIssuer("https://oidc.com/issuer")
+      .setCodeResponseType(true)
+      .setIdTokenResponseType(false);
 
     assertEquals("oidc.provider-id", updateRequest.getProviderId());
     Map<String,Object> properties = updateRequest.getProperties();
-    assertEquals(properties.size(), 4);
+    assertEquals(properties.size(), 6);
     assertEquals("DISPLAY_NAME", (String) properties.get("displayName"));
     assertFalse((boolean) properties.get("enabled"));
     assertEquals("CLIENT_ID", (String) properties.get("clientId"));
+    assertEquals("CLIENT_SECRET", (String) properties.get("clientSecret"));
     assertEquals("https://oidc.com/issuer", (String) properties.get("issuer"));
+
+    Map<String, Boolean> responseType = (Map<String, Boolean>) properties.get("responseType");
+    assertTrue(responseType.get("code"));
+    assertFalse(responseType.get("idToken"));
   }
 
   @Test(expected = IllegalArgumentException.class)
@@ -157,4 +218,14 @@ public class OidcProviderConfigTest {
   public void testUpdateRequestInvalidIssuerUrl() {
     new OidcProviderConfig.UpdateRequest("oidc.provider-id").setIssuer("not a valid url");
   }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testUpdateRequestMissingClientSecret() {
+    new OidcProviderConfig.UpdateRequest("oidc.provider-id").setClientSecret(null);
+  }
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testUpdateRequestEmptyClientSecret() {
+    new OidcProviderConfig.UpdateRequest("oidc.provider-id").setClientSecret("");
+  }
 }
diff --git a/src/test/java/com/google/firebase/auth/multitenancy/TenantAwareFirebaseAuthIT.java b/src/test/java/com/google/firebase/auth/multitenancy/TenantAwareFirebaseAuthIT.java
index 1ebac21..3c4578e 100644
--- a/src/test/java/com/google/firebase/auth/multitenancy/TenantAwareFirebaseAuthIT.java
+++ b/src/test/java/com/google/firebase/auth/multitenancy/TenantAwareFirebaseAuthIT.java
@@ -279,18 +279,28 @@ public class TenantAwareFirebaseAuthIT {
               .setDisplayName("DisplayName")
               .setEnabled(true)
               .setClientId("ClientId")
-              .setIssuer("https://oidc.com/issuer"));
+              .setClientSecret("ClientSecret")
+              .setIssuer("https://oidc.com/issuer")
+              .setCodeResponseType(true)
+              .setIdTokenResponseType(false));
+
     assertEquals(providerId, config.getProviderId());
     assertEquals("DisplayName", config.getDisplayName());
     assertEquals("ClientId", config.getClientId());
+    assertEquals("ClientSecret", config.getClientSecret());
     assertEquals("https://oidc.com/issuer", config.getIssuer());
+    assertTrue(config.isCodeResponseType());
+    assertFalse(config.isIdTokenResponseType());
 
     // Get provider config
     config = tenantAwareAuth.getOidcProviderConfigAsync(providerId).get();
     assertEquals(providerId, config.getProviderId());
     assertEquals("DisplayName", config.getDisplayName());
     assertEquals("ClientId", config.getClientId());
+    assertEquals("ClientSecret", config.getClientSecret());
     assertEquals("https://oidc.com/issuer", config.getIssuer());
+    assertTrue(config.isCodeResponseType());
+    assertFalse(config.isIdTokenResponseType());
 
     // Update provider config
     OidcProviderConfig.UpdateRequest updateRequest =
@@ -298,13 +308,20 @@ public class TenantAwareFirebaseAuthIT {
             .setDisplayName("NewDisplayName")
             .setEnabled(false)
             .setClientId("NewClientId")
-            .setIssuer("https://oidc.com/new-issuer");
+            .setClientSecret("NewClientSecret")
+            .setIssuer("https://oidc.com/new-issuer")
+            .setCodeResponseType(false)
+            .setIdTokenResponseType(true);
+
     config = tenantAwareAuth.updateOidcProviderConfigAsync(updateRequest).get();
     assertEquals(providerId, config.getProviderId());
     assertEquals("NewDisplayName", config.getDisplayName());
     assertFalse(config.isEnabled());
     assertEquals("NewClientId", config.getClientId());
+    assertEquals("NewClientSecret", config.getClientSecret());
     assertEquals("https://oidc.com/new-issuer", config.getIssuer());
+    assertFalse(config.isCodeResponseType());
+    assertTrue(config.isIdTokenResponseType());
 
     // Delete provider config
     temporaryProviderConfig.deleteOidcProviderConfig(providerId);
diff --git a/src/test/resources/listOidc.json b/src/test/resources/listOidc.json
index 0c13ea4..82a2f76 100644
--- a/src/test/resources/listOidc.json
+++ b/src/test/resources/listOidc.json
@@ -4,12 +4,22 @@
     "displayName" : "DISPLAY_NAME",
     "enabled" : true,
     "clientId" : "CLIENT_ID",
-    "issuer" : "https://oidc.com/issuer"
+    "clientSecret" : "CLIENT_SECRET",
+    "issuer" : "https://oidc.com/issuer",
+    "responseType" : {
+      "code": true,
+      "idToken": false
+    }
   }, {
     "name": "projects/projectId/oauthIdpConfigs/oidc.provider-id2",
     "displayName" : "DISPLAY_NAME",
     "enabled" : true,
     "clientId" : "CLIENT_ID",
-    "issuer" : "https://oidc.com/issuer"
+    "clientSecret" : "CLIENT_SECRET",
+    "issuer" : "https://oidc.com/issuer",
+    "responseType" : {
+      "code": true,
+      "idToken": false
+    }
   } ]
 }
diff --git a/src/test/resources/oidc.json b/src/test/resources/oidc.json
index e2f1845..0aed0df 100644
--- a/src/test/resources/oidc.json
+++ b/src/test/resources/oidc.json
@@ -3,5 +3,10 @@
   "displayName" : "DISPLAY_NAME",
   "enabled" : true,
   "clientId" : "CLIENT_ID",
-  "issuer" : "https://oidc.com/issuer"
+  "clientSecret" : "CLIENT_SECRET",
+  "issuer" : "https://oidc.com/issuer",
+  "responseType" : {
+    "code": true,
+    "idToken": false
+  }
 }