Repository: gravitee-io/graviteeio-access-management (java)

Issue:
[oidc] [implicit] redirect_uri is required
https://openid.net/specs/openid-connect-core-1_0.html#ImplicitAuthRequest

Pull request description:
fix(oidc): redirect_uri parameter is required if client has no or mor…
…e than one registered redirect_uris

fixes #402

Patch:
diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/src/main/java/io/gravitee/am/gateway/handler/vertx/handler/oauth2/endpoint/authorization/AuthorizationClientHandler.java b/gravitee-am-gateway/gravitee-am-gateway-handler/src/main/java/io/gravitee/am/gateway/handler/vertx/handler/oauth2/endpoint/authorization/AuthorizationClientHandler.java
index 11e9dfb6d5..7e734ebd6a 100644
--- a/gravitee-am-gateway/gravitee-am-gateway-handler/src/main/java/io/gravitee/am/gateway/handler/vertx/handler/oauth2/endpoint/authorization/AuthorizationClientHandler.java
+++ b/gravitee-am-gateway/gravitee-am-gateway-handler/src/main/java/io/gravitee/am/gateway/handler/vertx/handler/oauth2/endpoint/authorization/AuthorizationClientHandler.java
@@ -107,7 +107,13 @@ public class AuthorizationClientHandler implements Handler<RoutingContext> {
         // if no requested redirect_uri and no registered client redirect_uris
         // throw invalid request exception
         if (!hasRegisteredClientRedirectUris && !hasRequestedRedirectUri) {
-            throw new InvalidRequestException("A redirect_uri must be supplied.");
+            throw new InvalidRequestException("A redirect_uri must be supplied");
+        }
+
+        // if no requested redirect_uri and more than one registered client redirect_uris
+        // throw invalid request exception
+        if (!hasRequestedRedirectUri && (registeredClientRedirectUris != null && registeredClientRedirectUris.size() > 1)) {
+            throw new InvalidRequestException("Unable to find suitable redirect_uri, a redirect_uri must be supplied");
         }
 
         // if requested redirect_uri doesn't match registered client redirect_uris


Test patch:
diff --git a/gravitee-am-gateway/gravitee-am-gateway-handler/src/test/java/io/gravitee/am/gateway/handler/vertx/endpoint/AuthorizationEndpointHandlerTest.java b/gravitee-am-gateway/gravitee-am-gateway-handler/src/test/java/io/gravitee/am/gateway/handler/vertx/endpoint/AuthorizationEndpointHandlerTest.java
index b68885f5a9..9a60bfa0e8 100644
--- a/gravitee-am-gateway/gravitee-am-gateway-handler/src/test/java/io/gravitee/am/gateway/handler/vertx/endpoint/AuthorizationEndpointHandlerTest.java
+++ b/gravitee-am-gateway/gravitee-am-gateway-handler/src/test/java/io/gravitee/am/gateway/handler/vertx/endpoint/AuthorizationEndpointHandlerTest.java
@@ -227,7 +227,34 @@ public class AuthorizationEndpointHandlerTest  extends RxWebTestBase {
                 resp -> {
                     String location = resp.headers().get("location");
                     assertNotNull(location);
-                    assertEquals("/test/oauth/error?error=invalid_request&error_description=A+redirect_uri+must+be+supplied.", location);
+                    assertEquals("/test/oauth/error?error=invalid_request&error_description=A+redirect_uri+must+be+supplied", location);
+                },
+                HttpStatusCode.FOUND_302, "Found", null);
+    }
+
+    @Test
+    public void shouldNotInvokeAuthorizationEndpoint_emptyRedirectUri_clientHasSeveralRedirectUris() throws Exception {
+        final Client client = new Client();
+        client.setId("client-id");
+        client.setClientId("client-id");
+        client.setScopes(Collections.singletonList("read"));
+        client.setRedirectUris(Arrays.asList("http://redirect1", "http://redirect2"));
+
+        AuthorizationRequest authorizationRequest = new AuthorizationRequest();
+        authorizationRequest.setApproved(true);
+        authorizationRequest.setResponseType(OAuth2Constants.CODE);
+
+        when(domain.getPath()).thenReturn("test");
+        when(clientService.findByClientId("client-id")).thenReturn(Maybe.just(client));
+
+        testRequest(
+                HttpMethod.GET,
+                "/oauth/authorize?response_type=code&client_id=client-id",
+                null,
+                resp -> {
+                    String location = resp.headers().get("location");
+                    assertNotNull(location);
+                    assertEquals("/test/oauth/error?error=invalid_request&error_description=Unable+to+find+suitable+redirect_uri%252C+a+redirect_uri+must+be+supplied", location);
                 },
                 HttpStatusCode.FOUND_302, "Found", null);
     }
@@ -739,8 +766,8 @@ public class AuthorizationEndpointHandlerTest  extends RxWebTestBase {
                 resp -> {
                     String location = resp.headers().get("location");
                     assertNotNull(location);
-                    assertEquals("/test/oauth/error?error=invalid_request&error_description=Missing+parameter%253A+nonce+is+required+for+Implicit+and+Hybrid+Flow", location);
-                },
+                    assertEquals("/test/oauth/error#error=invalid_request&error_description=Missing+parameter%253A+nonce+is+required+for+Implicit+and+Hybrid+Flow", location);
+                    },
                 HttpStatusCode.FOUND_302, "Found", null);
     }