Repository: gravitee-io/graviteeio-access-management
Pull request #567 (2019-04-26 17:26:57)

fix: missing response_types in DCR feature
Hello,
This close issue [#2178](https://github.com/gravitee-io/issues/issues/2178)
Regards,
Alexandre.

lusoalex: @tcompiegne @brasseld this PR is ready for review.

Patch:
diff --git a/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/GrantTypeUtils.java b/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/GrantTypeUtils.java
index 4b48c2d286..b90163a01c 100644
--- a/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/GrantTypeUtils.java
+++ b/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/GrantTypeUtils.java
@@ -23,7 +23,7 @@ import java.util.stream.Collectors;
 import static io.gravitee.am.common.oauth2.GrantType.*;
 import static io.gravitee.am.common.oauth2.ResponseType.CODE;
 import static io.gravitee.am.common.oauth2.ResponseType.TOKEN;
-import static io.gravitee.am.common.oidc.ResponseType.ID_TOKEN;
+import static io.gravitee.am.common.oidc.ResponseType.*;
 
 /**
  * @author Alexandre FARIA (contact at alexandrefaria.net)
@@ -80,25 +80,25 @@ public class GrantTypeUtils {
         Set grantType = client.getAuthorizedGrantTypes() != null ? new HashSet<>(client.getAuthorizedGrantTypes()) : new HashSet();
 
         //If response type contains "code", then grant_type must contains "authorization_code"
-        if(responseType.contains(CODE) && !grantType.contains(AUTHORIZATION_CODE)) {
+        if(mustHaveAuthorizationCode(responseType) && !grantType.contains(AUTHORIZATION_CODE)) {
             grantType.add(AUTHORIZATION_CODE);
             updatedGrantType=true;
         }
 
         //If response type contains "token" or "id_token", then grant_type must contains "implicit"
-        if((responseType.contains(TOKEN)||responseType.contains(ID_TOKEN)) && !grantType.contains(IMPLICIT)) {
+        if(mustHaveImplicit(responseType) && !grantType.contains(IMPLICIT)) {
             grantType.add(IMPLICIT);
             updatedGrantType=true;
         }
 
         //If grant_type contains authorization_code, response_type must contains code
-        if(grantType.contains(AUTHORIZATION_CODE) && !responseType.contains(CODE)) {
+        if(grantType.contains(AUTHORIZATION_CODE) && !mustHaveAuthorizationCode(responseType)) {
             grantType.remove(AUTHORIZATION_CODE);
             updatedGrantType=true;
         }
 
         //If grant_type contains implicit, response_type must contains token or id_token
-        if(grantType.contains(IMPLICIT) && (!responseType.contains(TOKEN) && !responseType.contains(ID_TOKEN))) {
+        if(grantType.contains(IMPLICIT) && !mustHaveImplicit(responseType)) {
             grantType.remove(IMPLICIT);
             updatedGrantType=true;
         }
@@ -116,4 +116,18 @@ public class GrantTypeUtils {
 
         return client;
     }
+
+    private static boolean mustHaveAuthorizationCode(Set<String> responseType) {
+        return responseType.contains(CODE) ||
+                responseType.contains(CODE_TOKEN) ||
+                responseType.contains(CODE_ID_TOKEN) ||
+                responseType.contains(CODE_ID_TOKEN_TOKEN);
+    }
+
+    private static boolean mustHaveImplicit(Set<String> responseType) {
+        return responseType.contains(TOKEN) ||
+                responseType.contains(ID_TOKEN) ||
+                responseType.contains(CODE_TOKEN) ||
+                responseType.contains(CODE_ID_TOKEN_TOKEN);
+    }
 }
diff --git a/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/ResponseTypeUtils.java b/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/ResponseTypeUtils.java
index f16abb0857..ab8d62fc73 100644
--- a/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/ResponseTypeUtils.java
+++ b/gravitee-am-service/src/main/java/io/gravitee/am/service/utils/ResponseTypeUtils.java
@@ -33,7 +33,7 @@ import static io.gravitee.am.common.oidc.ResponseType.*;
 public class ResponseTypeUtils {
 
     private static final Set<String> VALID_RESPONSE_TYPES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
-            CODE, TOKEN, ID_TOKEN
+            CODE, TOKEN, ID_TOKEN, ID_TOKEN_TOKEN, CODE_TOKEN, CODE_ID_TOKEN, CODE_ID_TOKEN_TOKEN
     )));
 
     /**
diff --git a/postman/graviteeam-collection.json b/postman/graviteeam-collection.json
index c177acfb9d..24595a34b3 100644
--- a/postman/graviteeam-collection.json
+++ b/postman/graviteeam-collection.json
@@ -13638,7 +13638,7 @@
 													"    var body = pm.response.json();",
 													"    pm.expect(body).to.have.property(\"responseTypes\");",
 													"    pm.expect(body).to.have.property(\"authorizedGrantTypes\");",
-													"    pm.expect(body.responseTypes).to.eql(['token', 'code']);",
+													"    pm.expect(body.responseTypes).to.eql(['token', 'code', 'code token']);",
 													"    pm.expect(body.authorizedGrantTypes).to.eql([ 'implicit', 'authorization_code' ]);",
 													"});",
 													"",
@@ -13665,7 +13665,7 @@
 										],
 										"body": {
 											"mode": "raw",
-											"raw": "{\n   \"responseTypes\": [\"token\", \"code\"],\n   \"clientName\": \"Client was created via DCR\"\n  }"
+											"raw": "{\n   \"responseTypes\": [\"token\", \"code\", \"code token\"],\n   \"clientName\": \"Client was created via DCR\"\n  }"
 										},
 										"url": {
 											"raw": "{{management_url}}/management/domains/test/clients/{{newClientForDCRTests}}",
@@ -13700,7 +13700,7 @@
 													"    var body = pm.response.json();",
 													"    pm.expect(body).to.have.property(\"redirect_uris\");",
 													"    pm.expect(body).to.have.property(\"grant_types\");",
-													"    pm.expect(body.response_types).to.eql([ 'token','code' ]);",
+													"    pm.expect(body.response_types).to.eql([ 'token','code','code token' ]);",
 													"    pm.expect(body.grant_types).to.eql([ 'implicit','authorization_code' ]);",
 													"    pm.expect(body.client_name).to.eql('Client was created via DCR');",
 													"    ",
@@ -13756,6 +13756,8 @@
 													"    pm.response.to.be.header('Content-Type', 'application/json');",
 													"    var body = pm.response.json();",
 													"    pm.expect(body.client_name).to.eql('Client patched via DCR');",
+													"    pm.expect(body).to.have.property(\"response_types\");",
+													"    pm.expect(body.response_types).to.eql(['token', 'code', 'code id_token']);",
 													"});",
 													"",
 													"pm.test(\"One time Token\", function() {",
@@ -13786,7 +13788,7 @@
 										],
 										"body": {
 											"mode": "raw",
-											"raw": "{\n   \"client_name\": \"Client patched via DCR\"\n}"
+											"raw": "{\n   \"client_name\": \"Client patched via DCR\",\n   \"response_types\" : [\"token\", \"code\", \"code id_token\"]\n}"
 										},
 										"url": {
 											"raw": "{{registrationClientUri}}",
@@ -13813,6 +13815,8 @@
 													"    pm.response.to.be.header('Content-Type', 'application/json');",
 													"    var body = pm.response.json();",
 													"    pm.expect(body.client_name).to.eql('Client name updated via DCR');",
+													"    pm.expect(body).to.have.property(\"response_types\");",
+													"    pm.expect(body.response_types).to.eql(['code']);",
 													"});",
 													"",
 													"pm.test(\"One time Token\", function() {",


Test patch:
diff --git a/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/ResponseTypeUtilsTest.java b/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/ResponseTypeUtilsTest.java
index a3b14b6d1e..bed48757df 100644
--- a/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/ResponseTypeUtilsTest.java
+++ b/gravitee-am-service/src/test/java/io/gravitee/am/service/utils/ResponseTypeUtilsTest.java
@@ -34,13 +34,16 @@ public class ResponseTypeUtilsTest {
 
     @Test
     public void test_code_token_id_token() {
-        boolean isValid = ResponseTypeUtils.isValidResponseType(Arrays.asList("code", "token", "id_token"));
+        boolean isValid = ResponseTypeUtils.isValidResponseType(Arrays.asList(
+                "code", "token", "id_token",
+                "id_token token", "code token", "code id_token","code id_token token")
+        );
         assertTrue("Were expecting to be true",isValid);
     }
 
     @Test
     public void test_unknown_response_type() {
-        boolean isValid = ResponseTypeUtils.isValidResponseType(Arrays.asList("unknown"));
+        boolean isValid = ResponseTypeUtils.isValidResponseType(Arrays.asList("code token id_token"));
         assertFalse("Were expecting to be false",isValid);
     }