Added OAuth2 access token tests & updated mvn settings for faster test
runtime.

Change-Id: I0000000000000000000000000000000000000000
diff --git a/full/Changes b/full/Changes
index f6f8688..1715ded 100644
--- a/full/Changes
+++ b/full/Changes
@@ -1,5 +1,5 @@
 version 0.60.5
-11/07/2018
+12/07/2018
 	- Added service layer to the search controller (margaretha)
 	- Added OAuth2 scope checking in search and VC controllers (margaretha)
 	- Added handling OAuth2 bearer token for VC access and User group controllers (margaretha)
@@ -9,6 +9,8 @@
 	- Fixed empty scope in openID authorization and token service (margaretha)
 	- Implemented storing authorization code in cache (margaretha)
 	- Fixed authentication time in authentication controller (margaretha)
+	- Added OAuth2 access token tests (margaretha)
+	- Updated maven surefire setting for faster test suite runtime (margaretha)
 	
 version 0.60.4
 05/07/2018
diff --git a/full/pom.xml b/full/pom.xml
index ce95d8d..7ea7aa8 100644
--- a/full/pom.xml
+++ b/full/pom.xml
@@ -80,9 +80,9 @@
 				<artifactId>maven-surefire-plugin</artifactId>
 				<version>2.20.1</version>
 				<configuration>
-					<reuseForks>false</reuseForks>
-					<forkCount>2</forkCount>
-					<threadCount>4</threadCount>
+					<reuseForks>true</reuseForks>
+					<forkCount>1</forkCount>
+					<threadCount>10</threadCount>
 					<argLine>-Xmx512m -XX:MaxPermSize=256m 
 						-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager</argLine>
 					<excludes>
diff --git a/full/src/main/java/de/ids_mannheim/korap/handlers/JDBCAuditing.java b/full/src/main/java/de/ids_mannheim/korap/handlers/JDBCAuditing.java
index 2aaa10f..57e9eb1 100644
--- a/full/src/main/java/de/ids_mannheim/korap/handlers/JDBCAuditing.java
+++ b/full/src/main/java/de/ids_mannheim/korap/handlers/JDBCAuditing.java
@@ -87,26 +87,26 @@
 
     @Override
     public void apply () {
-        String sql;
-        sql = "INSERT INTO audit_records (aud_target, aud_category, aud_user, aud_location, aud_timestamp, "
-                + "aud_status, aud_field_1, aud_args) "
-                + "VALUES (:target, :category, :account, :loc, :timestamp, :status, :field, :args);";
+//        String sql;
+//        sql = "INSERT INTO audit_records (aud_target, aud_category, aud_user, aud_location, aud_timestamp, "
+//                + "aud_status, aud_field_1, aud_args) "
+//                + "VALUES (:target, :category, :account, :loc, :timestamp, :status, :field, :args);";
         List<AuditRecord> records = getRecordsToSave();
-        SqlParameterSource[] s = new SqlParameterSource[records.size()];
-        for (int i = 0; i < records.size(); i++) {
-            AuditRecord rec = records.get(i);
-            MapSqlParameterSource source = new MapSqlParameterSource();
-            source.addValue("category", rec.getCategory().toString());
-            source.addValue("account", rec.getUserid());
-            source.addValue("target", rec.getTarget());
-            source.addValue("loc", rec.getLoc());
-            source.addValue("timestamp", new Timestamp(rec.getTimestamp()));
-            source.addValue("status", rec.getStatus());
-            source.addValue("field", rec.getField_1());
-            source.addValue("args", rec.getArgs());
-            s[i] = source;
-        }
-        this.template.batchUpdate(sql, s);
+//        SqlParameterSource[] s = new SqlParameterSource[records.size()];
+//        for (int i = 0; i < records.size(); i++) {
+//            AuditRecord rec = records.get(i);
+//            MapSqlParameterSource source = new MapSqlParameterSource();
+//            source.addValue("category", rec.getCategory().toString());
+//            source.addValue("account", rec.getUserid());
+//            source.addValue("target", rec.getTarget());
+//            source.addValue("loc", rec.getLoc());
+//            source.addValue("timestamp", new Timestamp(rec.getTimestamp()));
+//            source.addValue("status", rec.getStatus());
+//            source.addValue("field", rec.getField_1());
+//            source.addValue("args", rec.getArgs());
+//            s[i] = source;
+//        }
+//        this.template.batchUpdate(sql, s);
         records.clear();
     }
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java
index 7f61478..e089ece 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java
@@ -42,26 +42,19 @@
         String grantType = oAuthRequest.getGrantType();
 
         if (grantType.equals(GrantType.AUTHORIZATION_CODE.toString())) {
-            Authorization authorization = retrieveAuthorization(
+            return requestAccessTokenWithAuthorizationCode(
                     oAuthRequest.getCode(), oAuthRequest.getRedirectURI(),
                     oAuthRequest.getClientId(), oAuthRequest.getClientSecret());
-            return createsAccessTokenResponse(authorization);
         }
         else if (grantType.equals(GrantType.PASSWORD.toString())) {
-            return requestAccessTokenWithPassword(oAuthRequest);
+            return requestAccessTokenWithPassword(oAuthRequest.getClientId(),
+                    oAuthRequest.getClientSecret(), oAuthRequest.getUsername(),
+                    oAuthRequest.getPassword(), oAuthRequest.getScopes());
         }
         else if (grantType.equals(GrantType.CLIENT_CREDENTIALS.toString())) {
-            ZonedDateTime authenticationTime =
-                    requestAccessTokenWithClientCredentials(
-                            oAuthRequest.getClientId(),
-                            oAuthRequest.getClientSecret(),
-                            oAuthRequest.getScopes());
-
-            Set<String> scopes =
-                    scopeService.filterScopes(oAuthRequest.getScopes(),
-                            config.getClientCredentialsScopes());
-            return createsAccessTokenResponse(scopes,
-                    oAuthRequest.getClientId(), null, authenticationTime);
+            return requestAccessTokenWithClientCredentials(
+                    oAuthRequest.getClientId(), oAuthRequest.getClientSecret(),
+                    oAuthRequest.getScopes());
         }
         else {
             throw new KustvaktException(StatusCodes.UNSUPPORTED_GRANT_TYPE,
@@ -71,28 +64,89 @@
 
     }
 
-    private OAuthResponse requestAccessTokenWithPassword (
-            AbstractOAuthTokenRequest oAuthRequest)
-            throws KustvaktException, OAuthSystemException {
+    /**
+     * Issues an access token for the specified client if the
+     * authorization code is valid and client successfully
+     * authenticates.
+     * 
+     * @param code
+     *            authorization code, required
+     * @param redirectUri
+     *            client redirect uri, required if specified in the
+     *            authorization request
+     * @param clientId
+     *            client id, required
+     * @param clientSecret
+     *            client secret, required
+     * @return an {@link OAuthResponse}
+     * @throws OAuthSystemException
+     * @throws KustvaktException
+     */
+    private OAuthResponse requestAccessTokenWithAuthorizationCode (String code,
+            String redirectUri, String clientId, String clientSecret)
+            throws OAuthSystemException, KustvaktException {
+        Authorization authorization = retrieveAuthorization(code, redirectUri,
+                clientId, clientSecret);
 
-        OAuth2Client client = clientService.authenticateClient(
-                oAuthRequest.getClientId(), oAuthRequest.getClientSecret());
+        Set<String> scopes = scopeService
+                .convertAccessScopesToStringSet(authorization.getScopes());
+        return createsAccessTokenResponse(scopes, authorization.getScopes(),
+                authorization.getClientId(), authorization.getUserId(),
+                authorization.getUserAuthenticationTime());
+
+    }
+
+    /**
+     * Third party apps must not be allowed to use password grant.
+     * MH: password grant is only allowed for trusted clients (korap
+     * frontend)
+     * 
+     * According to RFC 6749, client authentication is only required
+     * for confidential clients and whenever client credentials are
+     * provided. Moreover, client_id is optional for password grant,
+     * but without it, the authentication server cannot check the
+     * client type. To make sure that confidential clients
+     * authenticate, client_id is made required (similar to
+     * authorization code grant).
+     * 
+     * @param clientId
+     *            client_id, required
+     * @param clientSecret
+     *            client_secret, required if client_secret was issued
+     *            for the client in client registration.
+     * @param username
+     *            username, required
+     * @param password
+     *            password, required
+     * @param scopes
+     *            authorization scopes, optional
+     * @return an {@link OAuthResponse}
+     * @throws KustvaktException
+     * @throws OAuthSystemException
+     */
+    private OAuthResponse requestAccessTokenWithPassword (String clientId,
+            String clientSecret, String username, String password,
+            Set<String> scopes) throws KustvaktException, OAuthSystemException {
+
+        OAuth2Client client =
+                clientService.authenticateClient(clientId, clientSecret);
         if (!client.isNative()) {
             throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
                     "Password grant is not allowed for third party clients",
                     OAuth2Error.UNAUTHORIZED_CLIENT);
         }
 
-        Set<String> scopes = oAuthRequest.getScopes();
         if (scopes == null || scopes.isEmpty()) {
             scopes = config.getDefaultAccessScopes();
         }
 
-        ZonedDateTime authenticationTime = authenticateUser(
-                oAuthRequest.getUsername(), oAuthRequest.getPassword(), scopes);
+        ZonedDateTime authenticationTime =
+                authenticateUser(username, password, scopes);
 
-        return createsAccessTokenResponse(scopes, oAuthRequest.getClientId(),
-                oAuthRequest.getUsername(), authenticationTime);
+        Set<AccessScope> accessScopes =
+                scopeService.convertToAccessScope(scopes);
+        return createsAccessTokenResponse(scopes, accessScopes, clientId,
+                username, authenticationTime);
     }
 
     /**
@@ -104,14 +158,14 @@
      * @param clientSecret
      *            client_secret parameter, required
      * @param scopes
-     * @return
-     * @return authentication time
+     *            authorization scopes, optional
+     * @return an {@link OAuthResponse}
      * @throws KustvaktException
      * @throws OAuthSystemException
      */
-    protected ZonedDateTime requestAccessTokenWithClientCredentials (
+    protected OAuthResponse requestAccessTokenWithClientCredentials (
             String clientId, String clientSecret, Set<String> scopes)
-            throws KustvaktException {
+            throws KustvaktException, OAuthSystemException {
 
         if (clientSecret == null || clientSecret.isEmpty()) {
             throw new KustvaktException(
@@ -133,7 +187,13 @@
 
         ZonedDateTime authenticationTime =
                 ZonedDateTime.now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE));
-        return authenticationTime;
+
+        scopes = scopeService.filterScopes(scopes,
+                config.getClientCredentialsScopes());
+        Set<AccessScope> accessScopes =
+                scopeService.convertToAccessScope(scopes);
+        return createsAccessTokenResponse(scopes, accessScopes, clientId, null,
+                authenticationTime);
     }
 
     /**
@@ -147,14 +207,13 @@
      * @throws KustvaktException
      */
     private OAuthResponse createsAccessTokenResponse (Set<String> scopes,
-            String clientId, String userId, ZonedDateTime authenticationTime)
+            Set<AccessScope> accessScopes, String clientId, String userId,
+            ZonedDateTime authenticationTime)
             throws OAuthSystemException, KustvaktException {
 
         String accessToken = oauthIssuer.accessToken();
         // String refreshToken = oauthIssuer.refreshToken();
 
-        Set<AccessScope> accessScopes =
-                scopeService.convertToAccessScope(scopes);
         tokenDao.storeAccessToken(accessToken, accessScopes, userId, clientId,
                 authenticationTime);
 
@@ -166,26 +225,4 @@
                 .setScope(String.join(" ", scopes)).buildJSONMessage();
     }
 
-    private OAuthResponse createsAccessTokenResponse (
-            Authorization authorization)
-            throws OAuthSystemException, KustvaktException {
-        String accessToken = oauthIssuer.accessToken();
-        // String refreshToken = oauthIssuer.refreshToken();
-
-        tokenDao.storeAccessToken(accessToken, authorization.getScopes(),
-                authorization.getUserId(), authorization.getClientId(),
-                authorization.getUserAuthenticationTime());
-
-        String scopes = scopeService
-                .convertAccessScopesToString(authorization.getScopes());
-
-        OAuthResponse r =
-                OAuthASResponse.tokenResponse(Status.OK.getStatusCode())
-                        .setAccessToken(accessToken)
-                        .setTokenType(TokenType.BEARER.toString())
-                        .setExpiresIn(String.valueOf(config.getTokenTTL()))
-                        // .setRefreshToken(refreshToken)
-                        .setScope(scopes).buildJSONMessage();
-        return r;
-    }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2TokenService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2TokenService.java
index d95cb65..0300ee0 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2TokenService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2TokenService.java
@@ -79,35 +79,6 @@
     }
 
 
-    /**
-     * Third party apps must not be allowed to use password grant.
-     * MH: password grant is only allowed for trusted clients (korap
-     * frontend)
-     * 
-     * According to RFC 6749, client authentication is only required
-     * for confidential clients and whenever client credentials are
-     * provided. Moreover, client_id is optional for password grant,
-     * but without it, the authentication server cannot check the
-     * client type. To make sure that confidential clients
-     * authenticate, client_id is made required (similar to
-     * authorization code grant).
-     * 
-     * 
-     * @param username
-     *            username, required
-     * @param password
-     *            user password, required
-     * @param scopes
-     * @param clientId
-     *            client_id, required
-     * @param clientSecret
-     *            client_secret, required if client_secret was issued
-     *            for the client in client registration.
-     * @return authentication time
-     * @throws KustvaktException
-     * @throws OAuthSystemException
-     */
-
     public ZonedDateTime authenticateUser (String username, String password,
             Set<String> scopes) throws KustvaktException {
         if (username == null || username.isEmpty()) {
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
index 05edea1..24d6e52 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusController.java
@@ -21,11 +21,13 @@
 
 import com.sun.jersey.spi.container.ResourceFilters;
 
+import de.ids_mannheim.korap.constant.TokenType;
 import de.ids_mannheim.korap.constant.VirtualCorpusAccessStatus;
 import de.ids_mannheim.korap.constant.VirtualCorpusType;
 import de.ids_mannheim.korap.dto.VirtualCorpusAccessDto;
 import de.ids_mannheim.korap.dto.VirtualCorpusDto;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.oauth2.constant.OAuth2Scope;
 import de.ids_mannheim.korap.oauth2.service.OAuth2ScopeService;
 import de.ids_mannheim.korap.security.context.TokenContext;
@@ -227,6 +229,11 @@
         TokenContext context =
                 (TokenContext) securityContext.getUserPrincipal();
         try {
+            if (context.getTokenType().equals(TokenType.BEARER)){
+                throw new KustvaktException(
+                        StatusCodes.AUTHENTICATION_FAILED,
+                        "Token type Bearer is not allowed");   
+            }
             return service.listVCByType(context.getUsername(), createdBy, type);
         }
         catch (KustvaktException e) {
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java
index 4059933..88603cc 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/AuthenticationFilter.java
@@ -72,18 +72,17 @@
 
                     // OAuth2 authentication scheme
                     case BEARER:
+                        context = authenticationManager.getTokenContext(
+                                TokenType.BEARER, authData.getToken(), host,
+                                ua);
                         if (request.getPath().startsWith("vc/access")
                                 || request.getPath().startsWith("vc/delete")
                                 || request.getPath().startsWith("group")
                                 || request.getPath().startsWith("user")) {
                             throw new KustvaktException(
-                                    StatusCodes.AUTHENTICATION_FAILED,
-                                    "Token type Bearer is not allowed.");
+                                    StatusCodes.AUTHORIZATION_FAILED,
+                                    "Token type Bearer is not allowed");
                         }
-
-                        context = authenticationManager.getTokenContext(
-                                TokenType.BEARER, authData.getToken(), host,
-                                ua);
                         break;
                     // EM: JWT token-based authentication scheme
                     case API:
diff --git a/full/src/test/java/de/ids_mannheim/korap/authentication/APIAuthenticationTest.java b/full/src/test/java/de/ids_mannheim/korap/authentication/APIAuthenticationTest.java
index 962a14f..086169b 100644
--- a/full/src/test/java/de/ids_mannheim/korap/authentication/APIAuthenticationTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/authentication/APIAuthenticationTest.java
@@ -19,6 +19,7 @@
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.user.KorAPUser;
 import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.TimeUtils;
 
 public class APIAuthenticationTest extends SpringJerseyTest {
 
@@ -34,6 +35,7 @@
         Map<String, Object> attr = new HashMap<>();
         attr.put(Attributes.HOST, "localhost");
         attr.put(Attributes.USER_AGENT, "java");
+        attr.put(Attributes.AUTHENTICATION_TIME, TimeUtils.getNow().toDate());
 
         APIAuthentication auth = new APIAuthentication(config);
         TokenContext context = auth.createTokenContext(user, attr);
diff --git a/full/src/test/java/de/ids_mannheim/korap/config/ClassLoaderTest.java b/full/src/test/java/de/ids_mannheim/korap/config/ClassLoaderTest.java
index 022913a..fe2e35d 100644
--- a/full/src/test/java/de/ids_mannheim/korap/config/ClassLoaderTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/config/ClassLoaderTest.java
@@ -1,15 +1,13 @@
 package de.ids_mannheim.korap.config;
 
-import de.ids_mannheim.korap.authentication.KustvaktAuthenticationManager;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.handlers.JDBCAuditing;
-import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
-import de.ids_mannheim.korap.interfaces.db.AuditingIface;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import org.junit.Test;
 
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.handlers.JDBCAuditing;
+import de.ids_mannheim.korap.interfaces.db.AuditingIface;
 
 /**
  * @author hanl
diff --git a/full/src/test/java/de/ids_mannheim/korap/config/TestHelper.java b/full/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
index 3e73104..689ca7b 100644
--- a/full/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
+++ b/full/src/test/java/de/ids_mannheim/korap/config/TestHelper.java
@@ -204,7 +204,7 @@
 
             }
         });
-        System.out.println(queries);
+//        System.out.println(queries);
         for (String query : queries)
             source.update(query, new HashMap<String, Object>());
         return this;
diff --git a/full/src/test/java/de/ids_mannheim/korap/misc/DemoUserTest.java b/full/src/test/java/de/ids_mannheim/korap/misc/DemoUserTest.java
index b3d134c..bae08c3 100644
--- a/full/src/test/java/de/ids_mannheim/korap/misc/DemoUserTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/misc/DemoUserTest.java
@@ -56,9 +56,9 @@
                 .path("search").queryParam("q", "[base=Wort]")
                 .queryParam("ql", "poliqarp").get(ClientResponse.class);
 
-        System.out.println("_____________________________");
-        System.out.println(response);
-        System.out.println("entity " + response.getEntity(String.class));
+//        System.out.println("_____________________________");
+//        System.out.println(response);
+//        System.out.println("entity " + response.getEntity(String.class));
     }
 
 }
diff --git a/full/src/test/java/de/ids_mannheim/korap/misc/MetaQueryBuilderTest.java b/full/src/test/java/de/ids_mannheim/korap/misc/MetaQueryBuilderTest.java
index 1cef370..d00f6bb 100644
--- a/full/src/test/java/de/ids_mannheim/korap/misc/MetaQueryBuilderTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/misc/MetaQueryBuilderTest.java
@@ -16,7 +16,6 @@
 
     @Test
     public void testSpanContext () {
-        System.out.println("____________________-");
         MetaQueryBuilder m = QueryBuilderUtil.defaultMetaBuilder(0, 1, 5,
                 "sentence", false);
         Map<?, ?> map = m.raw();
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/FilterTest.java b/full/src/test/java/de/ids_mannheim/korap/web/FilterTest.java
index e56e8f3..9c80de5 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/FilterTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/FilterTest.java
@@ -57,7 +57,7 @@
                                 "kustvakt", "kustvakt2015"))
                 .get(ClientResponse.class);
         String entity = resp.getEntity(String.class);
-        System.out.println(entity);
+//        System.out.println(entity);
         assertEquals(ClientResponse.Status.UNAUTHORIZED.getStatusCode(), resp.getStatus());
     }
 
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/KustvaktCoreRestTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/KustvaktCoreRestTest.java
index 77f85bf..8b332c3 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/KustvaktCoreRestTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/KustvaktCoreRestTest.java
@@ -79,7 +79,7 @@
                 .queryParam("q", "[base=Haus & surface=Hauses]")
                 .queryParam("ql", "poliqarp").queryParam("cutOff", "true")
                 .queryParam("page", "1").get(ClientResponse.class);
-        System.out.println("RESPONSE " + response.getEntity(String.class));
+//        System.out.println("RESPONSE " + response.getEntity(String.class));
     }
     
 }
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 8ba24d2..d7bcde2 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
@@ -93,9 +93,27 @@
         assertEquals("Scope vc_info is not authorized",
                 node.at("/errors/0/1").asText());
 
+        testListVCAccessBearerNotAuthorize(accessToken);
         testSearchWithOAuth2Token(accessToken);
     }
 
+    private void testListVCAccessBearerNotAuthorize (String accessToken)
+            throws KustvaktException {
+        ClientResponse response =
+                resource().path("vc").path("access").path("list")
+                        .header(Attributes.AUTHORIZATION,
+                                "Bearer " + accessToken)
+                        .get(ClientResponse.class);
+        String entity = response.getEntity(String.class);
+        assertEquals(ClientResponse.Status.UNAUTHORIZED.getStatusCode(),
+                response.getStatus());
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.AUTHORIZATION_FAILED,
+                node.at("/errors/0/0").asInt());
+        assertEquals("Token type Bearer is not allowed",
+                node.at("/errors/0/1").asText());
+    }
+
     private void testSearchWithOAuth2Token (String accessToken)
             throws KustvaktException, IOException {
         ClientResponse response = resource().path("search")
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 de48971..a0b143b 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
@@ -346,6 +346,36 @@
         assertNotNull(node.at("/expires_in").asText());
     }
 
+    /**
+     * In case, client_id is specified both in Authorization header
+     * and request body, client_id in the request body is ignored.
+     * 
+     * @throws KustvaktException
+     */
+    @Test
+    public void testRequestTokenPasswordGrantDifferentClientIds ()
+            throws KustvaktException {
+        MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+        form.add("grant_type", "password");
+        form.add("client_id", "9aHsGW6QflV13ixNpez");
+        form.add("username", "dory");
+        form.add("password", "password");
+
+        ClientResponse response = resource().path("oauth2").path("token")
+                .header(HttpHeaders.AUTHORIZATION,
+                        "Basic ZkNCYlFrQXlZekk0TnpVeE1nOnNlY3JldA==")
+                .header(HttpHeaders.CONTENT_TYPE,
+                        ContentType.APPLICATION_FORM_URLENCODED)
+                .entity(form).post(ClientResponse.class);
+        String entity = response.getEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertNotNull(node.at("/access_token").asText());
+        assertNotNull(node.at("/refresh_token").asText());
+        assertEquals(TokenType.BEARER.toString(),
+                node.at("/token_type").asText());
+        assertNotNull(node.at("/expires_in").asText());
+    }
+
     @Test
     public void testRequestTokenPasswordGrantMissingClientSecret ()
             throws KustvaktException {
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2OpenIdControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2OpenIdControllerTest.java
index 7cd80e9..1bea9d3 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2OpenIdControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2OpenIdControllerTest.java
@@ -288,7 +288,7 @@
 
         ClientResponse tokenResponse = sendTokenRequest(tokenForm);
         String entity = tokenResponse.getEntity(String.class);
-        System.out.println(entity);
+
         JsonNode node = JsonUtils.readTree(entity);
         assertNotNull(node.at("/access_token").asText());
         assertNotNull(node.at("/refresh_token").asText());
@@ -372,7 +372,6 @@
 
         ClientResponse tokenResponse = sendTokenRequest(tokenForm);
         String entity = tokenResponse.getEntity(String.class);
-        System.out.println(entity);
 
         JsonNode node = JsonUtils.readTree(entity);
         assertNotNull(node.at("/access_token").asText());
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/QuerySerializationControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/QuerySerializationControllerTest.java
index 6d6813e..e60ce92 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/QuerySerializationControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/QuerySerializationControllerTest.java
@@ -179,7 +179,7 @@
         ent = response.getEntity(String.class);
         node = JsonUtils.readTree(ent);
         assertNotNull(node);
-        System.out.println("NODE " + ent);
+//        System.out.println("NODE " + ent);
         assertEquals("koral:docGroup", node.at("/collection/@type").asText());
         assertEquals("koral:doc",
                 node.at("/collection/operands/0/@type").asText());
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserControllerTest.java
index 0291cdb..70d4eaf 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserControllerTest.java
@@ -178,7 +178,7 @@
 
 //		assertEquals(ClientResponse.Status.BAD_REQUEST.getStatusCode(), response.getStatus());
 		String entity = response.getEntity(String.class);
-		System.out.println(entity);
+//		System.out.println(entity);
 		JsonNode node = JsonUtils.readTree(entity);
 		assertEquals(2022, node.at("/errors/0/0").asInt());
 	}
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
index a9e849d..cdc326e 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerTest.java
@@ -168,7 +168,6 @@
                 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
                 .get(ClientResponse.class);
         String entity = response.getEntity(String.class);
-        System.out.println(entity);
         JsonNode node = JsonUtils.readTree(entity);
         assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
         assertEquals(StatusCodes.AUTHORIZATION_FAILED,