Made scope param required in authorization request (solved #508)

Change-Id: I2fcf3f96af616567192442c454da6e7e19cbe4f4
diff --git a/full/Changes b/full/Changes
index 805109e..4dac86d 100644
--- a/full/Changes
+++ b/full/Changes
@@ -5,6 +5,8 @@
 2023-01-27
 - Updated client info API (replaced user authorization requirement with super 
   client authentication)
+2023-01-30
+- Made scope param required in authorization request (solved #508)
 
 
 # version 0.69.1
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2AuthorizationService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2AuthorizationService.java
index d2df86e..ff4565b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2AuthorizationService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2AuthorizationService.java
@@ -66,7 +66,8 @@
             throws KustvaktException {
 
         if (scopeSet == null || scopeSet.isEmpty()) {
-            scopeSet = config.getDefaultAccessScopes();
+            throw new KustvaktException(StatusCodes.MISSING_PARAMETER,
+                    "scope is required", OAuth2Error.INVALID_SCOPE);
         }
         Set<AccessScope> scopes = scopeService.convertToAccessScope(scopeSet);
 
diff --git a/full/src/test/java/de/ids_mannheim/korap/authentication/LdapOAuth2Test.java b/full/src/test/java/de/ids_mannheim/korap/authentication/LdapOAuth2Test.java
index 638e8b9..858b6cb 100644
--- a/full/src/test/java/de/ids_mannheim/korap/authentication/LdapOAuth2Test.java
+++ b/full/src/test/java/de/ids_mannheim/korap/authentication/LdapOAuth2Test.java
@@ -5,7 +5,9 @@
 import java.net.URI;
 import java.security.GeneralSecurityException;
 
-import javax.ws.rs.core.MediaType;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
@@ -20,9 +22,6 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.net.HttpHeaders;
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.client.Entity;
 import com.unboundid.ldap.sdk.LDAPException;
 
 import de.ids_mannheim.korap.config.Attributes;
@@ -176,6 +175,7 @@
                 .queryParam("response_type", "code")
                 .queryParam("client_id", clientId)
                 .queryParam("client_secret", clientSecret)
+                .queryParam("scope", "search match_info")
                 .request()
                 .header(Attributes.AUTHORIZATION, authHeader)
                 .get();
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AccessTokenTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AccessTokenTest.java
index ba2497f..935b819 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AccessTokenTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AccessTokenTest.java
@@ -243,7 +243,7 @@
         String userAuthToken = node.at("/access_token").asText();
 
         Response response = requestAuthorizationCode("code",
-                confidentialClientId, "", "", "", "Bearer " + userAuthToken);
+                confidentialClientId, "", "search", "", "Bearer " + userAuthToken);
 
         assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
 
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AuthorizationPostTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AuthorizationPostTest.java
index 67b5cbb..0427ac7 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AuthorizationPostTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AuthorizationPostTest.java
@@ -7,20 +7,19 @@
 
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
 import org.apache.oltu.oauth2.common.message.types.TokenType;
+import org.glassfish.jersey.uri.UriComponent;
 import org.junit.Test;
 import org.springframework.util.MultiValueMap;
 import org.springframework.web.util.UriComponentsBuilder;
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.net.HttpHeaders;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import org.glassfish.jersey.uri.UriComponent;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
@@ -55,6 +54,7 @@
         form.param("response_type", "code");
         form.param("client_id", confidentialClientId);
         form.param("state", "thisIsMyState");
+        form.param("scope", "search");
 
         Response response =
                 requestAuthorizationCode(form, userAuthHeader);
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java
index bfd0ad9..1a6d89f 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ControllerTest.java
@@ -10,8 +10,8 @@
 
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
@@ -22,7 +22,6 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.net.HttpHeaders;
-import javax.ws.rs.core.Response;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
@@ -73,7 +72,8 @@
     public void testAuthorizeWithRedirectUri () throws KustvaktException {
         Response response =
                 requestAuthorizationCode("code", publicClientId2,
-                        "https://public.com/redirect", "", "", userAuthHeader);
+                        "https://public.com/redirect", "search match_info", 
+                        "", userAuthHeader);
         assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
                 response.getStatus());
 
@@ -100,13 +100,13 @@
         assertEquals(redirectUri.getPath(), "/confidential/redirect");
 
         String[] queryParts = redirectUri.getQuery().split("&");
-        assertTrue(queryParts[0].startsWith("code="));
-        assertEquals(queryParts[1], "scope=match_info+search");
+        assertTrue(queryParts[0].startsWith("error_description=scope+is+required"));
+        assertEquals(queryParts[1], "error=invalid_scope");
     }
 
     @Test
     public void testAuthorizeMissingClientId () throws KustvaktException {
-        Response response = requestAuthorizationCode("code", "", "", "",
+        Response response = requestAuthorizationCode("code", "", "", "search",
                 "", userAuthHeader);
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         String entity = response.readEntity(String.class);
@@ -118,7 +118,7 @@
     @Test
     public void testAuthorizeMissingRedirectUri () throws KustvaktException {
         Response response = requestAuthorizationCode("code",
-                publicClientId2, "", "", state, userAuthHeader);
+                publicClientId2, "", "search", state, userAuthHeader);
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
 
         String entity = response.readEntity(String.class);
@@ -133,7 +133,7 @@
     @Test
     public void testAuthorizeMissingResponseType() throws KustvaktException {
         Response response = requestAuthorizationCode("",
-                confidentialClientId, "", "", "", userAuthHeader);
+                confidentialClientId, "", "search", "", userAuthHeader);
         assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
                 response.getStatus());
 
@@ -145,7 +145,7 @@
     @Test
     public void testAuthorizeMissingResponseTypeWithoutClientId () throws KustvaktException {
         Response response = requestAuthorizationCode("",
-                "", "", "", "", userAuthHeader);
+                "", "", "search", "", userAuthHeader);
         
         assertEquals(Status.BAD_REQUEST.getStatusCode(),
                 response.getStatus());
@@ -161,7 +161,7 @@
     @Test
     public void testAuthorizeInvalidClientId () throws KustvaktException {
         Response response = requestAuthorizationCode("code",
-                "unknown-client-id", "", "", "", userAuthHeader);
+                "unknown-client-id", "", "search", "", userAuthHeader);
         assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
         String entity = response.readEntity(String.class);
         JsonNode node = JsonUtils.readTree(entity);
@@ -174,7 +174,7 @@
     public void testAuthorizeDifferentRedirectUri () throws KustvaktException {
         String redirectUri = "https://different.uri/redirect";
         Response response = requestAuthorizationCode("code",
-                confidentialClientId, redirectUri, "", state, userAuthHeader);
+                confidentialClientId, redirectUri, "search", state, userAuthHeader);
         testInvalidRedirectUri(response.readEntity(String.class), true,
                 response.getStatus());
     }
@@ -184,7 +184,7 @@
             throws KustvaktException {
         Response response =
                 requestAuthorizationCode("code", publicClientId2,
-                        "http://localhost:1410", "", state, userAuthHeader);
+                        "http://localhost:1410", "search", state, userAuthHeader);
         testInvalidRedirectUri(response.readEntity(String.class), true,
                 response.getStatus());    }
 
@@ -192,7 +192,7 @@
     public void testAuthorizeWithRedirectUriFragment ()
             throws KustvaktException {
         Response response = requestAuthorizationCode("code",
-                publicClientId2, "http://public.com/index.html#redirect", "",
+                publicClientId2, "http://public.com/index.html#redirect", "search",
                 state, userAuthHeader);
         testInvalidRedirectUri(response.readEntity(String.class), true,
                 response.getStatus());
@@ -203,7 +203,7 @@
         // host not allowed by Apache URI Validator
         String redirectUri = "https://public.uri/redirect";
         Response response = requestAuthorizationCode("code",
-                publicClientId2, redirectUri, "", state, userAuthHeader);
+                publicClientId2, redirectUri, "search", state, userAuthHeader);
         testInvalidRedirectUri(response.readEntity(String.class), true,
                 response.getStatus());
     }
@@ -212,7 +212,7 @@
     public void testAuthorizeInvalidResponseType () throws KustvaktException {
         // without redirect URI in the request
         Response response = requestAuthorizationCode("string",
-                confidentialClientId, "", "", state, userAuthHeader);
+                confidentialClientId, "", "search", state, userAuthHeader);
         assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
                 response.getStatus());
 
@@ -278,7 +278,7 @@
     public void testAuthorizeUnsupportedTokenResponseType ()
             throws KustvaktException {
         Response response = requestAuthorizationCode("token",
-                confidentialClientId, "", "", state, userAuthHeader);
+                confidentialClientId, "", "search", state, userAuthHeader);
         assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
                 response.getStatus());
 
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2TestBase.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2TestBase.java
index 6006b74..a84f8f7 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2TestBase.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2TestBase.java
@@ -109,7 +109,7 @@
             String authHeader) throws KustvaktException {
 
         Response response = requestAuthorizationCode("code", clientId, "",
-                "", "", authHeader);
+                "search match_info", "", authHeader);
         assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
                 response.getStatus());
         URI redirectUri = response.getLocation();
@@ -122,7 +122,7 @@
     protected String requestAuthorizationCode (String clientId,
             String redirect_uri, String authHeader) throws KustvaktException {
         Response response = requestAuthorizationCode("code", clientId,
-                redirect_uri, "", "", authHeader);
+                redirect_uri, "search", "", authHeader);
         assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
                 response.getStatus());
         URI redirectUri = response.getLocation();