Merge branch 'jakarta-migration' into master

Change-Id: Ia2485c291d0fa21b58029919295d35d9993efa9a
diff --git a/full/Changes b/full/Changes
index c1f88e5..8d030e7 100644
--- a/full/Changes
+++ b/full/Changes
@@ -1,5 +1,24 @@
 # version 0.71.1
 
+- Replaced javax.ws to jakarta.ws namespace (#648)
+- Upgrading Jersey 2.40 to 3.x (#646)
+- Updated Spring 5.x to 6.x and jetty 9.x to 11.x (#645)
+- Replaced javax.persistence with jakarta.persistence (#648)
+- Migrate Hibernate 5 to 6 (#649)
+- Fix missing placeholders 
+- Fixed conflicting jackson-jarxrs
+- Fixed conflicting commons-logging and spring jcl
+- Replaced javax.servlet with jakarta.servlet (#648)
+- Updated authorization services using Nimbus (#650)
+- Fixed BlockingFilter by replacing javax.annotation.Priority 
+  with jakarta.annotation.Priority (#659, #648)
+- Replaced javax.annotation with jakarta.annotation
+- Enabled legacy support for authorization POST request
+- Changed OAuth2 token request using Nimbus (#650) 
+- Removed Apache Oltu API from token requests (#650)
+- Removed OpenID
+- Fixed clearing cache
+
 # version 0.71
 
 - Removed auditing (#611)
diff --git a/full/pom.xml b/full/pom.xml
index 4a77212..af78195 100644
--- a/full/pom.xml
+++ b/full/pom.xml
@@ -5,16 +5,17 @@
 	<artifactId>Kustvakt-full</artifactId>
 	<version>0.71.1</version>
 	<properties>
-		<java.version>11</java.version>
+		<java.version>17</java.version>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-		<jersey.version>2.40</jersey.version>
-		<hibernate.version>5.6.15.Final</hibernate.version>
-		<spring.version>5.3.29</spring.version>
-		<jetty.version>9.4.51.v20230217</jetty.version>
+		<jersey.version>3.1.3</jersey.version>
+		<hibernate.ehcache.version>6.0.0.Alpha7</hibernate.ehcache.version>
+		<hibernate.version>6.1.7.Final</hibernate.version>
+		<spring.version>6.0.11</spring.version>
+		<jetty.version>11.0.15</jetty.version>
 		<flyway.version>9.21.1</flyway.version>
 		<log4j.version>2.20.0</log4j.version>
-		<krill.version>0.61.3</krill.version>
-		<koral.version>0.41.0</koral.version>
+		<krill.version>[0.61.4,)</krill.version>
+		<koral.version>[0.41,)</koral.version>
 	</properties>
 	<profiles>
 		<profile>
@@ -158,6 +159,7 @@
 					<include>**/*.info</include>
 					<include>**/*.json</include>
 					<include>**/*.ldif</include>
+					<include>**/*.properties</include>
 				</includes>
 			</testResource>
 		</testResources>
@@ -252,7 +254,7 @@
 
 		<dependency>
 			<groupId>org.glassfish.jersey.ext</groupId>
-			<artifactId>jersey-spring5</artifactId>
+			<artifactId>jersey-spring6</artifactId>
 			<version>${jersey.version}</version>
 			<exclusions>
 				<exclusion>
@@ -283,7 +285,7 @@
 			<groupId>org.glassfish.jersey.media</groupId>
 			<artifactId>jersey-media-json-jackson</artifactId>
 			<version>${jersey.version}</version>
-			<exclusions>
+			<!--<exclusions>
 				<exclusion>
 					<groupId>com.fasterxml.jackson.core</groupId>
 					<artifactId>jackson-annotations</artifactId>
@@ -292,7 +294,7 @@
 					<groupId>com.fasterxml.jackson.core</groupId>
 					<artifactId>jackson-databind</artifactId>
 				</exclusion>
-			</exclusions>
+			</exclusions>-->
 		</dependency>
 		<dependency>
 			<groupId>net.minidev</groupId>
@@ -301,11 +303,17 @@
 		</dependency>
 		
 		<!-- Jersey 1x originally uses codehaus -->
-		<dependency>
+		<!--<dependency>
 			<groupId>com.fasterxml.jackson.jaxrs</groupId>
 			<artifactId>jackson-jaxrs-json-provider</artifactId>
 			<version>2.15.1</version>
 		</dependency>
+		<dependency>
+		    <groupId>com.fasterxml.jackson.jakarta.rs</groupId>
+		    <artifactId>jackson-jakarta-rs-json-provider</artifactId>
+		    <version>2.15.2</version>
+		</dependency>-->
+
 
 		<!-- Flyway -->
 		<dependency>
@@ -409,12 +417,24 @@
 			<groupId>org.apache.commons</groupId>
 			<artifactId>commons-dbcp2</artifactId>
 			<version>2.9.0</version>
+			<exclusions>
+				<exclusion>
+					<groupId>commons-logging</groupId>
+  					<artifactId>commons-logging</artifactId>
+				</exclusion>
+			</exclusions>
 		</dependency>
 
 		<dependency>
 			<groupId>commons-validator</groupId>
 			<artifactId>commons-validator</artifactId>
 			<version>1.7</version>
+			<exclusions>
+				<exclusion>
+					<groupId>commons-logging</groupId>
+  					<artifactId>commons-logging</artifactId>
+				</exclusion>
+			</exclusions>
 		</dependency>
 
 		<dependency>
@@ -423,11 +443,11 @@
 			<version>0.4</version>
 		</dependency>
 
-		<dependency>
+		<!--<dependency>
 		    <groupId>javax.annotation</groupId>
 		    <artifactId>javax.annotation-api</artifactId>
 		    <version>1.3.2</version>
-		</dependency>
+		</dependency>-->
 
 		<dependency>
 			<groupId>de.ids_mannheim.korap</groupId>
@@ -435,6 +455,10 @@
 			<version>${krill.version}</version>
 			<exclusions>
 				<exclusion>
+				    <groupId>com.fasterxml.jackson.jaxrs</groupId>
+      				<artifactId>jackson-jaxrs-json-provider</artifactId>
+				</exclusion>
+				<exclusion>
 					<groupId>org.glassfish.jersey.containers</groupId>
 					<artifactId>jersey-container-grizzly2-http</artifactId>
 				</exclusion>
@@ -578,6 +602,12 @@
 			<groupId>org.apache.httpcomponents</groupId>
 			<artifactId>httpclient</artifactId>
 			<version>4.5.14</version>
+			<exclusions>
+				<exclusion>
+					<groupId>commons-logging</groupId>
+  					<artifactId>commons-logging</artifactId>
+				</exclusion>
+			</exclusions>
 		</dependency>
 		<dependency>
 			<groupId>commons-io</groupId>
@@ -587,47 +617,60 @@
 
 		<!-- Hibernate -->
 		<dependency>
-			<groupId>org.hibernate</groupId>
-			<artifactId>hibernate-ehcache</artifactId>
+			<groupId>org.hibernate.orm</groupId>
+			<artifactId>hibernate-core</artifactId>
 			<version>${hibernate.version}</version>
 		</dependency>
 		<dependency>
-			<groupId>org.hibernate</groupId>
+			<groupId>org.hibernate.orm</groupId>
 			<artifactId>hibernate-jpamodelgen</artifactId>
 			<version>${hibernate.version}</version>
-			<scope>provided</scope>
 		</dependency>
 		<dependency>
-			<groupId>org.hibernate</groupId>
-			<artifactId>hibernate-entitymanager</artifactId>
-			<version>${hibernate.version}</version>
+			<groupId>org.hibernate.orm</groupId>
+			<artifactId>hibernate-ehcache</artifactId>
+			<version>${hibernate.ehcache.version}</version>
 			<exclusions>
 				<exclusion>
-					<groupId>org.javassist</groupId>
-					<artifactId>javassist</artifactId>
+					<groupId>org.hibernate</groupId>
+					<artifactId>hibernate-core</artifactId>
 				</exclusion>
 			</exclusions>
 		</dependency>
 		<dependency>
-			<groupId>org.hibernate</groupId>
-			<artifactId>hibernate-java8</artifactId>
-			<version>${hibernate.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>org.hibernate</groupId>
+			<groupId>org.hibernate.orm</groupId>
 			<artifactId>hibernate-c3p0</artifactId>
 			<version>${hibernate.version}</version>
 		</dependency>
 		
-		<!-- Sqlite -->
-		<dependency>
+		<!--<dependency>
 			<groupId>com.github.gwenn</groupId>
 			<artifactId>sqlite-dialect</artifactId>
 			<version>0.1.0</version>
+		</dependency>-->
+		<dependency>
+		    <groupId>org.hibernate.orm</groupId>
+		    <artifactId>hibernate-community-dialects</artifactId>
+		    <version>${hibernate.version}</version>
 		</dependency>
 		
 		<!-- servlet -->
 		<dependency>
+		    <groupId>jakarta.persistence</groupId>
+		    <artifactId>jakarta.persistence-api</artifactId>
+		    <version>3.1.0</version>
+		</dependency>
+
+		<!-- servlet -->
+		<dependency>
+		    <groupId>jakarta.servlet</groupId>
+		    <artifactId>jakarta.servlet-api</artifactId>
+		    <version>6.0.0</version>
+		    <scope>provided</scope>
+		</dependency>
+
+		<!-- needed by apache Oltu -->
+		<dependency>
 			<groupId>javax.servlet</groupId>
 			<artifactId>javax.servlet-api</artifactId>
 			<version>4.0.1</version>
@@ -696,13 +739,27 @@
 			<groupId>org.apache.velocity.tools</groupId>
 			<artifactId>velocity-tools-generic</artifactId>
 			<version>3.1</version>
+			<exclusions>
+				<exclusion>
+					<groupId>commons-logging</groupId>
+  					<artifactId>commons-logging</artifactId>
+				</exclusion>
+			</exclusions>
 		</dependency>
-		<!-- mail -->
+		
+		<!-- Mail -->
 		<dependency>
-			<groupId>com.sun.mail</groupId>
-			<artifactId>javax.mail</artifactId>
-			<version>1.6.2</version>
+		    <groupId>com.sun.mail</groupId>
+		    <artifactId>jakarta.mail</artifactId>
+		    <version>2.0.1</version>
 		</dependency>
+
+		<dependency>
+			<groupId>jakarta.activation</groupId>
+			<artifactId>jakarta.activation-api</artifactId>
+			<version>2.1.2</version>
+		</dependency>
+		
 		<dependency>
 			<groupId>javax.activation</groupId>
 			<artifactId>activation</artifactId>
@@ -720,14 +777,8 @@
 			<artifactId>org.apache.oltu.oauth2.client</artifactId>
 			<version>1.0.2</version>
 		</dependency>
-		<!-- JWT -->
-		<dependency>
-			<groupId>com.nimbusds</groupId>
-			<artifactId>nimbus-jose-jwt</artifactId>
-			<version>9.31</version>
-		</dependency>
 
-		<!-- OpenId -->
+		<!-- Nimbus -->
 		<dependency>
 			<groupId>com.nimbusds</groupId>
 			<artifactId>oauth2-oidc-sdk</artifactId>
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/APIAuthentication.java b/full/src/main/java/de/ids_mannheim/korap/authentication/APIAuthentication.java
index 341c4d0..ef9db77 100644
--- a/full/src/main/java/de/ids_mannheim/korap/authentication/APIAuthentication.java
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/APIAuthentication.java
@@ -20,8 +20,6 @@
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.user.User;
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
 
 /**
  * Authentication provider using JWT tokens
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/AuthenticationManager.java b/full/src/main/java/de/ids_mannheim/korap/authentication/AuthenticationManager.java
index 5b4f9c8..f11aa52 100644
--- a/full/src/main/java/de/ids_mannheim/korap/authentication/AuthenticationManager.java
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/AuthenticationManager.java
@@ -4,14 +4,13 @@
 import java.util.Map;
 import java.util.Set;
 
-import javax.ws.rs.core.HttpHeaders;
-
 import de.ids_mannheim.korap.config.KustvaktCacheable;
 import de.ids_mannheim.korap.constant.AuthenticationMethod;
 import de.ids_mannheim.korap.constant.TokenType;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.user.User;
+import jakarta.ws.rs.core.HttpHeaders;
 
 /**
  * @author hanl
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/DummyAuthenticationManager.java b/full/src/main/java/de/ids_mannheim/korap/authentication/DummyAuthenticationManager.java
index 306bf95..5934667 100644
--- a/full/src/main/java/de/ids_mannheim/korap/authentication/DummyAuthenticationManager.java
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/DummyAuthenticationManager.java
@@ -2,8 +2,6 @@
 
 import java.util.Map;
 
-import javax.ws.rs.core.HttpHeaders;
-
 import org.springframework.beans.factory.annotation.Autowired;
 
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
@@ -14,6 +12,7 @@
 import de.ids_mannheim.korap.user.KorAPUser;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.utils.TimeUtils;
+import jakarta.ws.rs.core.HttpHeaders;
 
 public class DummyAuthenticationManager extends AuthenticationManager {
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java b/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
index a4179eb..590fb9f 100644
--- a/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
+++ b/full/src/main/java/de/ids_mannheim/korap/authentication/KustvaktAuthenticationManager.java
@@ -5,9 +5,6 @@
 import java.util.Arrays;
 import java.util.Map;
 
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MultivaluedMap;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.eclipse.jetty.http.HttpHeader;
@@ -37,6 +34,8 @@
 import de.ids_mannheim.korap.user.User.Location;
 import de.ids_mannheim.korap.utils.TimeUtils;
 import de.ids_mannheim.korap.validator.Validator;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MultivaluedMap;
 
 /**
  * contains the logic to authentication and registration processes. Uses
@@ -291,7 +290,7 @@
 		String eppn = (String) attributes.get(Attributes.EPPN);
 
 		if (eppn == null || eppn.isEmpty())
-			throw new KustvaktException(StatusCodes.REQUEST_INVALID);
+			throw new KustvaktException(StatusCodes.INVALID_REQUEST);
 
 		if (!attributes.containsKey(Attributes.EMAIL) && validator.isValid(eppn, Attributes.EMAIL))
 			attributes.put(Attributes.EMAIL, eppn);
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/Attributes.java b/full/src/main/java/de/ids_mannheim/korap/config/Attributes.java
index a3e2433..e2e4ed5 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/Attributes.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/Attributes.java
@@ -2,17 +2,14 @@
 
 public class Attributes {
 
-    // EM: openid auth_time
     public static final String AUTHENTICATION_TIME = "auth_time";
     public static final String DEFAULT_TIME_ZONE = "Europe/Berlin";
-    // -- EM
     
     public static final String AUTHORIZATION = "Authorization";
     // moved to de.ids_mannheim.korap.config.AuthenticationScheme
 //    public static final String SESSION_AUTHENTICATION = "session_token";
 //    public static final String API_AUTHENTICATION = "api_token";
 //    public static final String OAUTH2_AUTHORIZATION = "bearer";
-//    public static final String OPENID_AUTHENTICATION = "id_token";
 //    public static final String BASIC_AUTHENTICATION = "basic";
 
     public static final String LOCATION = "location"; // location of Client: User.INTERN/EXTERN
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java b/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
index a752399..a1ba12f 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/FullConfiguration.java
@@ -1,15 +1,7 @@
 package de.ids_mannheim.korap.config;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
 import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URISyntaxException;
 import java.net.URL;
-import java.nio.charset.Charset;
-import java.security.interfaces.RSAPrivateKey;
-import java.text.ParseException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -21,15 +13,8 @@
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-import com.nimbusds.jose.JOSEException;
-import com.nimbusds.jose.jwk.JWK;
-import com.nimbusds.jose.jwk.JWKSet;
-import com.nimbusds.jose.jwk.RSAKey;
-import com.nimbusds.jose.util.IOUtils;
-
 import de.ids_mannheim.korap.constant.AuthenticationMethod;
 import de.ids_mannheim.korap.interfaces.EncryptionIface;
-import de.ids_mannheim.korap.oauth2.openid.OpenIdConfiguration;
 import de.ids_mannheim.korap.utils.TimeUtils;
 
 /**
@@ -70,7 +55,6 @@
 
     private AuthenticationMethod OAuth2passwordAuthentication;
     private String nativeClientHost;
-    private Set<String> defaultAccessScopes;
     private Set<String> clientCredentialsScopes;
     private int maxAuthenticationAttempts;
 
@@ -83,12 +67,6 @@
     private int maxNumberOfUserQueries;
     
     private URL issuer;
-    private URI issuerURI;
-    private OpenIdConfiguration openidConfig;
-
-    private RSAPrivateKey rsaPrivateKey;
-    private JWKSet publicKeySet;
-    private String rsaKeyId;
 
     private String namedVCPath;
     
@@ -117,8 +95,6 @@
 
         setSecurityConfiguration(properties);
         setOAuth2Configuration(properties);
-        setOpenIdConfiguration(properties);
-        setRSAKeys(properties);
 
         setNamedVCPath(properties.getProperty("krill.namedVC", ""));
         
@@ -133,14 +109,11 @@
                 properties.getProperty("max.user.persistent.queries", "20")));
     }
 
-    private void setSecurityConfiguration (Properties properties) {
+    private void setSecurityConfiguration (Properties properties) throws MalformedURLException {
         setSecureHashAlgorithm(Enum.valueOf(EncryptionIface.Encryption.class,
                 properties.getProperty("security.secure.hash.algorithm",
                         "BCRYPT")));
-    }
-
-    private void setOpenIdConfiguration (Properties properties)
-            throws URISyntaxException, MalformedURLException {
+        
         String issuerStr = properties.getProperty("security.jwt.issuer",
                 "https://korap.ids-mannheim.de");
 
@@ -148,99 +121,6 @@
             issuerStr = "http://" + issuerStr;
         }
         setIssuer(new URL(issuerStr));
-        setIssuerURI(issuer.toURI());
-
-        issuerStr = issuerURI.toString();
-
-        OpenIdConfiguration openidConfig = new OpenIdConfiguration();
-        openidConfig.setIssuer(issuerStr);
-        openidConfig.setJwks_uri(issuerStr + OpenIdConfiguration.JWKS_ENDPOINT);
-        openidConfig.setRegistration_endpoint(
-                issuerStr + OpenIdConfiguration.CLIENT_REGISTRATION_ENDPOINT);
-        openidConfig.setAuthorization_endpoint(
-                issuerStr + OpenIdConfiguration.AUTHORIZATION_ENDPOINT);
-        openidConfig.setToken_endpoint(
-                issuerStr + OpenIdConfiguration.TOKEN_ENDPOINT);
-
-        String grantTypes = properties.getProperty("openid.grant.types", "");
-        openidConfig.setGrant_types_supported(grantTypes.split(" "));
-
-        String responseTypes =
-                properties.getProperty("openid.response.types", "code");
-        openidConfig.setResponse_types_supported(responseTypes.split(" "));
-
-        String responseModes =
-                properties.getProperty("openid.response.modes", "");
-        openidConfig.setResponse_modes_supported(responseModes.split(" "));
-
-        String clientAuthMethods =
-                properties.getProperty("openid.client.auth.methods", "");
-        openidConfig.setToken_endpoint_auth_methods_supported(
-                clientAuthMethods.split(" "));
-
-        String tokenSigningAlgorithms = properties
-                .getProperty("openid.token.signing.algorithms", "RS256");
-        openidConfig.setToken_endpoint_auth_signing_alg_values_supported(
-                tokenSigningAlgorithms.split(" "));
-
-        String subjectTypes =
-                properties.getProperty("openid.subject.types", "public");
-        openidConfig.setSubject_types_supported(subjectTypes.split(" "));
-
-        String displayTypes =
-                properties.getProperty("openid.display.types", "");
-        openidConfig.setDisplay_values_supported(displayTypes.split(" "));
-
-        String supportedScopes =
-                properties.getProperty("openid.supported.scopes", "");
-        openidConfig.setScopes_supported(supportedScopes.split(" "));
-
-        String claimTypes =
-                properties.getProperty("openid.claim.types", "normal");
-        openidConfig.setClaim_types_supported(claimTypes.split(" "));
-
-        String supportedClaims =
-                properties.getProperty("openid.supported.claims", "");
-        openidConfig.setClaims_supported(supportedClaims.split(" "));
-
-        String claimLocales =
-                properties.getProperty("openid.supported.claim.locales", "");
-        openidConfig.setClaims_locales_supported(claimLocales.split(" "));
-
-        String uiLocales = properties.getProperty("openid.ui.locales", "en");
-        openidConfig.setUi_locales_supported(uiLocales.split(" "));
-
-        boolean supportClaimParam = Boolean.getBoolean(
-                properties.getProperty("openid.support.claim.param", "false"));
-        openidConfig.setClaims_parameter_supported(supportClaimParam);
-
-        openidConfig.setRequest_parameter_supported(false);
-        openidConfig.setRequest_uri_parameter_supported(false);
-        openidConfig.setRequire_request_uri_registration(false);
-        openidConfig.setMutual_tls_sender_constrained_access_tokens(false);
-
-        String privacyPolicy =
-                properties.getProperty("openid.privacy.policy", "");
-        openidConfig.setOp_policy_uri(privacyPolicy);
-
-        String termOfService =
-                properties.getProperty("openid.term.of.service", "");
-        openidConfig.setOp_tos_uri(termOfService);
-
-        String serviceDocURL = properties.getProperty("openid.service.doc", "");
-        openidConfig.setService_documentation(serviceDocURL);
-        this.setOpenidConfig(openidConfig);
-    }
-
-    private void setRSAKeys (Properties properties)
-            throws IOException, ParseException, JOSEException {
-        setRsaKeyId(properties.getProperty("rsa.key.id", ""));
-
-        String rsaPublic = properties.getProperty("rsa.public", null);
-        setPublicKeySet(rsaPublic);
-
-        String rsaPrivate = properties.getProperty("rsa.private", null);
-        setRsaPrivateKey(rsaPrivate);
     }
 
     private void setOAuth2Configuration (Properties properties) {
@@ -255,12 +135,6 @@
         setMaxAuthenticationAttempts(Integer
                 .parseInt(properties.getProperty("oauth2.max.attempts", "1")));
 
-        String scopes = properties.getProperty("oauth2.default.scopes",
-                "openid preferred_username");
-        Set<String> scopeSet =
-                Arrays.stream(scopes.split(" ")).collect(Collectors.toSet());
-        setDefaultAccessScopes(scopeSet);
-
         String clientScopes = properties
                 .getProperty("oauth2.client.credentials.scopes", "client_info");
         setClientCredentialsScopes(Arrays.stream(clientScopes.split(" "))
@@ -534,14 +408,6 @@
         this.maxAuthenticationAttempts = maxAuthenticationAttempts;
     }
 
-    public Set<String> getDefaultAccessScopes () {
-        return defaultAccessScopes;
-    }
-
-    public void setDefaultAccessScopes (Set<String> accessScopes) {
-        this.defaultAccessScopes = accessScopes;
-    }
-
     public Set<String> getClientCredentialsScopes () {
         return clientCredentialsScopes;
     }
@@ -559,78 +425,6 @@
         this.issuer = issuer;
     }
 
-    public URI getIssuerURI () {
-        return issuerURI;
-    }
-
-    public void setIssuerURI (URI issuerURI) {
-        this.issuerURI = issuerURI;
-    }
-
-    public JWKSet getPublicKeySet () {
-        return publicKeySet;
-    }
-
-    public void setPublicKeySet (String rsaPublic)
-            throws IOException, ParseException {
-        if (rsaPublic == null || rsaPublic.isEmpty()) {
-            return;
-        }
-
-        File rsaPublicFile = new File(rsaPublic);
-        JWKSet jwkSet = null;
-        InputStream is = null;
-        if (rsaPublicFile.exists()) {
-            jwkSet = JWKSet.load(rsaPublicFile);
-        }
-        else if ((is = getClass().getClassLoader()
-                .getResourceAsStream(rsaPublic)) != null) {
-            jwkSet = JWKSet.load(is);
-        }
-        this.publicKeySet = jwkSet;
-    }
-
-    public RSAPrivateKey getRsaPrivateKey () {
-        return rsaPrivateKey;
-    }
-
-    public void setRsaPrivateKey (String rsaPrivate)
-            throws IOException, ParseException, JOSEException {
-        if (rsaPrivate == null || rsaPrivate.isEmpty()) {
-            return;
-        }
-        File rsaPrivateFile = new File(rsaPrivate);
-        String keyString = null;
-        InputStream is = null;
-        if (rsaPrivateFile.exists()) {
-            keyString = IOUtils.readFileToString(rsaPrivateFile,
-                    Charset.forName("UTF-8"));
-        }
-        else if ((is = getClass().getClassLoader()
-                .getResourceAsStream(rsaPrivate)) != null) {
-            keyString = IOUtils.readInputStreamToString(is,
-                    Charset.forName("UTF-8"));
-        }
-        RSAKey rsaKey = (RSAKey) JWK.parse(keyString);
-        this.rsaPrivateKey = (RSAPrivateKey) rsaKey.toPrivateKey();
-    }
-
-    public String getRsaKeyId () {
-        return rsaKeyId;
-    }
-
-    public void setRsaKeyId (String rsaKeyId) {
-        this.rsaKeyId = rsaKeyId;
-    }
-
-    public OpenIdConfiguration getOpenidConfig () {
-        return openidConfig;
-    }
-
-    public void setOpenidConfig (OpenIdConfiguration openidConfig) {
-        this.openidConfig = openidConfig;
-    }
-
     public int getAccessTokenExpiry () {
         return accessTokenExpiry;
     }
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java b/full/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java
index 21f3921..63ec65e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/JWTSigner.java
@@ -179,7 +179,7 @@
         try {
             jwt = SignedJWT.parse(signedContent);
             if (!jwt.verify(verifier))
-                throw new KustvaktException(StatusCodes.REQUEST_INVALID,
+                throw new KustvaktException(StatusCodes.INVALID_REQUEST,
                         "token invalid", signedContent);
             return jwt.getJWTClaimsSet().getStringClaim("data");
         }
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java b/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java
index 410a58a..f16acbf 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/NamedVCLoader.java
@@ -7,8 +7,6 @@
 import java.util.Arrays;
 import java.util.zip.GZIPInputStream;
 
-import javax.management.RuntimeErrorException;
-
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.output.ByteArrayOutputStream;
@@ -61,7 +59,7 @@
         }
         catch (IOException | QueryException e) {
 //            e.printStackTrace();
-            throw new RuntimeErrorException(new Error(e.getMessage(), e.getCause()));
+            throw new RuntimeException(e.getMessage(), e.getCause());
         }
     }
     
diff --git a/full/src/main/java/de/ids_mannheim/korap/config/Scopes.java b/full/src/main/java/de/ids_mannheim/korap/config/Scopes.java
index 20e5627..161d5f6 100644
--- a/full/src/main/java/de/ids_mannheim/korap/config/Scopes.java
+++ b/full/src/main/java/de/ids_mannheim/korap/config/Scopes.java
@@ -16,7 +16,7 @@
 public class Scopes {
 
     public enum Scope {
-        openid, profile, email, queries, account, preferences, search
+        profile, email, queries, account, preferences, search
 
     }
 
@@ -25,8 +25,6 @@
             Attributes.ADDRESS, Attributes.PHONE, Attributes.GENDER,
             Attributes.COUNTRY };
 
-    private static final String[] OPENID_CONNECT = { Scope.profile.toString() };
-
     private static final Enum[] SERVICE_DEFAULTS = { Scope.account,
             Scope.preferences, Scope.search, Scope.queries };
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/constant/OAuth2Scope.java b/full/src/main/java/de/ids_mannheim/korap/constant/OAuth2Scope.java
index 5055972..ee6a09b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/constant/OAuth2Scope.java
+++ b/full/src/main/java/de/ids_mannheim/korap/constant/OAuth2Scope.java
@@ -11,7 +11,6 @@
     @Deprecated
     ADMIN,
     
-    OPENID, 
     AUTHORIZE,
     
     LIST_USER_CLIENT,
diff --git a/full/src/main/java/de/ids_mannheim/korap/constant/TokenType.java b/full/src/main/java/de/ids_mannheim/korap/constant/TokenType.java
index 76bac5b..bd4ad76 100644
--- a/full/src/main/java/de/ids_mannheim/korap/constant/TokenType.java
+++ b/full/src/main/java/de/ids_mannheim/korap/constant/TokenType.java
@@ -13,8 +13,6 @@
  */
 public enum TokenType {
     BASIC, API, SESSION, 
-    // openid token, e.g. within oauth2 response (json body)
-    ID_TOKEN,
     // OAuth2 access_token
     BEARER,
     // OAuth2 client
diff --git a/full/src/main/java/de/ids_mannheim/korap/core/entity/Annotation.java b/full/src/main/java/de/ids_mannheim/korap/core/entity/Annotation.java
index fe723fc..f29cac9 100644
--- a/full/src/main/java/de/ids_mannheim/korap/core/entity/Annotation.java
+++ b/full/src/main/java/de/ids_mannheim/korap/core/entity/Annotation.java
@@ -1,12 +1,11 @@
 package de.ids_mannheim.korap.core.entity;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Table;
-
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
 import lombok.Getter;
 import lombok.Setter;
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/core/entity/AnnotationKey.java b/full/src/main/java/de/ids_mannheim/korap/core/entity/AnnotationKey.java
index f94c715..d4184a4 100644
--- a/full/src/main/java/de/ids_mannheim/korap/core/entity/AnnotationKey.java
+++ b/full/src/main/java/de/ids_mannheim/korap/core/entity/AnnotationKey.java
@@ -2,19 +2,18 @@
 
 import java.util.Set;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
-
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
 import lombok.Getter;
 import lombok.Setter;
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/core/entity/AnnotationLayer.java b/full/src/main/java/de/ids_mannheim/korap/core/entity/AnnotationLayer.java
index 3160cef..06caf6a 100644
--- a/full/src/main/java/de/ids_mannheim/korap/core/entity/AnnotationLayer.java
+++ b/full/src/main/java/de/ids_mannheim/korap/core/entity/AnnotationLayer.java
@@ -2,22 +2,21 @@
 
 import java.util.Set;
 
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
-
 import org.hibernate.annotations.Fetch;
 import org.hibernate.annotations.FetchMode;
 
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
 import lombok.Getter;
 import lombok.Setter;
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/core/entity/Resource.java b/full/src/main/java/de/ids_mannheim/korap/core/entity/Resource.java
index 1f26d7f..99c572b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/core/entity/Resource.java
+++ b/full/src/main/java/de/ids_mannheim/korap/core/entity/Resource.java
@@ -2,15 +2,14 @@
 
 import java.util.Set;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
-import javax.persistence.Table;
-
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.Table;
 import lombok.Getter;
 import lombok.Setter;
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/core/service/SearchService.java b/full/src/main/java/de/ids_mannheim/korap/core/service/SearchService.java
index ce383e8..c940cab 100644
--- a/full/src/main/java/de/ids_mannheim/korap/core/service/SearchService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/core/service/SearchService.java
@@ -10,12 +10,6 @@
 import java.util.Set;
 import java.util.regex.Pattern;
 
-import javax.annotation.PostConstruct;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MultivaluedHashMap;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.UriBuilder;
-
 import org.apache.http.HttpStatus;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -41,6 +35,11 @@
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.web.ClientsHandler;
 import de.ids_mannheim.korap.web.SearchKrill;
+import jakarta.annotation.PostConstruct;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.UriBuilder;
 
 @Service
 public class SearchService extends BasicService{
diff --git a/full/src/main/java/de/ids_mannheim/korap/core/web/controller/AnnotationController.java b/full/src/main/java/de/ids_mannheim/korap/core/web/controller/AnnotationController.java
index 26d51dc..c337c5e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/core/web/controller/AnnotationController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/core/web/controller/AnnotationController.java
@@ -3,18 +3,11 @@
 import java.io.IOException;
 import java.util.List;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
 import com.fasterxml.jackson.databind.JsonNode;
-import de.ids_mannheim.korap.web.utils.ResourceFilters;
+
 import de.ids_mannheim.korap.core.service.AnnotationService;
 import de.ids_mannheim.korap.dto.FoundryDto;
 import de.ids_mannheim.korap.dto.LayerDto;
@@ -25,6 +18,13 @@
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
+import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
 
 /**
  * Provides services regarding annotation related information.
diff --git a/full/src/main/java/de/ids_mannheim/korap/core/web/controller/SearchController.java b/full/src/main/java/de/ids_mannheim/korap/core/web/controller/SearchController.java
index acddf23..7e4ed94 100644
--- a/full/src/main/java/de/ids_mannheim/korap/core/web/controller/SearchController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/core/web/controller/SearchController.java
@@ -8,28 +8,11 @@
 import java.util.Map;
 import java.util.Set;
 
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
-import de.ids_mannheim.korap.web.utils.ResourceFilters;
-import de.ids_mannheim.korap.web.utils.SearchResourceFilters;
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.constant.OAuth2Scope;
 import de.ids_mannheim.korap.core.service.SearchService;
@@ -44,6 +27,22 @@
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
+import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import de.ids_mannheim.korap.web.utils.SearchResourceFilters;
+import jakarta.servlet.ServletContext;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.ws.rs.DefaultValue;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * 
diff --git a/full/src/main/java/de/ids_mannheim/korap/core/web/controller/StatisticController.java b/full/src/main/java/de/ids_mannheim/korap/core/web/controller/StatisticController.java
index c053d45..30ccaa4 100644
--- a/full/src/main/java/de/ids_mannheim/korap/core/web/controller/StatisticController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/core/web/controller/StatisticController.java
@@ -3,28 +3,27 @@
 import java.util.List;
 import java.util.Locale;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
-import de.ids_mannheim.korap.web.utils.ResourceFilters;
 import de.ids_mannheim.korap.core.service.StatisticService;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.web.CoreResponseHandler;
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
+import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * Web services related to statistics
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/AdminDaoImpl.java b/full/src/main/java/de/ids_mannheim/korap/dao/AdminDaoImpl.java
index 54cab51..172ac69 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/AdminDaoImpl.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/AdminDaoImpl.java
@@ -1,20 +1,18 @@
 package de.ids_mannheim.korap.dao;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
-
 import org.springframework.stereotype.Repository;
-import org.springframework.transaction.annotation.Transactional;
 
 import de.ids_mannheim.korap.entity.Admin;
 import de.ids_mannheim.korap.entity.Admin_;
 import de.ids_mannheim.korap.user.User;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
 
 /**
  * Describes database queries and transactions regarding admin users.
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java
index 43b7fd0..0ebfe42 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/AnnotationDao.java
@@ -2,15 +2,6 @@
 
 import java.util.List;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
-
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -23,6 +14,14 @@
 import de.ids_mannheim.korap.core.entity.Annotation_;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.ParameterChecker;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
 
 /**
  * AnnotationDao manages queries to database regarding annotations including
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/DefaultSettingDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/DefaultSettingDao.java
index 858b7c7..f99990e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/DefaultSettingDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/DefaultSettingDao.java
@@ -1,13 +1,5 @@
 package de.ids_mannheim.korap.dao;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Root;
-
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -15,6 +7,13 @@
 import de.ids_mannheim.korap.entity.DefaultSetting_;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.ParameterChecker;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Root;
 
 /**
  * DefaultSettingDao manages database queries and transactions
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/PrivilegeDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/PrivilegeDao.java
index 9bdb351..f9c05e6 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/PrivilegeDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/PrivilegeDao.java
@@ -2,13 +2,6 @@
 
 import java.util.List;
 
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Root;
-
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -17,6 +10,12 @@
 import de.ids_mannheim.korap.entity.Privilege_;
 import de.ids_mannheim.korap.entity.Role;
 import de.ids_mannheim.korap.entity.Role_;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Root;
 
 /**
  * Manages database queries and transactions regarding
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/QueryAccessDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/QueryAccessDao.java
index f28c4ee..d341f38 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/QueryAccessDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/QueryAccessDao.java
@@ -2,16 +2,16 @@
 
 import java.util.List;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.TypedQuery;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Join;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/QueryDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/QueryDao.java
index 50d5b98..366188b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/QueryDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/QueryDao.java
@@ -6,17 +6,17 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.NonUniqueResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.NonUniqueResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.TypedQuery;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Join;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java
index c26a39d..002d4ea 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/ResourceDao.java
@@ -3,14 +3,14 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.TypedQuery;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/RoleDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/RoleDao.java
index 0467893..47ddd18 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/RoleDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/RoleDao.java
@@ -4,13 +4,13 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.ListJoin;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.ListJoin;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java
index 66ef5fb..82ec01e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupDao.java
@@ -4,16 +4,16 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.ListJoin;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Join;
+import jakarta.persistence.criteria.ListJoin;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
diff --git a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java
index 1b2c15b..7fe96c5 100644
--- a/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/dao/UserGroupMemberDao.java
@@ -3,15 +3,15 @@
 import java.util.HashSet;
 import java.util.List;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Join;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
diff --git a/full/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java b/full/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java
index bf8cca1..fe7bab7 100644
--- a/full/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java
+++ b/full/src/main/java/de/ids_mannheim/korap/encryption/RandomCodeGenerator.java
@@ -9,8 +9,6 @@
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.stream.Collectors;
 
-import javax.annotation.PostConstruct;
-
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.logging.log4j.LogManager;
@@ -21,6 +19,7 @@
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
+import jakarta.annotation.PostConstruct;
 
 /**
  * Generates a random string that can be used for tokens, client id,
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/Admin.java b/full/src/main/java/de/ids_mannheim/korap/entity/Admin.java
index 654efe3..66a90aa 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/Admin.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/Admin.java
@@ -1,11 +1,11 @@
 package de.ids_mannheim.korap.entity;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/DefaultSetting.java b/full/src/main/java/de/ids_mannheim/korap/entity/DefaultSetting.java
index b485ab5..d09e2b0 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/DefaultSetting.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/DefaultSetting.java
@@ -1,8 +1,8 @@
 package de.ids_mannheim.korap.entity;
 
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
 
 /**
  * Describes default_setting table. Each user may define one set of
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/InstalledPlugin.java b/full/src/main/java/de/ids_mannheim/korap/entity/InstalledPlugin.java
index 92ab0f9..efc0a01 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/InstalledPlugin.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/InstalledPlugin.java
@@ -2,15 +2,15 @@
 
 import java.time.ZonedDateTime;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
 
 import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
 import lombok.Getter;
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/Privilege.java b/full/src/main/java/de/ids_mannheim/korap/entity/Privilege.java
index 9838f8a..0828595 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/Privilege.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/Privilege.java
@@ -1,15 +1,15 @@
 package de.ids_mannheim.korap.entity;
 
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
 
 import de.ids_mannheim.korap.constant.PrivilegeType;
 import lombok.Getter;
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/QueryAccess.java b/full/src/main/java/de/ids_mannheim/korap/entity/QueryAccess.java
index a7b518a..b0c0c29 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/QueryAccess.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/QueryAccess.java
@@ -1,16 +1,16 @@
 package de.ids_mannheim.korap.entity;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
 
 import de.ids_mannheim.korap.constant.QueryAccessStatus;
 import lombok.Getter;
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/QueryDO.java b/full/src/main/java/de/ids_mannheim/korap/entity/QueryDO.java
index 4e95e22..4c1b09e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/QueryDO.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/QueryDO.java
@@ -2,17 +2,17 @@
 
 import java.util.List;
 
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
 
 import de.ids_mannheim.korap.constant.QueryType;
 import de.ids_mannheim.korap.constant.ResourceType;
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/Role.java b/full/src/main/java/de/ids_mannheim/korap/entity/Role.java
index 0eaf767..43e1770 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/Role.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/Role.java
@@ -2,16 +2,16 @@
 
 import java.util.List;
 
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.ManyToMany;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/UserGroup.java b/full/src/main/java/de/ids_mannheim/korap/entity/UserGroup.java
index 3612ea9..74f0beb 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/UserGroup.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/UserGroup.java
@@ -2,17 +2,17 @@
 
 import java.util.List;
 
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
 
 import de.ids_mannheim.korap.constant.UserGroupStatus;
 import lombok.Getter;
diff --git a/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java b/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java
index 983535b..760277c 100644
--- a/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java
+++ b/full/src/main/java/de/ids_mannheim/korap/entity/UserGroupMember.java
@@ -3,21 +3,21 @@
 import java.time.ZonedDateTime;
 import java.util.Set;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.Index;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
 
 import de.ids_mannheim.korap.constant.GroupMemberStatus;
 import de.ids_mannheim.korap.constant.PredefinedRole;
diff --git a/full/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java b/full/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
index efe9338..0915bb5 100644
--- a/full/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
+++ b/full/src/main/java/de/ids_mannheim/korap/exceptions/KustvaktException.java
@@ -3,6 +3,8 @@
 import java.net.URI;
 import java.util.Arrays;
 
+import com.nimbusds.oauth2.sdk.ErrorObject;
+
 //import de.ids_mannheim.korap.constant.TokenType;
 import lombok.Getter;
 import lombok.Setter;
@@ -25,6 +27,7 @@
     private boolean isNotification;
 //    private TokenType authType;
     private URI redirectUri;
+    private ErrorObject oauth2Error;
 
     public KustvaktException (int status) {
         this.statusCode = status;
@@ -92,6 +95,13 @@
         this.statusCode = status;
     }
 
+    public KustvaktException (int status, String message,
+            ErrorObject oauth2Error) {
+        super(message);
+        this.statusCode = status;
+        this.oauth2Error = oauth2Error;
+        this.entity = oauth2Error.toString();
+    }
 
     public KustvaktException (Throwable cause, int status) {
         super(cause);
diff --git a/full/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java b/full/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
index c1777a4..73f1c62 100644
--- a/full/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
+++ b/full/src/main/java/de/ids_mannheim/korap/exceptions/StatusCodes.java
@@ -112,7 +112,7 @@
 
     public static final int STATUS_OK = 1000;
     public static final int NOTHING_CHANGED = 1001;
-    public static final int REQUEST_INVALID = 1002;
+    public static final int INVALID_REQUEST = 1002;
     
 //    public static final int ACCESS_DENIED = 1003;
 
@@ -126,7 +126,7 @@
     public static final int GROUP_DELETED = 1606;
     
     /**
-     * 1800 Oauth2 and OpenID
+     * 1800 Oauth2
      */
 
     public static final int OAUTH2_SYSTEM_ERROR = 1800;
@@ -144,12 +144,11 @@
     
     public static final int UNSUPPORTED_GRANT_TYPE = 1811;
     public static final int UNSUPPORTED_AUTHENTICATION_METHOD = 1812;
+    public static final int UNSUPPORTED_RESPONSE_TYPE = 1813;
     
-    public static final int ID_TOKEN_CLAIM_ERROR = 1813;
-    public static final int ID_TOKEN_SIGNING_FAILED = 1814;
-    public static final int USER_REAUTHENTICATION_REQUIRED = 1815;
+    public static final int USER_REAUTHENTICATION_REQUIRED = 1822;
     
-    public static final int INVALID_REFRESH_TOKEN_EXPIRY = 1816;
+    public static final int INVALID_REFRESH_TOKEN_EXPIRY = 1830;
     
     /**
      * 1850 Plugins
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AccessScopeDao.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AccessScopeDao.java
index aeb1c92..9a2579c 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AccessScopeDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AccessScopeDao.java
@@ -3,12 +3,12 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AccessTokenDao.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AccessTokenDao.java
index ac32e87..b2fec0b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AccessTokenDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AccessTokenDao.java
@@ -5,15 +5,15 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.TypedQuery;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AuthorizationDaoImpl.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AuthorizationDaoImpl.java
index 8de2a42..b66037b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AuthorizationDaoImpl.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/AuthorizationDaoImpl.java
@@ -5,13 +5,13 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.persistence.EntityManager;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/InstalledPluginDao.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/InstalledPluginDao.java
index 00243ba..b2dfb39 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/InstalledPluginDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/InstalledPluginDao.java
@@ -4,14 +4,14 @@
 import java.time.ZonedDateTime;
 import java.util.List;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.TypedQuery;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/OAuth2ClientDao.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/OAuth2ClientDao.java
index bcf59c5..9aa7bb8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/OAuth2ClientDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/OAuth2ClientDao.java
@@ -4,16 +4,16 @@
 import java.time.ZonedDateTime;
 import java.util.List;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Join;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.TypedQuery;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Join;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/RefreshTokenDao.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/RefreshTokenDao.java
index 83fbc6f..0c68485 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/RefreshTokenDao.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/dao/RefreshTokenDao.java
@@ -5,15 +5,15 @@
 import java.util.List;
 import java.util.Set;
 
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.PersistenceContext;
-import javax.persistence.Query;
-import javax.persistence.TypedQuery;
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.NoResultException;
+import jakarta.persistence.PersistenceContext;
+import jakarta.persistence.Query;
+import jakarta.persistence.TypedQuery;
+import jakarta.persistence.criteria.CriteriaBuilder;
+import jakarta.persistence.criteria.CriteriaQuery;
+import jakarta.persistence.criteria.Predicate;
+import jakarta.persistence.criteria.Root;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Repository;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/AccessScope.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/AccessScope.java
index 99ee216..7903146 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/AccessScope.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/AccessScope.java
@@ -3,13 +3,13 @@
 import java.io.Serializable;
 import java.util.List;
 
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.ManyToMany;
-import javax.persistence.Table;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Id;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.Table;
 
 import de.ids_mannheim.korap.constant.OAuth2Scope;
 import lombok.Getter;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/AccessToken.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/AccessToken.java
index 17ee77d..04acc5e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/AccessToken.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/AccessToken.java
@@ -4,18 +4,18 @@
 import java.time.ZonedDateTime;
 import java.util.Set;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
-import javax.persistence.ManyToOne;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/Authorization.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/Authorization.java
index 76813ff..386434f 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/Authorization.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/Authorization.java
@@ -3,17 +3,17 @@
 import java.time.ZonedDateTime;
 import java.util.Set;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
 
 import lombok.Getter;
 import lombok.Setter;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/OAuth2Client.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/OAuth2Client.java
index 26fa82b..eac5d31 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/OAuth2Client.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/OAuth2Client.java
@@ -3,14 +3,14 @@
 import java.time.ZonedDateTime;
 import java.util.List;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
 
 import de.ids_mannheim.korap.entity.InstalledPlugin;
 import de.ids_mannheim.korap.oauth2.constant.OAuth2ClientType;
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/RefreshToken.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/RefreshToken.java
index 4830468..ff22e25 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/RefreshToken.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/entity/RefreshToken.java
@@ -3,19 +3,19 @@
 import java.time.ZonedDateTime;
 import java.util.Set;
 
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.JoinTable;
-import javax.persistence.ManyToMany;
-import javax.persistence.ManyToOne;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
 
 /**
  * Describes oauth2_refresh_token database table mapping and refresh
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java
deleted file mode 100644
index cb72f53..0000000
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuAuthorizationService.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package de.ids_mannheim.korap.oauth2.oltu.service;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.time.ZonedDateTime;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.http.HttpStatus;
-import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest;
-import org.apache.oltu.oauth2.as.response.OAuthASResponse;
-import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
-import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
-import org.apache.oltu.oauth2.common.message.OAuthResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import javax.ws.rs.core.Response.Status;
-
-import de.ids_mannheim.korap.encryption.RandomCodeGenerator;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
-import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
-import de.ids_mannheim.korap.oauth2.service.OAuth2AuthorizationService;
-import de.ids_mannheim.korap.oauth2.service.OAuth2ClientService;
-
-/**
- * OAuth2 authorization service using Apache Oltu
- * 
- * @author margaretha
- *
- */
-@Service
-public class OltuAuthorizationService extends OAuth2AuthorizationService {
-
-    @Autowired
-    private RandomCodeGenerator codeGenerator;
-    @Autowired
-    private OAuth2ClientService clientService;
-
-    /**
-     * Authorization code request does not require client
-     * authentication, but only checks if the client id exists.
-     * 
-     * @param request
-     * @param authzRequest
-     * @param username
-     * @param authTime
-     * @return redirect URI containing authorization code if
-     *         successful.
-     * 
-     * @throws KustvaktException
-     * @throws OAuthSystemException
-     */
-    public String requestAuthorizationCode (HttpServletRequest request,
-            OAuthAuthzRequest authzRequest, String username,
-            ZonedDateTime authenticationTime)
-            throws OAuthSystemException, KustvaktException {
-
-        String clientId = authzRequest.getClientId();
-        OAuth2Client client = clientService.authenticateClientId(clientId);
-
-        String redirectUriStr = authzRequest.getRedirectURI();
-        String verifiedRedirectUri = verifyRedirectUri(client, redirectUriStr);
-
-        URI redirectURI;
-        try {
-            redirectURI = new URI(verifiedRedirectUri);
-        }
-        catch (URISyntaxException e) {
-            throw new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
-                    "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
-        }
-
-        String scope, code;
-        try {
-            //checkResponseType(authzRequest.getResponseType(), redirectURI);
-            code = codeGenerator.createRandomCode();
-            scope = createAuthorization(username, authzRequest.getClientId(),
-                    redirectUriStr, authzRequest.getScopes(), code,
-                    authenticationTime, null);
-        }
-        catch (KustvaktException e) {
-            e.setRedirectUri(redirectURI);
-            throw e;
-        }
-
-        OAuthResponse oAuthResponse;
-        try {
-            oAuthResponse = OAuthASResponse
-                    .authorizationResponse(request,
-                            Status.FOUND.getStatusCode())
-                    .setCode(code).setScope(scope)
-                    .location(verifiedRedirectUri)
-                    .buildQueryMessage();
-        }
-        catch (OAuthSystemException e) {
-            // Should not happen
-            KustvaktException ke =
-                    new KustvaktException(StatusCodes.OAUTH2_SYSTEM_ERROR,
-                            e.getMessage(), OAuth2Error.SERVER_ERROR);
-            ke.setRedirectUri(redirectURI);
-            throw ke;
-        }
-        return oAuthResponse.getLocationUri();
-    }
-
-    public OAuthProblemException checkRedirectUri (OAuthProblemException e,
-            String clientId, String redirectUri) {
-        if (clientId !=null && !clientId.isEmpty()) {
-            String registeredUri = null;
-            try {
-                OAuth2Client client = clientService.retrieveClient(clientId);
-                registeredUri = client.getRedirectURI();
-            }
-            catch (KustvaktException e1) {}
-
-            if (redirectUri != null && !redirectUri.isEmpty()) {
-                if (registeredUri != null && !registeredUri.isEmpty()
-                        && !redirectUri.equals(registeredUri)) {
-                    e.description("Invalid redirect URI");
-                }
-                else {
-                    e.setRedirectUri(redirectUri);
-                    e.responseStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
-                }
-            }
-            else if (registeredUri != null && !registeredUri.isEmpty()) {
-                e.setRedirectUri(registeredUri);
-                e.responseStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
-            }
-            else {
-                e.description("Missing parameter: redirect URI");
-            }
-        }
-
-        return e;
-    }
-    
-    public KustvaktException checkRedirectUri (KustvaktException e,
-            String clientId, String redirectUri){
-        int statusCode = e.getStatusCode();
-        if (!clientId.isEmpty()
-                && statusCode != StatusCodes.CLIENT_NOT_FOUND
-                && statusCode != StatusCodes.AUTHORIZATION_FAILED
-                && statusCode != StatusCodes.INVALID_REDIRECT_URI) {
-            String registeredUri = null;
-            try {
-                OAuth2Client client = clientService.retrieveClient(clientId);
-                registeredUri = client.getRedirectURI();
-            }
-            catch (KustvaktException e1) {}
-
-            if (redirectUri != null && !redirectUri.isEmpty()) {
-                if (registeredUri != null && !registeredUri.isEmpty()
-                        && !redirectUri.equals(registeredUri)) {
-                    return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
-                            "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
-                }
-                else {
-                    try {
-                        e.setRedirectUri(new URI(redirectUri));
-                    }
-                    catch (URISyntaxException e1) {
-                        return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
-                                "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
-                    }
-                    e.setResponseStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
-                }
-            }
-            else if (registeredUri != null && !registeredUri.isEmpty()) {
-                try {
-                    e.setRedirectUri(new URI(registeredUri));
-                }
-                catch (URISyntaxException e1) {
-                    return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
-                            "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
-                }
-                e.setResponseStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
-            }
-            else {
-                return new KustvaktException(StatusCodes.MISSING_REDIRECT_URI,
-                        "Missing parameter: redirect URI", OAuth2Error.INVALID_REQUEST);
-            }
-        }
-
-        return e;
-    }
-}
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
deleted file mode 100644
index 665b082..0000000
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java
+++ /dev/null
@@ -1,645 +0,0 @@
-package de.ids_mannheim.korap.oauth2.oltu.service;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.time.format.DateTimeFormatter;
-import java.time.temporal.ChronoUnit;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import javax.persistence.NoResultException;
-import javax.ws.rs.core.Response.Status;
-
-import org.apache.oltu.oauth2.as.request.AbstractOAuthTokenRequest;
-import org.apache.oltu.oauth2.as.response.OAuthASResponse;
-import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
-import org.apache.oltu.oauth2.common.message.OAuthResponse;
-import org.apache.oltu.oauth2.common.message.types.GrantType;
-import org.apache.oltu.oauth2.common.message.types.TokenType;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import com.unboundid.ldap.sdk.LDAPException;
-
-import de.ids_mannheim.korap.authentication.LdapAuth3;
-import de.ids_mannheim.korap.config.Attributes;
-import de.ids_mannheim.korap.constant.AuthenticationMethod;
-import de.ids_mannheim.korap.encryption.RandomCodeGenerator;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
-import de.ids_mannheim.korap.oauth2.dao.AccessTokenDao;
-import de.ids_mannheim.korap.oauth2.dao.RefreshTokenDao;
-import de.ids_mannheim.korap.oauth2.dto.OAuth2TokenDto;
-import de.ids_mannheim.korap.oauth2.entity.AccessScope;
-import de.ids_mannheim.korap.oauth2.entity.AccessToken;
-import de.ids_mannheim.korap.oauth2.entity.Authorization;
-import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
-import de.ids_mannheim.korap.oauth2.entity.RefreshToken;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeAllTokenSuperRequest;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenRequest;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenSuperRequest;
-import de.ids_mannheim.korap.oauth2.service.OAuth2ClientService;
-import de.ids_mannheim.korap.oauth2.service.OAuth2TokenService;
-
-/** Implementation of token service using Apache Oltu.
- * 
- * @author margaretha
- *
- */
-@Service
-public class OltuTokenService extends OAuth2TokenService {
-
-    @Autowired
-    private RandomCodeGenerator randomGenerator;
-
-    @Autowired
-    private AccessTokenDao tokenDao;
-    @Autowired
-    private RefreshTokenDao refreshDao;
-    
-    @Autowired
-    private OAuth2ClientService clientService;
-
-    public OAuthResponse requestAccessToken (
-            AbstractOAuthTokenRequest oAuthRequest)
-            throws KustvaktException, OAuthSystemException {
-
-        String grantType = oAuthRequest.getGrantType();
-
-        if (grantType.equals(GrantType.AUTHORIZATION_CODE.toString())) {
-            return requestAccessTokenWithAuthorizationCode(
-                    oAuthRequest.getCode(), oAuthRequest.getRedirectURI(),
-                    oAuthRequest.getClientId(), oAuthRequest.getClientSecret());
-        }
-        else if (grantType.equals(GrantType.PASSWORD.toString())) {
-            return requestAccessTokenWithPassword(oAuthRequest.getClientId(),
-                    oAuthRequest.getClientSecret(), oAuthRequest.getUsername(),
-                    oAuthRequest.getPassword(), oAuthRequest.getScopes());
-        }
-        else if (grantType.equals(GrantType.CLIENT_CREDENTIALS.toString())) {
-            return requestAccessTokenWithClientCredentials(
-                    oAuthRequest.getClientId(), oAuthRequest.getClientSecret(),
-                    oAuthRequest.getScopes());
-        }
-        else if (grantType.equals(GrantType.REFRESH_TOKEN.toString())) {
-            return requestAccessTokenWithRefreshToken(
-                    oAuthRequest.getRefreshToken(), oAuthRequest.getScopes(),
-                    oAuthRequest.getClientId(), oAuthRequest.getClientSecret());
-        }
-        else {
-            throw new KustvaktException(StatusCodes.UNSUPPORTED_GRANT_TYPE,
-                    grantType + " is not supported.",
-                    OAuth2Error.UNSUPPORTED_GRANT_TYPE);
-        }
-
-    }
-
-    private boolean isInternalClient (String clientIpAddress) {
-        try {
-            InetAddress ip = InetAddress.getByName(clientIpAddress);
-            if (ip.isSiteLocalAddress()) {
-                return true;
-            }
-        }
-        catch (UnknownHostException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-        return false;
-    }
-
-    /**
-     * Revokes all access token associated with the given refresh
-     * token, and creates a new access token and a new refresh
-     * token with the same scopes. Thus, at one point of time,
-     * there is only one active access token associated with
-     * a refresh token.
-     * 
-     * Client authentication is done using the given client
-     * credentials.
-     * 
-     * TODO: should create a new refresh token when the old refresh
-     * token is used (DONE)
-     * 
-     * @param refreshTokenStr
-     * @param requestScopes
-     * @param clientId
-     * @param clientSecret
-     * @return if successful, a new access token
-     * @throws KustvaktException
-     * @throws OAuthSystemException
-     */
-    private OAuthResponse requestAccessTokenWithRefreshToken (
-            String refreshTokenStr, Set<String> requestScopes, String clientId,
-            String clientSecret)
-            throws KustvaktException, OAuthSystemException {
-
-        if (refreshTokenStr == null || refreshTokenStr.isEmpty()) {
-            throw new KustvaktException(StatusCodes.MISSING_PARAMETER,
-                    "Missing parameter: refresh_token",
-                    OAuth2Error.INVALID_REQUEST);
-        }
-
-        OAuth2Client oAuth2Client = clientService.authenticateClient(clientId, clientSecret);
-
-        RefreshToken refreshToken;
-        try {
-            refreshToken = refreshDao.retrieveRefreshToken(refreshTokenStr);
-        }
-        catch (NoResultException e) {
-            throw new KustvaktException(StatusCodes.INVALID_REFRESH_TOKEN,
-                    "Refresh token is not found", OAuth2Error.INVALID_GRANT);
-        }
-
-        if (!clientId.equals(refreshToken.getClient().getId())) {
-            throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
-                    "Client " + clientId + " is not authorized",
-                    OAuth2Error.INVALID_CLIENT);
-        }
-        else if (refreshToken.isRevoked()) {
-            throw new KustvaktException(StatusCodes.INVALID_REFRESH_TOKEN,
-                    "Refresh token has been revoked",
-                    OAuth2Error.INVALID_GRANT);
-        }
-        else if (ZonedDateTime.now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE))
-                .isAfter(refreshToken.getExpiryDate())) {
-            throw new KustvaktException(StatusCodes.INVALID_REFRESH_TOKEN,
-                    "Refresh token is expired", OAuth2Error.INVALID_GRANT);
-        }
-
-        Set<AccessScope> tokenScopes =
-                new HashSet<>(refreshToken.getScopes());
-        if (requestScopes != null && !requestScopes.isEmpty()) {
-            tokenScopes =
-                    scopeService.verifyRefreshScope(requestScopes, tokenScopes);
-            requestScopes = scopeService
-                    .convertAccessScopesToStringSet(tokenScopes);
-        }
-
-        // revoke the refresh token and all access tokens associated to it
-        revokeRefreshToken(refreshTokenStr);
-
-        return createsAccessTokenResponse(requestScopes, tokenScopes, clientId,
-                refreshToken.getUserId(),
-                refreshToken.getUserAuthenticationTime(), oAuth2Client);
-
-        // without new refresh token
-        // return createsAccessTokenResponse(scopes, requestedScopes,
-        // clientId,
-        // refreshToken.getUserId(),
-        // refreshToken.getUserAuthenticationTime(), refreshToken);
-    }
-
-    /**
-     * 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);
-
-        Set<String> scopes = scopeService
-                .convertAccessScopesToStringSet(authorization.getScopes());
-        OAuth2Client oAuth2Client = clientService.retrieveClient(clientId);
-        return createsAccessTokenResponse(scopes, authorization.getScopes(),
-                authorization.getClientId(), authorization.getUserId(),
-                authorization.getUserAuthenticationTime(), oAuth2Client);
-    }
-
-    /**
-     * 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).
-     * 
-     * TODO: FORCE client secret
-     * 
-     * @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.isSuper()) {
-            throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
-                    "Password grant is not allowed for third party clients",
-                    OAuth2Error.UNAUTHORIZED_CLIENT);
-        }
-
-        if (scopes == null || scopes.isEmpty()) {
-            scopes = new HashSet<String>(1);
-            scopes.add("all");
-            // scopes = config.getDefaultAccessScopes();
-        }
-
-        ZonedDateTime authenticationTime =
-                authenticateUser(username, password, scopes);
-
-        Set<AccessScope> accessScopes =
-                scopeService.convertToAccessScope(scopes);
-        
-        if (config.getOAuth2passwordAuthentication()
-                .equals(AuthenticationMethod.LDAP)) {
-            try {
-                //username = LdapAuth3.getEmail(username, config.getLdapConfig());
-                username = LdapAuth3.getUsername(username, config.getLdapConfig());
-            }
-            catch (LDAPException e) {
-                throw new KustvaktException(StatusCodes.LDAP_BASE_ERRCODE,
-                        e.getExceptionMessage());
-            }
-        }
-        
-        return createsAccessTokenResponse(scopes, accessScopes, clientId,
-                username, authenticationTime, client);
-    }
-
-    /**
-     * Clients must authenticate.
-     * Client credentials grant is limited to native clients.
-     * 
-     * @param clientId
-     *            client_id parameter, required
-     * @param clientSecret
-     *            client_secret parameter, required
-     * @param scopes
-     *            authorization scopes, optional
-     * @return an {@link OAuthResponse}
-     * @throws KustvaktException
-     * @throws OAuthSystemException
-     */
-    protected OAuthResponse requestAccessTokenWithClientCredentials (
-            String clientId, String clientSecret, Set<String> scopes)
-            throws KustvaktException, OAuthSystemException {
-
-        if (clientSecret == null || clientSecret.isEmpty()) {
-            throw new KustvaktException(
-                    StatusCodes.CLIENT_AUTHENTICATION_FAILED,
-                    "Missing parameter: client_secret",
-                    OAuth2Error.INVALID_REQUEST);
-        }
-
-        // OAuth2Client client =
-        OAuth2Client oAuth2Client = clientService.authenticateClient(clientId, clientSecret);
-
-        // if (!client.isNative()) {
-        // throw new KustvaktException(
-        // StatusCodes.CLIENT_AUTHENTICATION_FAILED,
-        // "Client credentials grant is not allowed for third party
-        // clients",
-        // OAuth2Error.UNAUTHORIZED_CLIENT);
-        // }
-
-        ZonedDateTime authenticationTime =
-                ZonedDateTime.now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE));
-
-        scopes = scopeService.filterScopes(scopes,
-                config.getClientCredentialsScopes());
-        Set<AccessScope> accessScopes =
-                scopeService.convertToAccessScope(scopes);
-        return createsAccessTokenResponse(scopes, accessScopes, clientId, null,
-                authenticationTime,oAuth2Client);
-    }
-
-    /**
-     * Creates an OAuthResponse containing an access token of type
-     * Bearer. By default, MD generator is used to generates access
-     * token of 128 bit values, represented in hexadecimal comprising
-     * 32 bytes. The generated value is subsequently encoded in
-     * Base64.
-     * 
-     * <br /><br />
-     * Additionally, a refresh token is issued for confidential clients. 
-     * It can be used to request a new access token without requiring user
-     * re-authentication.
-     * 
-     * @param scopes
-     *            a set of access token scopes in String
-     * @param accessScopes
-     *            a set of access token scopes in {@link AccessScope}
-     * @param clientId
-     *            a client id
-     * @param userId
-     *            a user id
-     * @param authenticationTime
-     *            the user authentication time
-     * @return an {@link OAuthResponse}
-     * @throws OAuthSystemException
-     * @throws KustvaktException
-     */
-    private OAuthResponse createsAccessTokenResponse (Set<String> scopes,
-            Set<AccessScope> accessScopes, String clientId, String userId,
-            ZonedDateTime authenticationTime, OAuth2Client client)
-            throws OAuthSystemException, KustvaktException {
-
-        String random = randomGenerator.createRandomCode();
-        random += randomGenerator.createRandomCode();
-        
-        if (clientService.isPublicClient(client)){
-            // refresh token == null, getAccessTokenLongExpiry
-            return createsAccessTokenResponse(scopes, accessScopes, clientId,
-                    userId, authenticationTime);
-            }
-        else {
-            // refresh token != null, getAccessTokenExpiry
-            // default refresh token expiry: 365 days in seconds
-            RefreshToken refreshToken = refreshDao.storeRefreshToken(random,
-                    userId, authenticationTime, client, accessScopes);
-            return createsAccessTokenResponse(scopes, accessScopes, clientId,
-                    userId, authenticationTime, refreshToken);
-        }
-    }
-
-    private OAuthResponse createsAccessTokenResponse (Set<String> scopes,
-            Set<AccessScope> accessScopes, String clientId, String userId,
-            ZonedDateTime authenticationTime, RefreshToken refreshToken)
-            throws OAuthSystemException, KustvaktException {
-
-        String accessToken = randomGenerator.createRandomCode();
-        accessToken +=randomGenerator.createRandomCode();
-        tokenDao.storeAccessToken(accessToken, refreshToken, accessScopes,
-                userId, clientId, authenticationTime);
-
-        return OAuthASResponse.tokenResponse(Status.OK.getStatusCode())
-                .setAccessToken(accessToken)
-                .setTokenType(TokenType.BEARER.toString())
-                .setExpiresIn(String.valueOf(config.getAccessTokenExpiry()))
-                .setRefreshToken(refreshToken.getToken())
-                .setScope(String.join(" ", scopes)).buildJSONMessage();
-    }
-    
-    private OAuthResponse createsAccessTokenResponse (Set<String> scopes,
-            Set<AccessScope> accessScopes, String clientId, String userId,
-            ZonedDateTime authenticationTime)
-            throws OAuthSystemException, KustvaktException {
-
-        String accessToken = randomGenerator.createRandomCode();
-        accessToken +=randomGenerator.createRandomCode();
-        tokenDao.storeAccessToken(accessToken, null, accessScopes,
-                userId, clientId, authenticationTime);
-
-        return OAuthASResponse.tokenResponse(Status.OK.getStatusCode())
-                .setAccessToken(accessToken)
-                .setTokenType(TokenType.BEARER.toString())
-                .setExpiresIn(String.valueOf(config.getAccessTokenLongExpiry()))
-                .setScope(String.join(" ", scopes)).buildJSONMessage();
-    }
-
-    public void revokeToken (OAuth2RevokeTokenRequest revokeTokenRequest)
-            throws KustvaktException {
-        String clientId = revokeTokenRequest.getClientId();
-        String clientSecret = revokeTokenRequest.getClientSecret();
-        String token = revokeTokenRequest.getToken();
-        String tokenType = revokeTokenRequest.getTokenType();
-
-        clientService.authenticateClient(clientId, clientSecret);
-        if (tokenType != null && tokenType.equals("refresh_token")) {
-            if (!revokeRefreshToken(token)) {
-                revokeAccessToken(token);
-            }
-            return;
-        }
-
-        if (!revokeAccessToken(token)) {
-            revokeRefreshToken(token);
-        }
-    }
-
-    private boolean revokeAccessToken (String token) throws KustvaktException {
-        try {
-            AccessToken accessToken = tokenDao.retrieveAccessToken(token);
-            revokeAccessToken(accessToken);
-            return true;
-        }
-        catch (KustvaktException e) {
-            if (!e.getStatusCode().equals(StatusCodes.INVALID_ACCESS_TOKEN)) {
-                return false;
-            }
-            throw e;
-        }
-    }
-    
-    private void revokeAccessToken (AccessToken accessToken)
-            throws KustvaktException {
-        if (accessToken != null){
-            accessToken.setRevoked(true);
-            tokenDao.updateAccessToken(accessToken);
-        }
-    }
-
-    private boolean revokeRefreshToken (String token) throws KustvaktException {
-        RefreshToken refreshToken = null;
-        try {
-            refreshToken = refreshDao.retrieveRefreshToken(token);
-        }
-        catch (NoResultException e) {
-            return false;
-        }
-
-        return revokeRefreshToken(refreshToken);
-    }
-
-    public boolean revokeRefreshToken (RefreshToken refreshToken)
-            throws KustvaktException {
-        if (refreshToken != null){
-            refreshToken.setRevoked(true);
-            refreshDao.updateRefreshToken(refreshToken);
-    
-            Set<AccessToken> accessTokenList = refreshToken.getAccessTokens();
-            for (AccessToken accessToken : accessTokenList) {
-                accessToken.setRevoked(true);
-                tokenDao.updateAccessToken(accessToken);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    public void revokeAllClientTokensViaSuperClient (String username,
-            OAuth2RevokeAllTokenSuperRequest revokeTokenRequest)
-            throws KustvaktException {
-        String superClientId = revokeTokenRequest.getSuperClientId();
-        String superClientSecret = revokeTokenRequest.getSuperClientSecret();
-
-        OAuth2Client superClient = clientService
-                .authenticateClient(superClientId, superClientSecret);
-        if (!superClient.isSuper()) {
-            throw new KustvaktException(
-                    StatusCodes.CLIENT_AUTHENTICATION_FAILED);
-        }
-
-        String clientId = revokeTokenRequest.getClientId();
-        revokeAllClientTokensForUser(clientId, username);
-    }
-    
-    public void revokeAllClientTokensForUser (String clientId, String username)
-            throws KustvaktException {
-        OAuth2Client client = clientService.retrieveClient(clientId);
-        if (clientService.isPublicClient(client)) {
-            List<AccessToken> accessTokens =
-                    tokenDao.retrieveAccessTokenByClientId(clientId, username);
-            for (AccessToken t : accessTokens) {
-                revokeAccessToken(t);
-            }
-        }
-        else {
-            List<RefreshToken> refreshTokens = refreshDao
-                    .retrieveRefreshTokenByClientId(clientId, username);
-            for (RefreshToken r : refreshTokens) {
-                revokeRefreshToken(r);
-            }
-        }
-    }
-    
-    public void revokeTokensViaSuperClient (String username,
-            OAuth2RevokeTokenSuperRequest revokeTokenRequest) throws KustvaktException {
-        String superClientId = revokeTokenRequest.getSuperClientId();
-        String superClientSecret = revokeTokenRequest.getSuperClientSecret();
-
-        OAuth2Client superClient = clientService
-                .authenticateClient(superClientId, superClientSecret);
-        if (!superClient.isSuper()) {
-            throw new KustvaktException(
-                    StatusCodes.CLIENT_AUTHENTICATION_FAILED);
-        }
-        
-        String token = revokeTokenRequest.getToken();
-        RefreshToken refreshToken = refreshDao.retrieveRefreshToken(token, username);
-        if (!revokeRefreshToken(refreshToken)){
-            AccessToken accessToken = tokenDao.retrieveAccessToken(token, username);
-            revokeAccessToken(accessToken);
-        }
-    }
-    
-    public List<OAuth2TokenDto> listUserRefreshToken (String username, String superClientId,
-            String superClientSecret, String clientId) throws KustvaktException {
-        
-        OAuth2Client client = clientService.authenticateClient(superClientId, superClientSecret);
-        if (!client.isSuper()) {
-            throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
-                    "Only super client is allowed.",
-                    OAuth2Error.UNAUTHORIZED_CLIENT);
-        }
-
-        List<RefreshToken> tokens = refreshDao.retrieveRefreshTokenByUser(username, clientId);
-        List<OAuth2TokenDto> dtoList = new ArrayList<>(tokens.size());
-        for (RefreshToken t : tokens){
-            OAuth2Client tokenClient = t.getClient();
-            if (tokenClient.getId().equals(client.getId())){
-                continue;
-            }
-            OAuth2TokenDto dto = new OAuth2TokenDto();
-            dto.setClientId(tokenClient.getId());
-            dto.setClientName(tokenClient.getName());
-            dto.setClientUrl(tokenClient.getUrl());
-            dto.setClientDescription(tokenClient.getDescription());
-            
-            DateTimeFormatter f = DateTimeFormatter.ISO_DATE_TIME;
-            dto.setCreatedDate(t.getCreatedDate().format(f));
-            long difference = ChronoUnit.SECONDS.between(ZonedDateTime.now(), t.getExpiryDate());
-            dto.setExpiresIn(difference);
-            
-            dto.setUserAuthenticationTime(
-                    t.getUserAuthenticationTime().format(f));
-            dto.setToken(t.getToken());
-            
-            Set<AccessScope> accessScopes = t.getScopes();
-            Set<String> scopes = new HashSet<>(accessScopes.size());
-            for (AccessScope s : accessScopes){
-                scopes.add(s.getId().toString());
-            }
-            dto.setScope(scopes);
-            dtoList.add(dto);
-        }
-        return dtoList;
-    }
-    
-    public List<OAuth2TokenDto> listUserAccessToken (String username, String superClientId,
-            String superClientSecret, String clientId) throws KustvaktException {
-        
-        OAuth2Client superClient = clientService.authenticateClient(superClientId, superClientSecret);
-        if (!superClient.isSuper()) {
-            throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
-                    "Only super client is allowed.",
-                    OAuth2Error.UNAUTHORIZED_CLIENT);
-        }
-
-        List<AccessToken> tokens =
-                tokenDao.retrieveAccessTokenByUser(username, clientId);
-        List<OAuth2TokenDto> dtoList = new ArrayList<>(tokens.size());
-        for (AccessToken t : tokens){
-            OAuth2Client tokenClient = t.getClient();
-            if (tokenClient.getId().equals(superClient.getId())){
-                continue;
-            }
-            OAuth2TokenDto dto = new OAuth2TokenDto();
-            dto.setClientId(tokenClient.getId());
-            dto.setClientName(tokenClient.getName());
-            dto.setClientUrl(tokenClient.getUrl());
-            dto.setClientDescription(tokenClient.getDescription());
-            
-            DateTimeFormatter f = DateTimeFormatter.ISO_DATE_TIME;
-            dto.setCreatedDate(t.getCreatedDate().format(f));
-            
-            long difference = ChronoUnit.SECONDS.between(ZonedDateTime.now(), t.getExpiryDate());
-            dto.setExpiresIn(difference);
-                    
-            dto.setUserAuthenticationTime(
-                    t.getUserAuthenticationTime().format(f));
-            dto.setToken(t.getToken());
-            
-            Set<AccessScope> accessScopes = t.getScopes();
-            Set<String> scopes = new HashSet<>(accessScopes.size());
-            for (AccessScope s : accessScopes){
-                scopes.add(s.getId().toString());
-            }
-            dto.setScope(scopes);
-            dtoList.add(dto);
-        }
-        return dtoList;
-    }
-   
-}
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/OpenIdConfiguration.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/OpenIdConfiguration.java
deleted file mode 100644
index 499b214..0000000
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/OpenIdConfiguration.java
+++ /dev/null
@@ -1,699 +0,0 @@
-package de.ids_mannheim.korap.oauth2.openid;
-
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonInclude.Include;
-
-/**
- * Defines OpenID configuration.
- * 
- * Note: some configuration such as display_values_supported and
- * ui_locales_supported are more relevant to KorAP user interface
- * component Kalamar.
- * 
- * @see <a
- *      href="https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata">OpenID
- *      Provider Metadata</a>
- * @author margaretha
- *
- */
-@JsonInclude(Include.NON_EMPTY)
-public class OpenIdConfiguration {
-
-    public final static String JWKS_ENDPOINT = "/oauth2/openid/jwks";
-    public static final String CLIENT_REGISTRATION_ENDPOINT =
-            "/oauth2/client/register";
-    public static final String AUTHORIZATION_ENDPOINT =
-            "/oauth2/openid/authorize";
-    public static final String TOKEN_ENDPOINT = "/oauth2/openid/token";
-
-    private String issuer;
-    private String jwks_uri;
-
-    private String authorization_endpoint;
-    private String token_endpoint;
-    private String userinfo_endpoint;
-    private String registration_endpoint;
-
-    // Additional endpoints
-    private String introspection_endpoint;
-    private String revocation_endpoint;
-    private String end_session_endpoint;
-
-    private String[] scopes_supported;
-    private String[] response_types_supported;
-    private String[] response_modes_supported;
-    private String[] grant_types_supported;
-
-    private String[] token_endpoint_auth_methods_supported;
-    private String[] token_endpoint_auth_signing_alg_values_supported;
-
-    private String[] id_token_signing_alg_values_supported;
-    private String[] id_token_encryption_alg_values_supported;
-    private String[] id_token_encryption_enc_values_supported;
-
-    private String[] userinfo_signing_alg_values_supported;
-    private String[] userinfo_encryption_alg_values_supported;
-    private String[] userinfo_encryption_enc_values_supported;
-
-    private String[] request_object_signing_alg_values_supported;
-    private String[] request_object_encryption_alg_values_supported;
-    private String[] request_object_encryption_enc_values_supported;
-
-    private String[] subject_types_supported;
-    private String[] acr_values_supported;
-    private String[] display_values_supported;
-    private String[] claim_types_supported;
-    private String[] claims_supported;
-    private String[] claims_locales_supported;
-    private String[] ui_locales_supported;
-
-    private boolean claims_parameter_supported = false;
-    private boolean request_parameter_supported = false;
-    private boolean request_uri_parameter_supported = true;
-    private boolean require_request_uri_registration = false;
-
-    private String op_policy_uri;
-    private String op_tos_uri;
-    private String service_documentation;
-
-    private boolean mutual_tls_sender_constrained_access_tokens = false;
-
-    // OAuth2.0 Discovery
-    // List of Proof Key for Code Exchange (PKCE) code challenge
-    // methods supported on by the authorization server
-    // private String[] code_challenge_methods_supported;
-
-    public String getIssuer () {
-        return issuer;
-    }
-
-    /**
-     * REQUIRED
-     * 
-     * @param issuer
-     *            The server identifier, typically base-URL
-     */
-    public void setIssuer (String issuer) {
-        this.issuer = issuer;
-    }
-
-    public String getJwks_uri () {
-        return jwks_uri;
-    }
-
-    /**
-     * REQUIRED
-     * 
-     * @param jwks_uri
-     *            The public JWK set URL
-     */
-    public void setJwks_uri (String jwks_uri) {
-        this.jwks_uri = jwks_uri;
-    }
-
-    public String getAuthorization_endpoint () {
-        return authorization_endpoint;
-    }
-
-    /**
-     * REQUIRED
-     * 
-     * @param authorization_endpoint
-     *            The authorisation endpoint URL.
-     */
-    public void setAuthorization_endpoint (String authorization_endpoint) {
-        this.authorization_endpoint = authorization_endpoint;
-    }
-
-    public String getToken_endpoint () {
-        return token_endpoint;
-    }
-
-    /**
-     * REQUIRED unless only the Implicit Flow is used.
-     * 
-     * @param token_endpoint
-     *            The token endpoint URL.
-     */
-    public void setToken_endpoint (String token_endpoint) {
-        this.token_endpoint = token_endpoint;
-    }
-
-    public String getUserinfo_endpoint () {
-        return userinfo_endpoint;
-    }
-
-    /**
-     * RECOMMENDED. The URL MUST use the https scheme.
-     * 
-     * @param userinfo_endpoint
-     *            The OpenID Connect UserInfo endpoint URL.
-     */
-    public void setUserinfo_endpoint (String userinfo_endpoint) {
-        this.userinfo_endpoint = userinfo_endpoint;
-    }
-
-    public String getRegistration_endpoint () {
-        return registration_endpoint;
-    }
-
-    /**
-     * RECOMMENDED
-     * 
-     * @param registration_endpoint
-     *            The OAuth 2.0 / OpenID Connect client registration
-     *            endpoint
-     *            URL.
-     */
-    public void setRegistration_endpoint (String registration_endpoint) {
-        this.registration_endpoint = registration_endpoint;
-    }
-
-    public String[] getScopes_supported () {
-        return scopes_supported;
-    }
-
-    /**
-     * RECOMMENDED
-     * 
-     * @param scopes_supported
-     *            List of the supported scope values. Certain
-     *            values may be omitted for privacy reasons.
-     */
-    public void setScopes_supported (String[] scopes_supported) {
-        this.scopes_supported = scopes_supported;
-    }
-
-    public String[] getResponse_types_supported () {
-        return response_types_supported;
-    }
-
-    /**
-     * REQUIRED
-     * 
-     * @param response_types_supported
-     *            List of the supported response_type
-     *            values.
-     */
-    public void setResponse_types_supported (
-            String[] response_types_supported) {
-        this.response_types_supported = response_types_supported;
-    }
-
-    public String[] getResponse_modes_supported () {
-        return response_modes_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param response_modes_supported
-     *            List of the supported response mode
-     *            values.
-     */
-    public void setResponse_modes_supported (
-            String[] response_modes_supported) {
-        this.response_modes_supported = response_modes_supported;
-    }
-
-    public String[] getGrant_types_supported () {
-        return grant_types_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param grant_types_supported
-     *            List of the supported grant types.
-     */
-    public void setGrant_types_supported (String[] grant_types_supported) {
-        this.grant_types_supported = grant_types_supported;
-    }
-
-    public String[] getAcr_values_supported () {
-        return acr_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param acr_values_supported
-     *            List of the supported Authentication Context Class
-     *            References.
-     */
-    public void setAcr_values_supported (String[] acr_values_supported) {
-        this.acr_values_supported = acr_values_supported;
-    }
-
-    public String[] getSubject_types_supported () {
-        return subject_types_supported;
-    }
-
-    /**
-     * REQUIRED
-     * 
-     * @param subject_types_supported
-     *            List of the supported subject (end-user) identifier
-     *            types.
-     */
-    public void setSubject_types_supported (String[] subject_types_supported) {
-        this.subject_types_supported = subject_types_supported;
-    }
-
-    public String[] getId_token_signing_alg_values_supported () {
-        return id_token_signing_alg_values_supported;
-    }
-
-    /**
-     * REQUIRED
-     * 
-     * @param id_token_signing_alg_values_supported
-     *            List of the supported JWS algorithms for
-     *            the issued ID tokens to encode claims in a JWT.
-     */
-    public void setId_token_signing_alg_values_supported (
-            String[] id_token_signing_alg_values_supported) {
-        this.id_token_signing_alg_values_supported =
-                id_token_signing_alg_values_supported;
-    }
-
-    public String[] getId_token_encryption_alg_values_supported () {
-        return id_token_encryption_alg_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param id_token_encryption_alg_values_supported
-     *            List of the supported JWE algorithms for
-     *            the issued ID tokens to encode claims in a JWT.
-     */
-    public void setId_token_encryption_alg_values_supported (
-            String[] id_token_encryption_alg_values_supported) {
-        this.id_token_encryption_alg_values_supported =
-                id_token_encryption_alg_values_supported;
-    }
-
-    public String[] getId_token_encryption_enc_values_supported () {
-        return id_token_encryption_enc_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param id_token_encryption_enc_values_supported
-     *            List of the supported JWE encryption methods for
-     *            the issued ID tokens to encode claims in a JWT.
-     */
-    public void setId_token_encryption_enc_values_supported (
-            String[] id_token_encryption_enc_values_supported) {
-        this.id_token_encryption_enc_values_supported =
-                id_token_encryption_enc_values_supported;
-    }
-
-    public String[] getUserinfo_signing_alg_values_supported () {
-        return userinfo_signing_alg_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param userinfo_signing_alg_values_supported
-     *            List of the supported signing JWS algorithms for
-     *            encoding the claims in a JWT returned at the
-     *            UserInfo endpoint.
-     */
-    public void setUserinfo_signing_alg_values_supported (
-            String[] userinfo_signing_alg_values_supported) {
-        this.userinfo_signing_alg_values_supported =
-                userinfo_signing_alg_values_supported;
-    }
-
-    public String[] getUserinfo_encryption_alg_values_supported () {
-        return userinfo_encryption_alg_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param userinfo_encryption_alg_values_supported
-     *            List of the supported JWE encryption algorithms for
-     *            encoding the claims in a JWT returned at the
-     *            UserInfo endpoint.
-     */
-    public void setUserinfo_encryption_alg_values_supported (
-            String[] userinfo_encryption_alg_values_supported) {
-        this.userinfo_encryption_alg_values_supported =
-                userinfo_encryption_alg_values_supported;
-    }
-
-    public String[] getUserinfo_encryption_enc_values_supported () {
-        return userinfo_encryption_enc_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param userinfo_encryption_enc_values_supported
-     *            List of the supported JWE encryption methods for
-     *            encoding the claims in a JWT returned at the
-     *            UserInfo endpoint.
-     */
-    public void setUserinfo_encryption_enc_values_supported (
-            String[] userinfo_encryption_enc_values_supported) {
-        this.userinfo_encryption_enc_values_supported =
-                userinfo_encryption_enc_values_supported;
-    }
-
-    public String[] getRequest_object_signing_alg_values_supported () {
-        return request_object_signing_alg_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param request_object_signing_alg_values_supported
-     *            JSON array containing a list of supported JWS
-     *            signing algorithms (alg values) supported for
-     *            Request Objects
-     */
-    public void setRequest_object_signing_alg_values_supported (
-            String[] request_object_signing_alg_values_supported) {
-        this.request_object_signing_alg_values_supported =
-                request_object_signing_alg_values_supported;
-    }
-
-    public String[] getRequest_object_encryption_alg_values_supported () {
-        return request_object_encryption_alg_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param request_object_encryption_alg_values_supported
-     *            List of the supported JWE encryption algorithms for
-     *            OpenID Connect request objects
-     */
-    public void setRequest_object_encryption_alg_values_supported (
-            String[] request_object_encryption_alg_values_supported) {
-        this.request_object_encryption_alg_values_supported =
-                request_object_encryption_alg_values_supported;
-    }
-
-    public String[] getRequest_object_encryption_enc_values_supported () {
-        return request_object_encryption_enc_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param request_object_encryption_enc_values_supported
-     *            List of the supported JWE encryption methods for
-     *            OpenID Connect request objects, omitted or empty if
-     *            none.
-     */
-    public void setRequest_object_encryption_enc_values_supported (
-            String[] request_object_encryption_enc_values_supported) {
-        this.request_object_encryption_enc_values_supported =
-                request_object_encryption_enc_values_supported;
-    }
-
-    public String[] getToken_endpoint_auth_methods_supported () {
-        return token_endpoint_auth_methods_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param token_endpoint_auth_methods_supported
-     *            List of the supported client authentication methods
-     *            at the token endpoint.
-     */
-    public void setToken_endpoint_auth_methods_supported (
-            String[] token_endpoint_auth_methods_supported) {
-        this.token_endpoint_auth_methods_supported =
-                token_endpoint_auth_methods_supported;
-    }
-
-    public String[] getToken_endpoint_auth_signing_alg_values_supported () {
-        return token_endpoint_auth_signing_alg_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param token_endpoint_auth_signing_alg_values_supported
-     *            List of the supported JWS algorithms for JWT-based
-     *            client authentication at the token endpoint
-     */
-    public void setToken_endpoint_auth_signing_alg_values_supported (
-            String[] token_endpoint_auth_signing_alg_values_supported) {
-        this.token_endpoint_auth_signing_alg_values_supported =
-                token_endpoint_auth_signing_alg_values_supported;
-    }
-
-    public String[] getDisplay_values_supported () {
-        return display_values_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param display_values_supported
-     *            List of the supported display parameters.
-     */
-    public void setDisplay_values_supported (
-            String[] display_values_supported) {
-        this.display_values_supported = display_values_supported;
-    }
-
-    public String[] getClaim_types_supported () {
-        return claim_types_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param claim_types_supported
-     *            List of the supported OpenID Connect claim types.
-     */
-    public void setClaim_types_supported (String[] claim_types_supported) {
-        this.claim_types_supported = claim_types_supported;
-    }
-
-    public String[] getClaims_supported () {
-        return claims_supported;
-    }
-
-    /**
-     * RECOMMENDED
-     * 
-     * @param claims_supported
-     *            List of the supported OpenID Connect claims.
-     */
-    public void setClaims_supported (String[] claims_supported) {
-        this.claims_supported = claims_supported;
-    }
-
-    public String getService_documentation () {
-        return service_documentation;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param service_documentation
-     *            The service documentation URL
-     */
-    public void setService_documentation (String service_documentation) {
-        this.service_documentation = service_documentation;
-    }
-
-    public String[] getClaims_locales_supported () {
-        return claims_locales_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param claims_locales_supported
-     *            List of the supported OpenID Connect claims locales
-     */
-    public void setClaims_locales_supported (
-            String[] claims_locales_supported) {
-        this.claims_locales_supported = claims_locales_supported;
-    }
-
-    public String[] getUi_locales_supported () {
-        return ui_locales_supported;
-    }
-
-    /**
-     * OPTIONAL
-     * 
-     * @param ui_locales_supported
-     *            List of the supported UI locales
-     */
-    public void setUi_locales_supported (String[] ui_locales_supported) {
-        this.ui_locales_supported = ui_locales_supported;
-    }
-
-    public boolean isClaims_parameter_supported () {
-        return claims_parameter_supported;
-    }
-
-    /**
-     * OPTIONAL. Default false.
-     * 
-     * @param claims_parameter_supported
-     *            Specifies whether the claims request parameter is
-     *            supported.
-     */
-    public void setClaims_parameter_supported (
-            boolean claims_parameter_supported) {
-        this.claims_parameter_supported = claims_parameter_supported;
-    }
-
-    public boolean isRequest_parameter_supported () {
-        return request_parameter_supported;
-    }
-
-    /**
-     * OPTIONAL. Default false.
-     * 
-     * @param request_parameter_supported
-     *            Specifies whether the request parameter is
-     *            supported.
-     */
-    public void setRequest_parameter_supported (
-            boolean request_parameter_supported) {
-        this.request_parameter_supported = request_parameter_supported;
-    }
-
-    public boolean isRequest_uri_parameter_supported () {
-        return request_uri_parameter_supported;
-    }
-
-    /**
-     * OPTIONAL. Default true.
-     * 
-     * @param request_uri_parameter_supported
-     *            Specifies whether the request_uri parameter is
-     *            supported.
-     */
-    public void setRequest_uri_parameter_supported (
-            boolean request_uri_parameter_supported) {
-        this.request_uri_parameter_supported = request_uri_parameter_supported;
-    }
-
-    public boolean isRequire_request_uri_registration () {
-        return require_request_uri_registration;
-    }
-
-    /**
-     * OPTIONAL. Default false.
-     * 
-     * @param require_request_uri_registration
-     *            Specifies whether request URIs must be registered
-     *            for a client.
-     */
-    public void setRequire_request_uri_registration (
-            boolean require_request_uri_registration) {
-        this.require_request_uri_registration =
-                require_request_uri_registration;
-    }
-
-    public String getOp_policy_uri () {
-        return op_policy_uri;
-    }
-
-    /**
-     * OPTIONAL. URL that the OpenID Provider provides to the person
-     * registering the Client to read about the requirements on
-     * how the client can use the data provided by the OpenID
-     * Provider. The registration process SHOULD display this URL to
-     * the person registering the Client if it is given.
-     * 
-     * @param op_policy_uri
-     *            The privacy policy document URL, omitted if none.
-     */
-    public void setOp_policy_uri (String op_policy_uri) {
-        this.op_policy_uri = op_policy_uri;
-    }
-
-    public String getOp_tos_uri () {
-        return op_tos_uri;
-    }
-
-    /**
-     * @param op_tos_uri
-     *            The terms of service document URL, omitted if none.
-     */
-    public void setOp_tos_uri (String op_tos_uri) {
-        this.op_tos_uri = op_tos_uri;
-    }
-
-    public String getIntrospection_endpoint () {
-        return introspection_endpoint;
-    }
-
-    /**
-     * ADDITIONAL
-     * 
-     * @param introspection_endpoint
-     *            The token introspection endpoint URL.
-     */
-    public void setIntrospection_endpoint (String introspection_endpoint) {
-        this.introspection_endpoint = introspection_endpoint;
-    }
-
-    public String getRevocation_endpoint () {
-        return revocation_endpoint;
-    }
-
-    /**
-     * ADDITIONAL
-     * 
-     * @param revocation_endpoint
-     *            The token revocation endpoint URL.
-     */
-    public void setRevocation_endpoint (String revocation_endpoint) {
-        this.revocation_endpoint = revocation_endpoint;
-    }
-
-    public String getEnd_session_endpoint () {
-        return end_session_endpoint;
-    }
-
-    /**
-     * ADDITIONAL
-     * 
-     * @param end_session_endpoint
-     *            The OpenID Connect logout endpoint URL, omitted if
-     *            disabled.
-     */
-    public void setEnd_session_endpoint (String end_session_endpoint) {
-        this.end_session_endpoint = end_session_endpoint;
-    }
-
-    public boolean isMutual_tls_sender_constrained_access_tokens () {
-        return mutual_tls_sender_constrained_access_tokens;
-    }
-
-    /**
-     * OPTIONAL. Default false.
-     * 
-     * @see <a
-     *      href="https://tools.ietf.org/id/draft-ietf-oauth-mtls-03.html#server_metadata">Mutual
-     *      TLS Profile for OAuth 2.0</a>
-     * @param mutual_tls_sender_constrained_access_tokens
-     *            specifies whether issue of client X.509 certificate
-     *            bound access tokens is supported, omitted
-     *            implies no support.
-     */
-    public void setMutual_tls_sender_constrained_access_tokens (
-            boolean mutual_tls_sender_constrained_access_tokens) {
-        this.mutual_tls_sender_constrained_access_tokens =
-                mutual_tls_sender_constrained_access_tokens;
-    }
-}
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/OpenIdHttpRequestWrapper.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/OpenIdHttpRequestWrapper.java
deleted file mode 100644
index 998d1eb..0000000
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/OpenIdHttpRequestWrapper.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package de.ids_mannheim.korap.oauth2.openid;
-
-import java.net.URL;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.oauth2.sdk.http.HTTPRequest;
-
-/** A request wrapper based on HTTPRequest.
- * 
- * @author margaretha
- *
- */
-public class OpenIdHttpRequestWrapper extends HTTPRequest {
-
-    private Map<String, List<String>> params;
-
-    public OpenIdHttpRequestWrapper (Method method, URL url) {
-        super(method, url);
-    }
-
-    @Override
-    public Map<String, List<String>> getQueryParameters () {
-        return this.params;
-    }
-
-    public void toHttpRequest (HttpServletRequest servletRequest,
-                               Map<String, List<String>> map) throws ParseException {
-
-        this.params = map;
-        this.setClientIPAddress(servletRequest.getRemoteAddr());
-        this.setContentType(servletRequest.getContentType());
-
-        Enumeration<String> headerNames = servletRequest.getHeaderNames();
-        while (headerNames.hasMoreElements()) {
-            String name = headerNames.nextElement().toString();
-            this.setHeader(name, servletRequest.getHeader(name));
-        }
-    }
-}
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/JWKService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/JWKService.java
deleted file mode 100644
index df9fb17..0000000
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/JWKService.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package de.ids_mannheim.korap.oauth2.openid.service;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.NoSuchAlgorithmException;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.interfaces.RSAPublicKey;
-import java.util.UUID;
-
-import org.json.JSONObject;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import com.nimbusds.jose.jwk.JWK;
-import com.nimbusds.jose.jwk.JWKSet;
-import com.nimbusds.jose.jwk.RSAKey;
-
-import de.ids_mannheim.korap.config.FullConfiguration;
-
-/** JWK services for generating key pair and key set.
- * 
- * @author margaretha
- *
- */
-@Service
-public class JWKService {
-
-    @Autowired
-    private FullConfiguration config;
-
-    public static void main (String[] args)
-            throws NoSuchAlgorithmException, IOException {
-        generateJWK();
-    }
-
-    public static void generateJWK ()
-            throws NoSuchAlgorithmException, IOException {
-        KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
-        gen.initialize(2048);
-        KeyPair keyPair = gen.generateKeyPair();
-
-        // Convert to JWK format
-        JWK jwk = new RSAKey.Builder((RSAPublicKey) keyPair.getPublic())
-                .privateKey((RSAPrivateKey) keyPair.getPrivate())
-                .keyID(UUID.randomUUID().toString()).build();
-
-        // write private key
-        JSONObject json = new JSONObject(jwk.toJSONString());
-        OutputStreamWriter writer = new OutputStreamWriter(
-                new FileOutputStream("kustvakt_rsa.key"));
-        writer.write(json.toString(2));
-        writer.flush();
-        writer.close();
-
-        JWK publicJWK = jwk.toPublicJWK();
-        JWKSet jwkSet = new JWKSet(publicJWK);
-        json = new JSONObject(jwkSet.toString());
-        // write public key
-        writer = new OutputStreamWriter(
-                new FileOutputStream("kustvakt_rsa_public.key"));
-        writer.write(json.toString(2));
-        writer.flush();
-        writer.close();
-    }
-
-    /**
-     * Generates indented JSON string representation of kustvakt
-     * public keys
-     * 
-     * @return json string of kustvakt public keys
-     * 
-     * @see RFC 8017 regarding RSA specifications
-     * @see RFC 7517 regarding JWK (Json Web Key) and JWK Set
-     * 
-     */
-    public String generatePublicKeySetJson () {
-        JWKSet jwkSet = config.getPublicKeySet();
-        JSONObject json = new JSONObject(jwkSet.toString());
-        return json.toString(2);
-    }
-}
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdAuthorizationService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdAuthorizationService.java
deleted file mode 100644
index 87e71c3..0000000
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdAuthorizationService.java
+++ /dev/null
@@ -1,245 +0,0 @@
-package de.ids_mannheim.korap.oauth2.openid.service;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.time.ZoneId;
-import java.time.ZonedDateTime;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.List;
-import java.util.Set;
-
-import javax.ws.rs.core.MultivaluedMap;
-
-import org.apache.commons.validator.routines.UrlValidator;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import com.nimbusds.oauth2.sdk.AuthorizationCode;
-import com.nimbusds.oauth2.sdk.AuthorizationRequest;
-import com.nimbusds.oauth2.sdk.AuthorizationSuccessResponse;
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.oauth2.sdk.ResponseMode;
-import com.nimbusds.oauth2.sdk.ResponseType;
-import com.nimbusds.oauth2.sdk.Scope;
-import com.nimbusds.oauth2.sdk.id.State;
-import com.nimbusds.openid.connect.sdk.AuthenticationRequest;
-import com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse;
-import com.nimbusds.openid.connect.sdk.Nonce;
-
-import de.ids_mannheim.korap.config.Attributes;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
-import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
-import de.ids_mannheim.korap.oauth2.service.OAuth2AuthorizationService;
-
-/** Authorization service implementation using open id. 
- * 
- * @author margaretha
- *
- */
-@Service
-public class OpenIdAuthorizationService extends OAuth2AuthorizationService {
-
-    @Autowired
-    private UrlValidator redirectURIValidator;
-
-    public void checkRedirectUriParam (Map<String, String> map)
-            throws KustvaktException {
-        if (map.containsKey("redirect_uri")) {
-            String redirect_uri = map.get("redirect_uri");
-            if (redirect_uri != null && !redirect_uri.isEmpty()) {
-                if (!redirectURIValidator.isValid(redirect_uri)) {
-                    throw new KustvaktException(
-                            StatusCodes.INVALID_REDIRECT_URI,
-                            "Invalid redirect URI",
-                            OAuth2Error.INVALID_REQUEST);
-                }
-                return;
-            }
-        }
-
-        throw new KustvaktException(StatusCodes.MISSING_REDIRECT_URI,
-                "redirect_uri is required", OAuth2Error.INVALID_REQUEST);
-    }
-
-    public URI requestAuthorizationCode (MultivaluedMap<String, String> map,
-            String username, boolean isAuthentication,
-            ZonedDateTime authenticationTime)
-            throws KustvaktException, ParseException {
-
-        AuthorizationCode code = new AuthorizationCode();
-        URI redirectUri = null;
-
-        if (isAuthentication) {
-            AuthenticationRequest authRequest = null;
-            authRequest = AuthenticationRequest.parse((Map<String,List<String>>) map);
-            redirectUri = handleAuthenticationRequest(authRequest, code,
-                    username, authenticationTime);
-            return new AuthenticationSuccessResponse(redirectUri, code, null,
-                    null, authRequest.getState(), null, null).toURI();
-        }
-        else {
-            AuthorizationRequest authzRequest = AuthorizationRequest.parse((Map<String,List<String>>) map);
-            redirectUri = handleAuthorizationRequest(authzRequest, code,
-                    username, authenticationTime, null);
-            return new AuthorizationSuccessResponse(redirectUri, code, null,
-                    authzRequest.getState(), null).toURI();
-
-        }
-    }
-
-    private URI handleAuthorizationRequest (AuthorizationRequest authzRequest,
-            AuthorizationCode code, String username,
-            ZonedDateTime authenticationTime, String nonce)
-            throws KustvaktException {
-
-        URI redirectUri = authzRequest.getRedirectionURI();
-        String redirectUriStr =
-                (redirectUri != null) ? redirectUri.toString() : null;
-
-        String clientId = authzRequest.getClientID().getValue();
-        OAuth2Client client = clientService.authenticateClientId(clientId);
-        String verifiedRedirectUri = verifyRedirectUri(client, redirectUriStr);
-
-        try {
-            redirectUri = new URI(verifiedRedirectUri);
-        }
-        catch (URISyntaxException e) {
-            throw new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
-                    "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
-        }
-
-        try {
-            ResponseType responseType = authzRequest.getResponseType();
-            checkResponseType(responseType.toString());
-
-            Scope scope = authzRequest.getScope();
-            Set<String> scopeSet = null;
-            if (scope != null) {
-                scopeSet = new HashSet<>(scope.toStringList());
-            }
-            createAuthorization(username, clientId, redirectUriStr, scopeSet,
-                    code.getValue(), authenticationTime, nonce);
-        }
-        catch (KustvaktException e) {
-            e.setRedirectUri(redirectUri);
-            throw e;
-        }
-
-        return redirectUri;
-    }
-
-
-    /**
-     * Kustvakt does not support the following parameters:
-     * <em>claims</em>, <em>requestURI</em>, <em>requestObject</em>,
-     * <em>id_token_hint</em>, and ignores them if they are included
-     * in an authentication request. Kustvakt provides minimum support
-     * for <em>acr_values</em> by not throwing an error when it is
-     * included in an authentication request.
-     * 
-     * <p>Parameters related to user interface are also ignored,
-     * namely <em>display</em>, <em>prompt</em>,
-     * <em>ui_locales</em>, <em>login_hint</em>. However,
-     * <em>display</em>, <em>prompt</em>, and <em>ui_locales</em>
-     * must be supported by Kalamar. The minimum level of
-     * support required for these parameters is simply that its use
-     * must not result in an error.</p>
-     * 
-     * <p>Some Authentication request parameters in addition to
-     * OAuth2.0 authorization parameters according to OpenID connect
-     * core 1.0 Specification:</p>
-     * 
-     * <ul>
-     * 
-     * <li>nonce</li>
-     * <p> OPTIONAL. The value is passed through unmodified from the
-     * Authentication Request to the ID Token.</p>
-     * 
-     * <li>max_age</li>
-     * <p>OPTIONAL. Maximum Authentication Age in seconds. If the
-     * elapsed time is
-     * greater than this value, the OpenID Provider MUST attempt
-     * to actively re-authenticate the End-User. When max_age is used,
-     * the ID Token returned MUST include an auth_time Claim
-     * Value.</p>
-     * 
-     * <li>claims</li>
-     * <p>Support for the claims parameter is OPTIONAL. Should an OP
-     * (openid provider) not support this parameter and an RP (relying
-     * party /client) uses it, the OP SHOULD return a set of Claims to
-     * the RP that it believes would be useful to the RP and the
-     * End-User using whatever heuristics it believes are
-     * appropriate.</p>
-     * 
-     * </ul>
-     * 
-     * @see "OpenID Connect Core 1.0 specification"
-     * 
-     * @param authRequest
-     * @param code
-     * @param username
-     * @param authenticationTime
-     * @return
-     * @throws KustvaktException
-     */
-    private URI handleAuthenticationRequest (AuthenticationRequest authRequest,
-            AuthorizationCode code, String username,
-            ZonedDateTime authenticationTime) throws KustvaktException {
-        // TO DO: extra checking for authentication params?
-
-        Nonce nonce = authRequest.getNonce();
-        String nonceValue = null;
-        if (nonce != null && !nonce.getValue().isEmpty()) {
-            nonceValue = nonce.getValue();
-        }
-
-        checkMaxAge(authRequest.getMaxAge(), authenticationTime);
-
-        AuthorizationRequest request = authRequest;
-        return handleAuthorizationRequest(request, code, username,
-                authenticationTime, nonceValue);
-    }
-
-    private void checkMaxAge (int maxAge, ZonedDateTime authenticationTime)
-            throws KustvaktException {
-        if (maxAge > 0) {
-            ZonedDateTime now =
-                    ZonedDateTime.now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE));
-
-            if (authenticationTime.plusSeconds(maxAge).isBefore(now)) {
-                throw new KustvaktException(
-                        StatusCodes.USER_REAUTHENTICATION_REQUIRED,
-                        "User reauthentication is required because the authentication "
-                                + "time is too old according to max_age");
-            }
-        }
-    }
-
-    @Override
-    protected void checkResponseType (String responseType)
-            throws KustvaktException {
-        String[] types = responseType.split(" ");
-        for (String type : types) {
-            super.checkResponseType(type);
-        }
-    }
-
-    public State retrieveState (Map<String, String> map) {
-        String stateStr = map.get("state");
-        if (stateStr != null && stateStr.isEmpty()) {
-            return new State(stateStr);
-        }
-        return null;
-    }
-
-    public ResponseMode retrieveResponseMode (Map<String, String> map) {
-        String str = map.get("response_mode");
-        if (str != null && str.isEmpty()) {
-            return new ResponseMode(str);
-        }
-        return null;
-    }
-}
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdConfigService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdConfigService.java
deleted file mode 100644
index bcec0fa..0000000
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdConfigService.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package de.ids_mannheim.korap.oauth2.openid.service;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import de.ids_mannheim.korap.config.FullConfiguration;
-import de.ids_mannheim.korap.oauth2.openid.OpenIdConfiguration;
-
-/**
- * @author margaretha
- *
- */
-@Service
-public class OpenIdConfigService {
-
-    @Autowired
-    private FullConfiguration config;
-
-    public OpenIdConfiguration retrieveOpenIdConfigInfo () {
-        return config.getOpenidConfig();
-    }
-}
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdTokenService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdTokenService.java
deleted file mode 100644
index 93692ad..0000000
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/openid/service/OpenIdTokenService.java
+++ /dev/null
@@ -1,382 +0,0 @@
-package de.ids_mannheim.korap.oauth2.openid.service;
-
-import java.net.URI;
-import java.security.PrivateKey;
-import java.time.ZonedDateTime;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import com.nimbusds.jose.JOSEException;
-import com.nimbusds.jose.JWSAlgorithm;
-import com.nimbusds.jose.JWSHeader;
-import com.nimbusds.jose.JWSSigner;
-import com.nimbusds.jose.crypto.RSASSASigner;
-import com.nimbusds.jwt.JWTClaimsSet;
-import com.nimbusds.jwt.SignedJWT;
-import com.nimbusds.oauth2.sdk.AccessTokenResponse;
-import com.nimbusds.oauth2.sdk.AuthorizationCodeGrant;
-import com.nimbusds.oauth2.sdk.AuthorizationGrant;
-import com.nimbusds.oauth2.sdk.GrantType;
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.oauth2.sdk.ResourceOwnerPasswordCredentialsGrant;
-import com.nimbusds.oauth2.sdk.Scope;
-import com.nimbusds.oauth2.sdk.TokenRequest;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
-import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
-import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
-import com.nimbusds.oauth2.sdk.auth.ClientSecretPost;
-import com.nimbusds.oauth2.sdk.id.Audience;
-import com.nimbusds.oauth2.sdk.id.ClientID;
-import com.nimbusds.oauth2.sdk.id.Issuer;
-import com.nimbusds.oauth2.sdk.id.Subject;
-import com.nimbusds.oauth2.sdk.token.AccessToken;
-import com.nimbusds.oauth2.sdk.token.BearerAccessToken;
-import com.nimbusds.oauth2.sdk.token.RefreshToken;
-import com.nimbusds.oauth2.sdk.token.Tokens;
-import com.nimbusds.openid.connect.sdk.Nonce;
-import com.nimbusds.openid.connect.sdk.OIDCTokenResponse;
-import com.nimbusds.openid.connect.sdk.claims.IDTokenClaimsSet;
-import com.nimbusds.openid.connect.sdk.token.OIDCTokens;
-
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
-import de.ids_mannheim.korap.oauth2.dao.AccessTokenDao;
-import de.ids_mannheim.korap.oauth2.dao.RefreshTokenDao;
-import de.ids_mannheim.korap.oauth2.entity.AccessScope;
-import de.ids_mannheim.korap.oauth2.entity.Authorization;
-import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
-import de.ids_mannheim.korap.oauth2.service.OAuth2TokenService;
-import de.ids_mannheim.korap.utils.TimeUtils;
-
-/**
- * Token service implementation using OpenId.
- * 
- * ID Tokens MUST be signed using JWS and optionally both signed and
- * then encrypted using JWS [JWS] and JWE [JWE] respectively.
- * 
- * ID Tokens MUST NOT use none as the alg value unless the Response
- * Type used returns no ID Token from the Authorization Endpoint (such
- * as when using the Authorization Code Flow) and the Client
- * explicitly requested the use of none at Registration time.
- * 
- * ID Tokens SHOULD NOT use the JWS or JWE x5u, x5c, jku, or jwk
- * Header Parameter fields.
- * 
- * @author margaretha
- *
- */
-@Service
-public class OpenIdTokenService extends OAuth2TokenService {
-
-    @Autowired
-    private AccessTokenDao tokenDao;
-    @Autowired
-    private RefreshTokenDao refreshDao;
-
-    public AccessTokenResponse requestAccessToken (TokenRequest tokenRequest)
-            throws KustvaktException {
-        AuthorizationGrant grant = tokenRequest.getAuthorizationGrant();
-        GrantType grantType = grant.getType();
-        ClientAuthentication clientAuthentication =
-                tokenRequest.getClientAuthentication();
-        ClientID clientId = tokenRequest.getClientID();
-
-        if (grantType.equals(GrantType.AUTHORIZATION_CODE)) {
-            return requestAccessTokenWithAuthorizationCode(grant,
-                    clientAuthentication, clientId);
-        }
-        else if (grantType.equals(GrantType.PASSWORD)) {
-            ResourceOwnerPasswordCredentialsGrant passwordGrant =
-                    (ResourceOwnerPasswordCredentialsGrant) grant;
-            return requestAccessTokenWithPassword(passwordGrant.getUsername(),
-                    passwordGrant.getPassword().getValue(),
-                    tokenRequest.getScope(), clientAuthentication, clientId);
-        }
-        else if (grantType.equals(GrantType.CLIENT_CREDENTIALS)) {
-
-        }
-        else {
-            throw new KustvaktException(StatusCodes.UNSUPPORTED_GRANT_TYPE,
-                    grantType + " is not supported.",
-                    OAuth2Error.UNSUPPORTED_GRANT_TYPE);
-        }
-        return null;
-    }
-
-    /**
-     * 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
-     *            password, required
-     * @param scope
-     *            scope, optional
-     * @param clientAuthentication
-     * @param clientId
-     * @return
-     * @throws KustvaktException
-     */
-    private AccessTokenResponse requestAccessTokenWithPassword (String username,
-            String password, Scope scope,
-            ClientAuthentication clientAuthentication, ClientID clientId)
-            throws KustvaktException {
-
-        Set<String> scopeSet = null;
-        if (scope != null) {
-            scopeSet = new HashSet<String>();
-            scopeSet.addAll(scope.toStringList());
-        }
-        else {
-            scopeSet = config.getDefaultAccessScopes();
-            scope = new Scope(scopeSet.toArray(new String[scopeSet.size()]));
-        }
-
-        ZonedDateTime authenticationTime;
-        String clientIdStr = null;
-        OAuth2Client client;
-        if (clientAuthentication == null) {
-            if (clientId == null) {
-                throw new KustvaktException(StatusCodes.MISSING_PARAMETER,
-                        "Missing parameter: client_id",
-                        OAuth2Error.INVALID_REQUEST);
-            }
-            else {
-                clientIdStr = clientId.getValue();
-                client = clientService.authenticateClient(clientIdStr, null);
-            }
-        }
-        else {
-            String[] clientCredentials =
-                    extractClientCredentials(clientAuthentication);
-            clientIdStr = clientCredentials[0];
-            client = clientService.authenticateClient(clientCredentials[0],
-                    clientCredentials[1]);
-        }
-
-        if (!client.isSuper()) {
-            throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
-                    "Password grant is not allowed for third party clients",
-                    OAuth2Error.UNAUTHORIZED_CLIENT);
-        }
-
-        authenticationTime = authenticateUser(username, password, scopeSet);
-
-        AccessToken accessToken =
-                new BearerAccessToken(config.getAccessTokenExpiry(), scope);
-
-        RefreshToken refreshToken = new RefreshToken();
-        Set<AccessScope> scopes = scopeService.convertToAccessScope(scopeSet);
-        de.ids_mannheim.korap.oauth2.entity.RefreshToken rt =
-                refreshDao.storeRefreshToken(refreshToken.getValue(), username,
-                        authenticationTime, client, scopes);
-        tokenDao.storeAccessToken(accessToken.getValue(), rt, scopes, username,
-                clientIdStr, authenticationTime);
-
-        return createsAccessTokenResponse(accessToken, refreshToken, scope,
-                clientIdStr, username, authenticationTime, null);
-    }
-
-    private AccessTokenResponse requestAccessTokenWithAuthorizationCode (
-            AuthorizationGrant grant, ClientAuthentication clientAuthentication,
-            ClientID clientId) throws KustvaktException {
-        AuthorizationCodeGrant codeGrant = (AuthorizationCodeGrant) grant;
-        String authorizationCode = codeGrant.getAuthorizationCode().getValue();
-        URI redirectionURI = codeGrant.getRedirectionURI();
-        String redirectURI = null;
-        if (redirectionURI != null) {
-            redirectURI = redirectionURI.toString();
-        }
-
-        Authorization authorization = null;
-        if (clientAuthentication == null) {
-            if (clientId == null) {
-                throw new KustvaktException(StatusCodes.MISSING_PARAMETER,
-                        "Missing parameter: client_id",
-                        OAuth2Error.INVALID_REQUEST);
-            }
-            else {
-                authorization = retrieveAuthorization(authorizationCode,
-                        redirectURI, clientId.getValue(), null);
-            }
-        }
-        else {
-            String[] clientCredentials =
-                    extractClientCredentials(clientAuthentication);
-            authorization = retrieveAuthorization(authorizationCode,
-                    redirectURI, clientCredentials[0], clientCredentials[1]);
-        }
-
-        return createsAccessTokenResponse(authorization);
-
-    }
-
-    private AccessTokenResponse createsAccessTokenResponse (
-            Authorization authorization) throws KustvaktException {
-        Set<AccessScope> scopes = authorization.getScopes();
-        String[] scopeArray = scopes.stream().map(scope -> scope.toString())
-                .toArray(String[]::new);
-        Scope scope = new Scope(scopeArray);
-        AccessToken accessToken =
-                new BearerAccessToken(config.getAccessTokenExpiry(), scope);
-        RefreshToken refreshToken = new RefreshToken();
-        OAuth2Client client =
-                clientService.retrieveClient(authorization.getClientId());
-        
-        de.ids_mannheim.korap.oauth2.entity.RefreshToken rt =
-                refreshDao.storeRefreshToken(refreshToken.getValue(),
-                        authorization.getUserId(),
-                        authorization.getUserAuthenticationTime(),
-                        client, scopes);
-
-        tokenDao.storeAccessToken(accessToken.getValue(), rt, scopes,
-                authorization.getUserId(), authorization.getClientId(),
-                authorization.getUserAuthenticationTime());
-
-        return createsAccessTokenResponse(accessToken, refreshToken, scope,
-                authorization.getClientId(), authorization.getUserId(),
-                authorization.getUserAuthenticationTime(),
-                authorization.getNonce());
-    }
-
-    private AccessTokenResponse createsAccessTokenResponse (
-            AccessToken accessToken, RefreshToken refreshToken, Scope scope,
-            String clientId, String userId,
-            ZonedDateTime userAuthenticationTime, String nonce)
-            throws KustvaktException {
-
-        if (scope.contains("openid")) {
-            JWTClaimsSet claims = createIdTokenClaims(clientId, userId,
-                    userAuthenticationTime, nonce);
-            SignedJWT idToken = signIdToken(claims,
-                    // default
-                    new JWSHeader(JWSAlgorithm.RS256),
-                    config.getRsaPrivateKey());
-            OIDCTokens tokens =
-                    new OIDCTokens(idToken, accessToken, refreshToken);
-            return new OIDCTokenResponse(tokens);
-        }
-        else {
-            Tokens tokens = new Tokens(accessToken, refreshToken);
-            return new AccessTokenResponse(tokens);
-        }
-    }
-
-    private String[] extractClientCredentials (
-            ClientAuthentication clientAuthentication)
-            throws KustvaktException {
-
-        ClientAuthenticationMethod method = clientAuthentication.getMethod();
-        String clientSecret;
-        String clientId;
-        if (method.equals(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)) {
-            ClientSecretBasic basic = (ClientSecretBasic) clientAuthentication;
-            clientSecret = basic.getClientSecret().getValue();
-            clientId = basic.getClientID().getValue();
-        }
-        else if (method.equals(ClientAuthenticationMethod.CLIENT_SECRET_POST)) {
-            ClientSecretPost post = (ClientSecretPost) clientAuthentication;
-            clientSecret = post.getClientSecret().getValue();
-            clientId = post.getClientID().getValue();
-        }
-        else {
-            // client authentication method is not supported
-            throw new KustvaktException(
-                    StatusCodes.UNSUPPORTED_AUTHENTICATION_METHOD,
-                    method.getValue() + " is not supported.",
-                    OAuth2Error.INVALID_CLIENT);
-        }
-        return new String[] { clientId, clientSecret };
-    }
-
-    private JWTClaimsSet createIdTokenClaims (String client_id, String username,
-            ZonedDateTime authenticationTime, String nonce)
-            throws KustvaktException {
-        // A locally unique and never reassigned identifier within the
-        // Issuer for the End-User
-        Subject sub = new Subject(username);
-        Issuer iss = new Issuer(config.getIssuerURI());
-        Audience aud = new Audience(client_id);
-        ArrayList<Audience> audList = new ArrayList<Audience>(1);
-        audList.add(aud);
-        Date iat = TimeUtils.getNow().toDate();
-        Date exp =
-                TimeUtils.getNow().plusSeconds(config.getTokenTTL()).toDate();
-
-        IDTokenClaimsSet claims =
-                new IDTokenClaimsSet(iss, sub, audList, exp, iat);
-
-        Date authTime = Date.from(authenticationTime.toInstant());
-        claims.setAuthenticationTime(authTime);
-        if (nonce != null && !nonce.isEmpty()) {
-            claims.setNonce(new Nonce(nonce));
-        }
-
-        try {
-            return claims.toJWTClaimsSet();
-        }
-        catch (ParseException e) {
-            throw new KustvaktException(StatusCodes.ID_TOKEN_CLAIM_ERROR,
-                    e.getMessage());
-        }
-    }
-
-    /**
-     * id token should be signed and additionally encrypted
-     * according to keys and algorithms the client specified
-     * during registration
-     * 
-     * Currently supporting only:
-     * default algorithm = RSA SHA-256 (RS256)
-     * 
-     * @param jwtClaimsSet
-     *            id token claim set
-     * @param jwsHeader
-     *            jws header
-     * @param privateKey
-     * 
-     * @return
-     * @throws KustvaktException
-     */
-    private SignedJWT signIdToken (JWTClaimsSet jwtClaimsSet,
-            JWSHeader jwsHeader, PrivateKey privateKey)
-            throws KustvaktException {
-
-        SignedJWT idToken = new SignedJWT(jwsHeader, jwtClaimsSet);
-        JWSSigner signer = null;
-        if (jwsHeader.getAlgorithm().equals(JWSAlgorithm.RS256)) {
-            signer = new RSASSASigner(privateKey);
-        }
-        else {
-            throw new KustvaktException(StatusCodes.ID_TOKEN_SIGNING_FAILED,
-                    "Unsupported algorithm "
-                            + jwsHeader.getAlgorithm().getName());
-        }
-
-        try {
-            idToken.sign(signer);
-        }
-        catch (JOSEException e) {
-            throw new KustvaktException(StatusCodes.ID_TOKEN_SIGNING_FAILED,
-                    e.getMessage());
-        }
-
-        return idToken;
-    }
-}
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 8da5caa..06960bb 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
@@ -1,20 +1,33 @@
 package de.ids_mannheim.korap.oauth2.service;
 
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.util.Set;
 
 import org.apache.commons.validator.routines.UrlValidator;
+import org.apache.http.HttpStatus;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import com.nimbusds.oauth2.sdk.AuthorizationCode;
+import com.nimbusds.oauth2.sdk.AuthorizationErrorResponse;
+import com.nimbusds.oauth2.sdk.AuthorizationRequest;
+import com.nimbusds.oauth2.sdk.AuthorizationSuccessResponse;
+import com.nimbusds.oauth2.sdk.ErrorObject;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.ResponseType;
+import com.nimbusds.oauth2.sdk.id.State;
+
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.FullConfiguration;
+import de.ids_mannheim.korap.encryption.RandomCodeGenerator;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
 import de.ids_mannheim.korap.oauth2.dao.AuthorizationDao;
 import de.ids_mannheim.korap.oauth2.entity.AccessScope;
 import de.ids_mannheim.korap.oauth2.entity.Authorization;
@@ -34,6 +47,8 @@
     public static boolean DEBUG = false;
     
     @Autowired
+    private RandomCodeGenerator codeGenerator;
+    @Autowired
     protected OAuth2ClientService clientService;
     @Autowired
     protected OAuth2ScopeServiceImpl scopeService;
@@ -44,22 +59,84 @@
 
     @Autowired
     protected FullConfiguration config;
+    
+    public State createAuthorizationState (String state) {
+        State authState = null;
+        if (state!=null && !state.isEmpty())
+            authState = new State(state);
+        return authState;
+    }
+    
+    public AuthorizationErrorResponse createAuthorizationError (
+            KustvaktException e, String state) {
+        State authState = createAuthorizationState(state);
+        ErrorObject error = e.getOauth2Error();
+        error = error.setDescription(e.getMessage());
+        AuthorizationErrorResponse errorResponse =
+                new AuthorizationErrorResponse(e.getRedirectUri(),
+                        error,authState, null);
+        return errorResponse;
+    }
+    
+    public URI requestAuthorizationCode (URI requestURI, String clientId,
+            String redirectUri, String scope, String state, String username,
+            ZonedDateTime authenticationTime) throws KustvaktException {
 
-    /**
-     * Authorization code request does not require client
-     * authentication, but only checks if the client id exists.
-     * 
-     * @param username
-     * @param clientId
-     * @param redirectUri
-     * @param scopeSet
-     * @param code
-     * @param authenticationTime
-     *            user authentication time
-     * @param nonce
-     * @return
-     * @throws KustvaktException
-     */
+        URI redirectURI = null;
+        String code;
+        try {
+            OAuth2Client client = clientService.authenticateClientId(clientId);
+            redirectURI = verifyRedirectUri(client, redirectUri);
+            //checkResponseType(authzRequest.getResponseType(), redirectURI);
+            code = codeGenerator.createRandomCode();
+            URI responseURI = createAuthorizationResponse(requestURI,
+                    redirectURI, code, state);
+
+            createAuthorization(username, clientId, redirectUri, scope,
+                    code.toString(), authenticationTime, null);
+            return responseURI;
+            
+        }
+        catch (KustvaktException e) {
+            e.setRedirectUri(redirectURI);
+            throw e;
+        }
+    }
+
+    private URI createAuthorizationResponse (URI requestURI, URI redirectURI,
+            String code, String state)
+            throws KustvaktException {
+        AuthorizationRequest authRequest = null;
+        try {
+            authRequest = AuthorizationRequest.parse(requestURI);
+
+            if (authRequest.getResponseType()
+                    .equals(new ResponseType(ResponseType.Value.CODE))) {
+
+                State authState = createAuthorizationState(state);
+                AuthorizationSuccessResponse response =
+                        new AuthorizationSuccessResponse(redirectURI,
+                                new AuthorizationCode(code), null, authState,
+                                null);
+                return response.toURI();
+            }
+            else {
+                KustvaktException ke = new KustvaktException(
+                        StatusCodes.UNSUPPORTED_RESPONSE_TYPE,
+                        "Unsupported response type. Only code is supported.",
+                        OAuth2Error.UNSUPPORTED_RESPONSE_TYPE);
+                throw ke;
+            }
+        }
+        catch (ParseException e) {
+            KustvaktException ke =
+                    new KustvaktException(StatusCodes.INVALID_REQUEST,
+                            e.getMessage(), OAuth2Error.INVALID_REQUEST_URI);
+            throw ke;
+        }
+
+    }
+    @Deprecated
     public String createAuthorization (String username, String clientId,
             String redirectUri, Set<String> scopeSet, String code,
             ZonedDateTime authenticationTime, String nonce)
@@ -75,6 +152,35 @@
                 scopes, redirectUri, authenticationTime, nonce);
         return String.join(" ", scopeSet);
     }
+    
+    /**
+     * Authorization code request does not require client
+     * authentication, but only checks if the client id exists.
+     * 
+     * @param username
+     * @param clientId
+     * @param redirectUri
+     * @param scopeSet
+     * @param code
+     * @param authenticationTime
+     *            user authentication time
+     * @param nonce
+     * @throws KustvaktException
+     */
+    public void createAuthorization (String username, String clientId,
+            String redirectUri, String scope, String code,
+            ZonedDateTime authenticationTime, String nonce)
+            throws KustvaktException {
+
+        if (scope == null || scope.isEmpty()) {
+            throw new KustvaktException(StatusCodes.MISSING_PARAMETER,
+                    "scope is required", OAuth2Error.INVALID_SCOPE);
+        }
+        Set<AccessScope> accessScopes = scopeService.convertToAccessScope(scope);
+
+        authorizationDao.storeAuthorizationCode(clientId, username, code,
+                accessScopes, redirectUri, authenticationTime, nonce);
+    }
 
     @Deprecated
     protected void checkResponseType (String responseType)
@@ -110,7 +216,7 @@
      * @return a client's redirect URI
      * @throws KustvaktException
      */
-    public String verifyRedirectUri (OAuth2Client client, String redirectUri)
+    public URI verifyRedirectUri (OAuth2Client client, String redirectUri)
             throws KustvaktException {
 
         String registeredUri = client.getRedirectURI();
@@ -133,8 +239,66 @@
                     "Missing parameter: redirect URI",
                     OAuth2Error.INVALID_REQUEST);
         }
+        URI redirectURI;
+        try {
+            redirectURI = new URI(redirectUri);
+        }
+        catch (URISyntaxException e) {
+            throw new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
+                    "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
+        }
+        
+        return redirectURI;
+    }
+    
+    public KustvaktException checkRedirectUri (KustvaktException e,
+            String clientId, String redirectUri){
+        int statusCode = e.getStatusCode();
+        if (clientId!=null && !clientId.isEmpty()
+                && statusCode != StatusCodes.CLIENT_NOT_FOUND
+                && statusCode != StatusCodes.AUTHORIZATION_FAILED
+                && statusCode != StatusCodes.INVALID_REDIRECT_URI) {
+            String registeredUri = null;
+            try {
+                OAuth2Client client = clientService.retrieveClient(clientId);
+                registeredUri = client.getRedirectURI();
+            }
+            catch (KustvaktException e1) {}
 
-        return redirectUri;
+            if (redirectUri != null && !redirectUri.isEmpty()) {
+                if (registeredUri != null && !registeredUri.isEmpty()
+                        && !redirectUri.equals(registeredUri)) {
+                    return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
+                            "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
+                }
+                else {
+                    try {
+                        e.setRedirectUri(new URI(redirectUri));
+                    }
+                    catch (URISyntaxException e1) {
+                        return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
+                                "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
+                    }
+                    e.setResponseStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
+                }
+            }
+            else if (registeredUri != null && !registeredUri.isEmpty()) {
+                try {
+                    e.setRedirectUri(new URI(registeredUri));
+                }
+                catch (URISyntaxException e1) {
+                    return new KustvaktException(StatusCodes.INVALID_REDIRECT_URI,
+                            "Invalid redirect URI", OAuth2Error.INVALID_REQUEST);
+                }
+                e.setResponseStatus(HttpStatus.SC_TEMPORARY_REDIRECT);
+            }
+            else {
+                return new KustvaktException(StatusCodes.MISSING_REDIRECT_URI,
+                        "Missing parameter: redirect URI", OAuth2Error.INVALID_REQUEST);
+            }
+        }
+
+        return e;
     }
 
     public Authorization retrieveAuthorization (String code)
@@ -205,4 +369,5 @@
         }
         return true;
     }
+
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java
index ee7aa91..55d85ab 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ClientService.java
@@ -13,6 +13,8 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+
 import de.ids_mannheim.korap.config.FullConfiguration;
 import de.ids_mannheim.korap.dao.AdminDao;
 import de.ids_mannheim.korap.dto.InstalledPluginDto;
@@ -22,7 +24,6 @@
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.interfaces.EncryptionIface;
 import de.ids_mannheim.korap.oauth2.constant.OAuth2ClientType;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
 import de.ids_mannheim.korap.oauth2.dao.AccessTokenDao;
 import de.ids_mannheim.korap.oauth2.dao.AuthorizationDao;
 import de.ids_mannheim.korap.oauth2.dao.InstalledPluginDao;
@@ -34,7 +35,6 @@
 import de.ids_mannheim.korap.oauth2.entity.Authorization;
 import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
 import de.ids_mannheim.korap.oauth2.entity.RefreshToken;
-import de.ids_mannheim.korap.oauth2.oltu.service.OltuTokenService;
 import de.ids_mannheim.korap.utils.ParameterChecker;
 import de.ids_mannheim.korap.web.input.OAuth2ClientJson;
 
@@ -66,7 +66,7 @@
 //                    UrlValidator.NO_FRAGMENTS + UrlValidator.ALLOW_LOCAL_URLS);
 
     @Autowired
-    private OltuTokenService tokenService;
+    private OAuth2TokenService tokenService;
     @Autowired
     private InstalledPluginDao pluginDao;
     @Autowired
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeServiceImpl.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeServiceImpl.java
index 9102ea3..56f0115 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeServiceImpl.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/service/OAuth2ScopeServiceImpl.java
@@ -10,13 +10,14 @@
 
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.constant.OAuth2Scope;
 import de.ids_mannheim.korap.constant.TokenType;
 import de.ids_mannheim.korap.dao.AdminDao;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
 import de.ids_mannheim.korap.oauth2.dao.AccessScopeDao;
 import de.ids_mannheim.korap.oauth2.entity.AccessScope;
 import de.ids_mannheim.korap.security.context.TokenContext;
@@ -41,6 +42,7 @@
      * @return
      * @throws KustvaktException
      */
+    @Deprecated
     public Set<AccessScope> convertToAccessScope (Collection<String> scopes)
             throws KustvaktException {
 
@@ -56,14 +58,47 @@
             }
             catch (IllegalArgumentException e) {
                 throw new KustvaktException(StatusCodes.INVALID_SCOPE,
-                        scope + " is an invalid scope",
+                        "Invalid scope",
                         OAuth2Error.INVALID_SCOPE);
             }
 
             index = definedScopes.indexOf(new AccessScope(oauth2Scope));
             if (index == -1) {
                 throw new KustvaktException(StatusCodes.INVALID_SCOPE,
-                        scope + " is an invalid scope",
+                        "Invalid scope",
+                        OAuth2Error.INVALID_SCOPE);
+            }
+            else {
+                requestedScopes.add(definedScopes.get(index));
+            }
+        }
+        return requestedScopes;
+    }
+    
+    public Set<AccessScope> convertToAccessScope (String scopes)
+            throws KustvaktException {
+
+        String[] scopeArray = scopes.split(" ");
+        List<AccessScope> definedScopes = accessScopeDao.retrieveAccessScopes();
+        Set<AccessScope> requestedScopes =
+                new HashSet<AccessScope>(scopeArray.length);
+        int index;
+        OAuth2Scope oauth2Scope = null;
+        for (String scope : scopeArray) {
+            try {
+                oauth2Scope =
+                        Enum.valueOf(OAuth2Scope.class, scope.toUpperCase());
+            }
+            catch (IllegalArgumentException e) {
+                throw new KustvaktException(StatusCodes.INVALID_SCOPE,
+                        "Invalid scope",
+                        OAuth2Error.INVALID_SCOPE);
+            }
+
+            index = definedScopes.indexOf(new AccessScope(oauth2Scope));
+            if (index == -1) {
+                throw new KustvaktException(StatusCodes.INVALID_SCOPE,
+                        "Invalid scope",
                         OAuth2Error.INVALID_SCOPE);
             }
             else {
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 9647748..40ef907 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
@@ -1,22 +1,60 @@
 package de.ids_mannheim.korap.oauth2.service;
 
+import java.net.URI;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.oltu.oauth2.as.response.OAuthASResponse;
 import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
+import org.apache.oltu.oauth2.common.message.OAuthResponse;
+import org.apache.oltu.oauth2.common.message.types.TokenType;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import com.nimbusds.oauth2.sdk.AuthorizationCodeGrant;
+import com.nimbusds.oauth2.sdk.AuthorizationGrant;
+import com.nimbusds.oauth2.sdk.GrantType;
+import com.nimbusds.oauth2.sdk.RefreshTokenGrant;
+import com.nimbusds.oauth2.sdk.ResourceOwnerPasswordCredentialsGrant;
+import com.nimbusds.oauth2.sdk.Scope;
+import com.nimbusds.oauth2.sdk.TokenRequest;
+import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
+import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
+import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
+import com.nimbusds.oauth2.sdk.auth.ClientSecretPost;
+import com.nimbusds.oauth2.sdk.id.ClientID;
+import com.unboundid.ldap.sdk.LDAPException;
+
 import de.ids_mannheim.korap.authentication.AuthenticationManager;
+import de.ids_mannheim.korap.authentication.LdapAuth3;
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.FullConfiguration;
+import de.ids_mannheim.korap.constant.AuthenticationMethod;
+import de.ids_mannheim.korap.encryption.RandomCodeGenerator;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
+import de.ids_mannheim.korap.oauth2.dao.AccessTokenDao;
+import de.ids_mannheim.korap.oauth2.dao.RefreshTokenDao;
+import de.ids_mannheim.korap.oauth2.dto.OAuth2TokenDto;
+import de.ids_mannheim.korap.oauth2.entity.AccessScope;
+import de.ids_mannheim.korap.oauth2.entity.AccessToken;
 import de.ids_mannheim.korap.oauth2.entity.Authorization;
+import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
+import de.ids_mannheim.korap.oauth2.entity.RefreshToken;
+import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeAllTokenSuperRequest;
+import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenRequest;
+import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenSuperRequest;
+import jakarta.persistence.NoResultException;
+import jakarta.ws.rs.core.Response.Status;
 
 /**
  * OAuth2TokenService manages business logic related to OAuth2
@@ -41,6 +79,14 @@
     protected FullConfiguration config;
     @Autowired
     private AuthenticationManager authenticationManager;
+    
+    @Autowired
+    private RandomCodeGenerator randomGenerator;
+
+    @Autowired
+    private AccessTokenDao tokenDao;
+    @Autowired
+    private RefreshTokenDao refreshDao;
 
     /**
      * RFC 6749:
@@ -103,4 +149,569 @@
         return authenticationTime;
     }
 
+    public OAuthResponse requestAccessToken (
+            TokenRequest tokenRequest, String clientId, String clientSecret)
+            throws KustvaktException, OAuthSystemException {
+
+        AuthorizationGrant authGrant = tokenRequest.getAuthorizationGrant();
+        GrantType grantType = authGrant.getType();
+        Scope scope = tokenRequest.getScope();
+        Set<String> scopeSet = new HashSet<>();
+        if (scope !=null)
+            scopeSet.addAll(scope.toStringList());
+        
+        if (grantType.equals(GrantType.AUTHORIZATION_CODE)) {
+            AuthorizationCodeGrant codeGrant = (AuthorizationCodeGrant) authGrant;
+            String authCode = codeGrant.getAuthorizationCode().getValue();
+            URI uri = codeGrant.getRedirectionURI();
+            String redirectionURI = (uri != null) ? uri.toString() : null;
+            
+            return requestAccessTokenWithAuthorizationCode(authCode,
+                    redirectionURI, clientId, clientSecret);
+        }
+        else if (grantType.equals(GrantType.PASSWORD)) {
+            ResourceOwnerPasswordCredentialsGrant passwordGrant =
+                    (ResourceOwnerPasswordCredentialsGrant) authGrant;
+            String username = passwordGrant.getUsername();
+            String password = passwordGrant.getPassword().getValue();
+            return requestAccessTokenWithPassword(clientId, clientSecret,
+                    username, password, scopeSet);
+        }
+        else if (grantType.equals(GrantType.CLIENT_CREDENTIALS)) {
+            return requestAccessTokenWithClientCredentials(clientId,
+                    clientSecret, scopeSet);
+        }
+        else if (grantType.equals(GrantType.REFRESH_TOKEN)) {
+            RefreshTokenGrant refreshGrant = (RefreshTokenGrant) authGrant;
+            String refreshToken = refreshGrant.getRefreshToken().getValue();
+            return requestAccessTokenWithRefreshToken(refreshToken, scopeSet,
+                    clientId, clientSecret);
+        }
+        else {
+            throw new KustvaktException(StatusCodes.UNSUPPORTED_GRANT_TYPE,
+                    grantType + " is not supported.",
+                    OAuth2Error.UNSUPPORTED_GRANT_TYPE);
+        }
+
+    }
+    
+
+    /**
+     * Revokes all access token associated with the given refresh
+     * token, and creates a new access token and a new refresh
+     * token with the same scopes. Thus, at one point of time,
+     * there is only one active access token associated with
+     * a refresh token.
+     * 
+     * Client authentication is done using the given client
+     * credentials.
+     * 
+     * TODO: should create a new refresh token when the old refresh
+     * token is used (DONE)
+     * 
+     * @param refreshTokenStr
+     * @param requestScopes
+     * @param clientId
+     * @param clientSecret
+     * @return if successful, a new access token
+     * @throws KustvaktException
+     * @throws OAuthSystemException
+     */
+    private OAuthResponse requestAccessTokenWithRefreshToken (
+            String refreshTokenStr, Set<String> requestScopes, String clientId,
+            String clientSecret)
+            throws KustvaktException, OAuthSystemException {
+
+        if (refreshTokenStr == null || refreshTokenStr.isEmpty()) {
+            throw new KustvaktException(StatusCodes.MISSING_PARAMETER,
+                    "Missing parameter: refresh_token",
+                    OAuth2Error.INVALID_REQUEST);
+        }
+
+        OAuth2Client oAuth2Client = clientService.authenticateClient(clientId, clientSecret);
+
+        RefreshToken refreshToken;
+        try {
+            refreshToken = refreshDao.retrieveRefreshToken(refreshTokenStr);
+        }
+        catch (NoResultException e) {
+            throw new KustvaktException(StatusCodes.INVALID_REFRESH_TOKEN,
+                    "Refresh token is not found", OAuth2Error.INVALID_GRANT);
+        }
+
+        if (!clientId.equals(refreshToken.getClient().getId())) {
+            throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
+                    "Client " + clientId + " is not authorized",
+                    OAuth2Error.INVALID_CLIENT);
+        }
+        else if (refreshToken.isRevoked()) {
+            throw new KustvaktException(StatusCodes.INVALID_REFRESH_TOKEN,
+                    "Refresh token has been revoked",
+                    OAuth2Error.INVALID_GRANT);
+        }
+        else if (ZonedDateTime.now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE))
+                .isAfter(refreshToken.getExpiryDate())) {
+            throw new KustvaktException(StatusCodes.INVALID_REFRESH_TOKEN,
+                    "Refresh token is expired", OAuth2Error.INVALID_GRANT);
+        }
+
+        Set<AccessScope> tokenScopes =
+                new HashSet<>(refreshToken.getScopes());
+        if (requestScopes != null && !requestScopes.isEmpty()) {
+            tokenScopes =
+                    scopeService.verifyRefreshScope(requestScopes, tokenScopes);
+            requestScopes = scopeService
+                    .convertAccessScopesToStringSet(tokenScopes);
+        }
+
+        // revoke the refresh token and all access tokens associated to it
+        revokeRefreshToken(refreshTokenStr);
+
+        return createsAccessTokenResponse(requestScopes, tokenScopes, clientId,
+                refreshToken.getUserId(),
+                refreshToken.getUserAuthenticationTime(), oAuth2Client);
+
+        // without new refresh token
+        // return createsAccessTokenResponse(scopes, requestedScopes,
+        // clientId,
+        // refreshToken.getUserId(),
+        // refreshToken.getUserAuthenticationTime(), refreshToken);
+    }
+
+    /**
+     * Issues an access token for the specified client if the
+     * authorization code is valid and client successfully
+     * authenticates.
+     * 
+     * @param code
+     *            authorization code, required
+     * @param redirectionURI
+     *            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 redirectionURI, String clientId, String clientSecret)
+            throws OAuthSystemException, KustvaktException {
+        Authorization authorization = retrieveAuthorization(code, redirectionURI,
+                clientId, clientSecret);
+
+        Set<String> scopes = scopeService
+                .convertAccessScopesToStringSet(authorization.getScopes());
+        OAuth2Client oAuth2Client = clientService.retrieveClient(clientId);
+        return createsAccessTokenResponse(scopes, authorization.getScopes(),
+                authorization.getClientId(), authorization.getUserId(),
+                authorization.getUserAuthenticationTime(), oAuth2Client);
+    }
+
+    /**
+     * 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).
+     * 
+     * TODO: FORCE client secret
+     * 
+     * @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.isSuper()) {
+            throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
+                    "Password grant is not allowed for third party clients",
+                    OAuth2Error.UNAUTHORIZED_CLIENT);
+        }
+
+        if (scopes == null || scopes.isEmpty()) {
+            scopes = new HashSet<String>(1);
+            scopes.add("all");
+            // scopes = config.getDefaultAccessScopes();
+        }
+
+        ZonedDateTime authenticationTime =
+                authenticateUser(username, password, scopes);
+
+        Set<AccessScope> accessScopes =
+                scopeService.convertToAccessScope(scopes);
+        
+        if (config.getOAuth2passwordAuthentication()
+                .equals(AuthenticationMethod.LDAP)) {
+            try {
+                //username = LdapAuth3.getEmail(username, config.getLdapConfig());
+                username = LdapAuth3.getUsername(username, config.getLdapConfig());
+            }
+            catch (LDAPException e) {
+                throw new KustvaktException(StatusCodes.LDAP_BASE_ERRCODE,
+                        e.getExceptionMessage());
+            }
+        }
+        
+        return createsAccessTokenResponse(scopes, accessScopes, clientId,
+                username, authenticationTime, client);
+    }
+
+    /**
+     * Clients must authenticate.
+     * Client credentials grant is limited to native clients.
+     * 
+     * @param clientId
+     *            client_id parameter, required
+     * @param clientSecret
+     *            client_secret parameter, required
+     * @param scopes
+     *            authorization scopes, optional
+     * @return an {@link OAuthResponse}
+     * @throws KustvaktException
+     * @throws OAuthSystemException
+     */
+    protected OAuthResponse requestAccessTokenWithClientCredentials (
+            String clientId, String clientSecret, Set<String> scopes)
+            throws KustvaktException, OAuthSystemException {
+
+        if (clientSecret == null || clientSecret.isEmpty()) {
+            throw new KustvaktException(
+                    StatusCodes.CLIENT_AUTHENTICATION_FAILED,
+                    "Missing parameter: client_secret",
+                    OAuth2Error.INVALID_REQUEST);
+        }
+
+        // OAuth2Client client =
+        OAuth2Client oAuth2Client = clientService.authenticateClient(clientId, clientSecret);
+
+        // if (!client.isNative()) {
+        // throw new KustvaktException(
+        // StatusCodes.CLIENT_AUTHENTICATION_FAILED,
+        // "Client credentials grant is not allowed for third party
+        // clients",
+        // OAuth2Error.UNAUTHORIZED_CLIENT);
+        // }
+
+        ZonedDateTime authenticationTime =
+                ZonedDateTime.now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE));
+
+        scopes = scopeService.filterScopes(scopes,
+                config.getClientCredentialsScopes());
+        Set<AccessScope> accessScopes =
+                scopeService.convertToAccessScope(scopes);
+        return createsAccessTokenResponse(scopes, accessScopes, clientId, null,
+                authenticationTime,oAuth2Client);
+    }
+
+    /**
+     * Creates an OAuthResponse containing an access token of type
+     * Bearer. By default, MD generator is used to generates access
+     * token of 128 bit values, represented in hexadecimal comprising
+     * 32 bytes. The generated value is subsequently encoded in
+     * Base64.
+     * 
+     * <br /><br />
+     * Additionally, a refresh token is issued for confidential clients. 
+     * It can be used to request a new access token without requiring user
+     * re-authentication.
+     * 
+     * @param scopes
+     *            a set of access token scopes in String
+     * @param accessScopes
+     *            a set of access token scopes in {@link AccessScope}
+     * @param clientId
+     *            a client id
+     * @param userId
+     *            a user id
+     * @param authenticationTime
+     *            the user authentication time
+     * @return an {@link OAuthResponse}
+     * @throws OAuthSystemException
+     * @throws KustvaktException
+     */
+    private OAuthResponse createsAccessTokenResponse (Set<String> scopes,
+            Set<AccessScope> accessScopes, String clientId, String userId,
+            ZonedDateTime authenticationTime, OAuth2Client client)
+            throws OAuthSystemException, KustvaktException {
+
+        String random = randomGenerator.createRandomCode();
+        random += randomGenerator.createRandomCode();
+        
+        if (clientService.isPublicClient(client)){
+            // refresh token == null, getAccessTokenLongExpiry
+            return createsAccessTokenResponse(scopes, accessScopes, clientId,
+                    userId, authenticationTime);
+            }
+        else {
+            // refresh token != null, getAccessTokenExpiry
+            // default refresh token expiry: 365 days in seconds
+            RefreshToken refreshToken = refreshDao.storeRefreshToken(random,
+                    userId, authenticationTime, client, accessScopes);
+            return createsAccessTokenResponse(scopes, accessScopes, clientId,
+                    userId, authenticationTime, refreshToken);
+        }
+    }
+
+    private OAuthResponse createsAccessTokenResponse (Set<String> scopes,
+            Set<AccessScope> accessScopes, String clientId, String userId,
+            ZonedDateTime authenticationTime, RefreshToken refreshToken)
+            throws OAuthSystemException, KustvaktException {
+
+        String accessToken = randomGenerator.createRandomCode();
+        accessToken +=randomGenerator.createRandomCode();
+        tokenDao.storeAccessToken(accessToken, refreshToken, accessScopes,
+                userId, clientId, authenticationTime);
+
+        return OAuthASResponse.tokenResponse(Status.OK.getStatusCode())
+                .setAccessToken(accessToken)
+                .setTokenType(TokenType.BEARER.toString())
+                .setExpiresIn(String.valueOf(config.getAccessTokenExpiry()))
+                .setRefreshToken(refreshToken.getToken())
+                .setScope(String.join(" ", scopes)).buildJSONMessage();
+    }
+    
+    private OAuthResponse createsAccessTokenResponse (Set<String> scopes,
+            Set<AccessScope> accessScopes, String clientId, String userId,
+            ZonedDateTime authenticationTime)
+            throws OAuthSystemException, KustvaktException {
+
+        String accessToken = randomGenerator.createRandomCode();
+        accessToken +=randomGenerator.createRandomCode();
+        tokenDao.storeAccessToken(accessToken, null, accessScopes,
+                userId, clientId, authenticationTime);
+
+        return OAuthASResponse.tokenResponse(Status.OK.getStatusCode())
+                .setAccessToken(accessToken)
+                .setTokenType(TokenType.BEARER.toString())
+                .setExpiresIn(String.valueOf(config.getAccessTokenLongExpiry()))
+                .setScope(String.join(" ", scopes)).buildJSONMessage();
+    }
+
+    public void revokeToken (String clientId, String clientSecret,
+            String token, String tokenType) throws KustvaktException {
+        clientService.authenticateClient(clientId, clientSecret);
+        if (tokenType != null && tokenType.equals("refresh_token")) {
+            if (!revokeRefreshToken(token)) {
+                revokeAccessToken(token);
+            }
+            return;
+        }
+
+        if (!revokeAccessToken(token)) {
+            revokeRefreshToken(token);
+        }
+    }
+
+    private boolean revokeAccessToken (String token) throws KustvaktException {
+        try {
+            AccessToken accessToken = tokenDao.retrieveAccessToken(token);
+            revokeAccessToken(accessToken);
+            return true;
+        }
+        catch (KustvaktException e) {
+            if (!e.getStatusCode().equals(StatusCodes.INVALID_ACCESS_TOKEN)) {
+                return false;
+            }
+            throw e;
+        }
+    }
+    
+    private void revokeAccessToken (AccessToken accessToken)
+            throws KustvaktException {
+        if (accessToken != null){
+            accessToken.setRevoked(true);
+            tokenDao.updateAccessToken(accessToken);
+        }
+    }
+
+    private boolean revokeRefreshToken (String token) throws KustvaktException {
+        RefreshToken refreshToken = null;
+        try {
+            refreshToken = refreshDao.retrieveRefreshToken(token);
+        }
+        catch (NoResultException e) {
+            return false;
+        }
+
+        return revokeRefreshToken(refreshToken);
+    }
+
+    public boolean revokeRefreshToken (RefreshToken refreshToken)
+            throws KustvaktException {
+        if (refreshToken != null){
+            refreshToken.setRevoked(true);
+            refreshDao.updateRefreshToken(refreshToken);
+    
+            Set<AccessToken> accessTokenList = refreshToken.getAccessTokens();
+            for (AccessToken accessToken : accessTokenList) {
+                accessToken.setRevoked(true);
+                tokenDao.updateAccessToken(accessToken);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public void revokeAllClientTokensViaSuperClient (String username,
+            String superClientId, String superClientSecret, String clientId)
+            throws KustvaktException {
+        OAuth2Client superClient = clientService
+                .authenticateClient(superClientId, superClientSecret);
+        if (!superClient.isSuper()) {
+            throw new KustvaktException(
+                    StatusCodes.CLIENT_AUTHENTICATION_FAILED);
+        }
+
+        revokeAllClientTokensForUser(clientId, username);
+    }
+    
+    public void revokeAllClientTokensForUser (String clientId, String username)
+            throws KustvaktException {
+        OAuth2Client client = clientService.retrieveClient(clientId);
+        if (clientService.isPublicClient(client)) {
+            List<AccessToken> accessTokens =
+                    tokenDao.retrieveAccessTokenByClientId(clientId, username);
+            for (AccessToken t : accessTokens) {
+                revokeAccessToken(t);
+            }
+        }
+        else {
+            List<RefreshToken> refreshTokens = refreshDao
+                    .retrieveRefreshTokenByClientId(clientId, username);
+            for (RefreshToken r : refreshTokens) {
+                revokeRefreshToken(r);
+            }
+        }
+    }
+    
+    public void revokeTokensViaSuperClient (String username,
+            String superClientId, String superClientSecret, String token)
+            throws KustvaktException {
+        OAuth2Client superClient = clientService
+                .authenticateClient(superClientId, superClientSecret);
+        if (!superClient.isSuper()) {
+            throw new KustvaktException(
+                    StatusCodes.CLIENT_AUTHENTICATION_FAILED);
+        }
+
+        RefreshToken refreshToken =
+                refreshDao.retrieveRefreshToken(token, username);
+        if (!revokeRefreshToken(refreshToken)) {
+            AccessToken accessToken =
+                    tokenDao.retrieveAccessToken(token, username);
+            revokeAccessToken(accessToken);
+        }
+    }
+    
+    public List<OAuth2TokenDto> listUserRefreshToken (String username, String superClientId,
+            String superClientSecret, String clientId) throws KustvaktException {
+        
+        OAuth2Client client = clientService.authenticateClient(superClientId, superClientSecret);
+        if (!client.isSuper()) {
+            throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
+                    "Only super client is allowed.",
+                    OAuth2Error.UNAUTHORIZED_CLIENT);
+        }
+
+        List<RefreshToken> tokens = refreshDao.retrieveRefreshTokenByUser(username, clientId);
+        List<OAuth2TokenDto> dtoList = new ArrayList<>(tokens.size());
+        for (RefreshToken t : tokens){
+            OAuth2Client tokenClient = t.getClient();
+            if (tokenClient.getId().equals(client.getId())){
+                continue;
+            }
+            OAuth2TokenDto dto = new OAuth2TokenDto();
+            dto.setClientId(tokenClient.getId());
+            dto.setClientName(tokenClient.getName());
+            dto.setClientUrl(tokenClient.getUrl());
+            dto.setClientDescription(tokenClient.getDescription());
+            
+            DateTimeFormatter f = DateTimeFormatter.ISO_DATE_TIME;
+            dto.setCreatedDate(t.getCreatedDate().format(f));
+            long difference = ChronoUnit.SECONDS.between(ZonedDateTime.now(), t.getExpiryDate());
+            dto.setExpiresIn(difference);
+            
+            dto.setUserAuthenticationTime(
+                    t.getUserAuthenticationTime().format(f));
+            dto.setToken(t.getToken());
+            
+            Set<AccessScope> accessScopes = t.getScopes();
+            Set<String> scopes = new HashSet<>(accessScopes.size());
+            for (AccessScope s : accessScopes){
+                scopes.add(s.getId().toString());
+            }
+            dto.setScope(scopes);
+            dtoList.add(dto);
+        }
+        return dtoList;
+    }
+    
+    public List<OAuth2TokenDto> listUserAccessToken (String username, String superClientId,
+            String superClientSecret, String clientId) throws KustvaktException {
+        
+        OAuth2Client superClient = clientService.authenticateClient(superClientId, superClientSecret);
+        if (!superClient.isSuper()) {
+            throw new KustvaktException(StatusCodes.CLIENT_AUTHORIZATION_FAILED,
+                    "Only super client is allowed.",
+                    OAuth2Error.UNAUTHORIZED_CLIENT);
+        }
+
+        List<AccessToken> tokens =
+                tokenDao.retrieveAccessTokenByUser(username, clientId);
+        List<OAuth2TokenDto> dtoList = new ArrayList<>(tokens.size());
+        for (AccessToken t : tokens){
+            OAuth2Client tokenClient = t.getClient();
+            if (tokenClient.getId().equals(superClient.getId())){
+                continue;
+            }
+            OAuth2TokenDto dto = new OAuth2TokenDto();
+            dto.setClientId(tokenClient.getId());
+            dto.setClientName(tokenClient.getName());
+            dto.setClientUrl(tokenClient.getUrl());
+            dto.setClientDescription(tokenClient.getDescription());
+            
+            DateTimeFormatter f = DateTimeFormatter.ISO_DATE_TIME;
+            dto.setCreatedDate(t.getCreatedDate().format(f));
+            
+            long difference = ChronoUnit.SECONDS.between(ZonedDateTime.now(), t.getExpiryDate());
+            dto.setExpiresIn(difference);
+                    
+            dto.setUserAuthenticationTime(
+                    t.getUserAuthenticationTime().format(f));
+            dto.setToken(t.getToken());
+            
+            Set<AccessScope> accessScopes = t.getScopes();
+            Set<String> scopes = new HashSet<>(accessScopes.size());
+            for (AccessScope s : accessScopes){
+                scopes.add(s.getId().toString());
+            }
+            dto.setScope(scopes);
+            dtoList.add(dto);
+        }
+        return dtoList;
+    }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/security/context/KustvaktContext.java b/full/src/main/java/de/ids_mannheim/korap/security/context/KustvaktContext.java
index 6d36199..bd2843f 100644
--- a/full/src/main/java/de/ids_mannheim/korap/security/context/KustvaktContext.java
+++ b/full/src/main/java/de/ids_mannheim/korap/security/context/KustvaktContext.java
@@ -1,9 +1,9 @@
 package de.ids_mannheim.korap.security.context;
 
-import javax.ws.rs.core.SecurityContext;
-
 import java.security.Principal;
 
+import jakarta.ws.rs.core.SecurityContext;
+
 /**
  * @author hanl
  * @date 13/05/2014
diff --git a/full/src/main/java/de/ids_mannheim/korap/security/context/TokenContext.java b/full/src/main/java/de/ids_mannheim/korap/security/context/TokenContext.java
index b31c643..23d2fa4 100644
--- a/full/src/main/java/de/ids_mannheim/korap/security/context/TokenContext.java
+++ b/full/src/main/java/de/ids_mannheim/korap/security/context/TokenContext.java
@@ -2,7 +2,6 @@
 
 import java.io.Serializable;
 import java.time.ZonedDateTime;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -16,7 +15,6 @@
 import de.ids_mannheim.korap.utils.TimeUtils;
 import lombok.AccessLevel;
 import lombok.Data;
-import lombok.Getter;
 import lombok.Setter;
 
 /**
diff --git a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java
index e7fa88e..ecd1ac9 100644
--- a/full/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java
+++ b/full/src/main/java/de/ids_mannheim/korap/server/KustvaktBaseServer.java
@@ -8,8 +8,6 @@
 import java.security.NoSuchAlgorithmException;
 import java.util.Scanner;
 
-import javax.servlet.ServletContextListener;
-
 import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.HttpConnectionFactory;
 import org.eclipse.jetty.server.Server;
@@ -25,6 +23,7 @@
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.encryption.RandomCodeGenerator;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import jakarta.servlet.ServletContextListener;
 import lombok.Getter;
 import lombok.Setter;
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/MailAuthenticator.java b/full/src/main/java/de/ids_mannheim/korap/service/MailAuthenticator.java
index a15d890..84397d5 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/MailAuthenticator.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/MailAuthenticator.java
@@ -1,7 +1,7 @@
 package de.ids_mannheim.korap.service;
 
-import javax.mail.Authenticator;
-import javax.mail.PasswordAuthentication;
+import jakarta.mail.Authenticator;
+import jakarta.mail.PasswordAuthentication;
 
 /** Defines Authenticator for creating javax.mail.Session.
  * 
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/MailService.java b/full/src/main/java/de/ids_mannheim/korap/service/MailService.java
index 1aaebc5..0a6b2d4 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/MailService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/MailService.java
@@ -3,9 +3,6 @@
 import java.io.StringWriter;
 import java.nio.charset.StandardCharsets;
 
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeMessage;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.apache.velocity.VelocityContext;
@@ -22,6 +19,8 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.utils.ParameterChecker;
+import jakarta.mail.internet.InternetAddress;
+import jakarta.mail.internet.MimeMessage;
 
 /**
  * Manages mail related services, such as sending group member
diff --git a/full/src/main/java/de/ids_mannheim/korap/service/QueryService.java b/full/src/main/java/de/ids_mannheim/korap/service/QueryService.java
index 8b339ed..19b57e9 100644
--- a/full/src/main/java/de/ids_mannheim/korap/service/QueryService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/service/QueryService.java
@@ -7,8 +7,6 @@
 import java.util.List;
 import java.util.regex.Pattern;
 
-import javax.ws.rs.core.Response.Status;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,6 +43,7 @@
 import de.ids_mannheim.korap.web.controller.QueryReferenceController;
 import de.ids_mannheim.korap.web.controller.VirtualCorpusController;
 import de.ids_mannheim.korap.web.input.QueryJson;
+import jakarta.ws.rs.core.Response.Status;
 
 /**
  * QueryService handles the logic behind
diff --git a/full/src/main/java/de/ids_mannheim/korap/user/User.java b/full/src/main/java/de/ids_mannheim/korap/user/User.java
index 902473a..66b6873 100644
--- a/full/src/main/java/de/ids_mannheim/korap/user/User.java
+++ b/full/src/main/java/de/ids_mannheim/korap/user/User.java
@@ -12,7 +12,7 @@
 import lombok.Setter;
 import org.joda.time.DateTime;
 
-import javax.persistence.Entity;
+import jakarta.persistence.Entity;
 import java.io.Serializable;
 import java.util.HashMap;
 import java.util.List;
diff --git a/full/src/main/java/de/ids_mannheim/korap/utils/JerseyUtils.java b/full/src/main/java/de/ids_mannheim/korap/utils/JerseyUtils.java
index 0a8623f..c60dfa0 100644
--- a/full/src/main/java/de/ids_mannheim/korap/utils/JerseyUtils.java
+++ b/full/src/main/java/de/ids_mannheim/korap/utils/JerseyUtils.java
@@ -1,12 +1,12 @@
 package de.ids_mannheim.korap.utils;
 
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
-
 import org.glassfish.jersey.message.internal.MediaTypes;
 import org.glassfish.jersey.server.ContainerRequest;
 
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
+
 public class JerseyUtils {
 
     /**
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java
index 4ae0a53..4964913 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/ClientsHandler.java
@@ -1,17 +1,17 @@
 package de.ids_mannheim.korap.web;
 
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.exceptions.StatusCodes;
-
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.MultivaluedMap;
 import java.net.URI;
 import java.util.List;
 import java.util.Map;
 
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.MultivaluedMap;
+
 /**
  * @author hanl
  * @date 10/12/2013
@@ -34,7 +34,7 @@
             return service.path(path).queryParam(key, value).request().get(String.class);
         }
         catch (WebApplicationException e) {
-            throw new KustvaktException(StatusCodes.REQUEST_INVALID);
+            throw new KustvaktException(StatusCodes.INVALID_REQUEST);
         }
     }
 
@@ -52,7 +52,7 @@
             return resource.request().get(String.class);
         }
         catch (WebApplicationException e) {
-            throw new KustvaktException(StatusCodes.REQUEST_INVALID);
+            throw new KustvaktException(StatusCodes.INVALID_REQUEST);
         }
     }
 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/CoreResponseHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/CoreResponseHandler.java
index b0553d6..3d9cd42 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/CoreResponseHandler.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/CoreResponseHandler.java
@@ -1,11 +1,10 @@
 package de.ids_mannheim.korap.web;
 
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Response;
-
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.response.Notifications;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.Response;
 
 /**
  * @author hanl, margaretha
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/KustvaktResponseHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/KustvaktResponseHandler.java
index 6fe0cc1..79ce3bc 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/KustvaktResponseHandler.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/KustvaktResponseHandler.java
@@ -2,14 +2,13 @@
 
 import java.util.EnumSet;
 
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.ResponseBuilder;
-
 import de.ids_mannheim.korap.constant.AuthenticationScheme;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.ResponseBuilder;
 
 /**
  * KustvaktResponseHandler includes exceptions regarding
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java
index a1f7c67..077383f 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/OAuth2ResponseHandler.java
@@ -3,22 +3,21 @@
 import java.net.URI;
 import java.net.URISyntaxException;
 
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.ResponseBuilder;
-import javax.ws.rs.core.Response.Status;
-
 import org.apache.http.HttpHeaders;
-import org.apache.oltu.oauth2.common.error.OAuthError;
 import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
 import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
 import org.apache.oltu.oauth2.common.message.OAuthResponse;
 import org.apache.oltu.oauth2.common.message.OAuthResponse.OAuthErrorResponseBuilder;
 
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.ResponseBuilder;
+import jakarta.ws.rs.core.Response.Status;
 
 /**
  * OAuth2ResponseHandler builds {@link Response}s from
@@ -81,6 +80,7 @@
     
     public WebApplicationException throwit (KustvaktException e, String state) {
         String errorCode = e.getEntity();
+                    
         int responseStatus = e.getResponseStatus();
         try {
             if(responseStatus>0) {
@@ -89,30 +89,30 @@
             else if (errorCode == null){
                 return super.throwit(e);
             }
-            else if (errorCode.equals(OAuth2Error.INVALID_CLIENT)
-                    || errorCode.equals(OAuth2Error.UNAUTHORIZED_CLIENT)
-                    || errorCode.equals(OAuth2Error.INVALID_TOKEN)) {
+            else if (errorCode.equals(OAuth2Error.INVALID_CLIENT.getCode())
+                    || errorCode.equals(OAuth2Error.UNAUTHORIZED_CLIENT.getCode())
+                    || errorCode.equals(de.ids_mannheim.korap.oauth2.constant.OAuth2Error.INVALID_TOKEN)) {
                 return throwit(createOAuthProblemException(e,
                         Status.UNAUTHORIZED.getStatusCode(), state));
             }
-            else if (errorCode.equals(OAuth2Error.INVALID_GRANT)
-                    || errorCode.equals(OAuth2Error.INVALID_REQUEST)
-                    || errorCode.equals(OAuth2Error.INVALID_SCOPE)
-                    || errorCode.equals(OAuth2Error.UNSUPPORTED_GRANT_TYPE)
-                    || errorCode.equals(OAuth2Error.UNSUPPORTED_RESPONSE_TYPE)
-                    || errorCode.equals(OAuth2Error.ACCESS_DENIED)) {
+            else if (errorCode.equals(OAuth2Error.INVALID_GRANT.getCode())
+                    || errorCode.equals(OAuth2Error.INVALID_REQUEST.getCode())
+                    || errorCode.equals(OAuth2Error.INVALID_SCOPE.getCode())
+                    || errorCode.equals(OAuth2Error.UNSUPPORTED_GRANT_TYPE.getCode())
+                    || errorCode.equals(OAuth2Error.UNSUPPORTED_RESPONSE_TYPE.getCode())
+                    || errorCode.equals(OAuth2Error.ACCESS_DENIED.getCode())) {
                 return throwit(createOAuthProblemException(e,
                         Status.BAD_REQUEST.getStatusCode(), state));
             }
-            else if (errorCode.equals(OAuth2Error.INSUFFICIENT_SCOPE)) {
+            else if (errorCode.equals(de.ids_mannheim.korap.oauth2.constant.OAuth2Error.INSUFFICIENT_SCOPE)) {
                 return throwit(createOAuthProblemException(e,
                         Status.FORBIDDEN.getStatusCode(), state));
             }
-            else if (errorCode.equals(OAuth2Error.SERVER_ERROR)) {
+            else if (errorCode.equals(OAuth2Error.SERVER_ERROR.getCode())) {
                 return throwit(createOAuthProblemException(e,
                         Status.INTERNAL_SERVER_ERROR.getStatusCode(), state));
             }
-            else if (errorCode.equals(OAuth2Error.TEMPORARILY_UNAVAILABLE)) {
+            else if (errorCode.equals(OAuth2Error.TEMPORARILY_UNAVAILABLE.getCode())) {
                 return throwit(createOAuthProblemException(e,
                         Status.SERVICE_UNAVAILABLE.getStatusCode(), state));
             }
@@ -182,15 +182,8 @@
         return builder.build();
     }
 
-    public Response sendRedirect (String locationUri) throws KustvaktException {
-        try {
-            ResponseBuilder builder =
-                    Response.temporaryRedirect(new URI(locationUri));
-            return builder.build();
-        }
-        catch (URISyntaxException e) {
-            throw new KustvaktException(StatusCodes.INVALID_ARGUMENT,
-                    e.getMessage(), OAuthError.CodeResponse.INVALID_REQUEST);
-        }
+    public Response sendRedirect (URI locationUri) {
+        ResponseBuilder builder = Response.temporaryRedirect(locationUri);
+        return builder.build();
     }
 }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/OpenIdResponseHandler.java b/full/src/main/java/de/ids_mannheim/korap/web/OpenIdResponseHandler.java
deleted file mode 100644
index 3cf7d1c..0000000
--- a/full/src/main/java/de/ids_mannheim/korap/web/OpenIdResponseHandler.java
+++ /dev/null
@@ -1,232 +0,0 @@
-package de.ids_mannheim.korap.web;
-
-import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.ResponseBuilder;
-import javax.ws.rs.core.Response.Status;
-
-import org.apache.http.HttpHeaders;
-import org.springframework.stereotype.Service;
-
-import com.nimbusds.oauth2.sdk.AccessTokenResponse;
-import com.nimbusds.oauth2.sdk.AuthorizationErrorResponse;
-import com.nimbusds.oauth2.sdk.ErrorObject;
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.oauth2.sdk.ResponseMode;
-import com.nimbusds.oauth2.sdk.TokenErrorResponse;
-import com.nimbusds.oauth2.sdk.id.State;
-import com.nimbusds.oauth2.sdk.token.BearerTokenError;
-import com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse;
-
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
-import net.minidev.json.JSONObject;
-
-/** Generates OpenId specific responses.
- * 
- * @author margaretha
- *
- */
-@Service
-public class OpenIdResponseHandler extends KustvaktResponseHandler {
-
-    final static Map<String, ErrorObject> errorObjectMap = new HashMap<>();
-    {
-        errorObjectMap.put(OAuth2Error.ACCESS_DENIED,
-                com.nimbusds.oauth2.sdk.OAuth2Error.ACCESS_DENIED);
-        errorObjectMap.put(OAuth2Error.INVALID_CLIENT,
-                com.nimbusds.oauth2.sdk.OAuth2Error.INVALID_CLIENT);
-        errorObjectMap.put(OAuth2Error.INVALID_GRANT,
-                com.nimbusds.oauth2.sdk.OAuth2Error.INVALID_GRANT);
-        errorObjectMap.put(OAuth2Error.INVALID_REQUEST,
-                com.nimbusds.oauth2.sdk.OAuth2Error.INVALID_REQUEST);
-        errorObjectMap.put(OAuth2Error.INVALID_SCOPE,
-                com.nimbusds.oauth2.sdk.OAuth2Error.INVALID_SCOPE);
-        errorObjectMap.put(OAuth2Error.SERVER_ERROR,
-                com.nimbusds.oauth2.sdk.OAuth2Error.SERVER_ERROR);
-        errorObjectMap.put(OAuth2Error.TEMPORARILY_UNAVAILABLE,
-                com.nimbusds.oauth2.sdk.OAuth2Error.TEMPORARILY_UNAVAILABLE);
-        errorObjectMap.put(OAuth2Error.UNAUTHORIZED_CLIENT,
-                com.nimbusds.oauth2.sdk.OAuth2Error.UNAUTHORIZED_CLIENT);
-        errorObjectMap.put(OAuth2Error.UNSUPPORTED_GRANT_TYPE,
-                com.nimbusds.oauth2.sdk.OAuth2Error.UNSUPPORTED_GRANT_TYPE);
-        errorObjectMap.put(OAuth2Error.UNSUPPORTED_RESPONSE_TYPE,
-                com.nimbusds.oauth2.sdk.OAuth2Error.UNSUPPORTED_RESPONSE_TYPE);
-    }
-
-    final static Map<String, ErrorObject> tokenErrorObjectMap = new HashMap<>();
-    {
-        tokenErrorObjectMap.put(OAuth2Error.INSUFFICIENT_SCOPE,
-                BearerTokenError.INSUFFICIENT_SCOPE);
-        tokenErrorObjectMap.put(OAuth2Error.INVALID_TOKEN,
-                BearerTokenError.INVALID_TOKEN);
-        tokenErrorObjectMap.put(OAuth2Error.INVALID_REQUEST,
-                BearerTokenError.INVALID_REQUEST);
-    }
-
-    /**
-     * According to OpenID connect core 1.0 specification, all
-     * authentication errors must be represented through
-     * AuthenticationErrorResponse. Moreover, for authorization code
-     * flow, the error response parameters must be added to the
-     * redirect URI as query parameters, unless a different response
-     * mode was specified.
-     * 
-     * {@link AuthorizationErrorResponse} defines specific
-     * {@link ErrorObject}s regarding OAUTH2 errors.
-     * {@link AuthenticationErrorResponse} defines additional
-     * ErrorObjects regarding OpenID connect authenticaition errors.
-     * 
-     * @param e
-     *            a {@link KustvaktException}
-     * @param isAuthentication
-     * @param redirectURI
-     * @param state
-     * @param responseMode
-     * @return a redirect uri with error response parameters as part
-     *         of query parameters
-     */
-    public Response createAuthorizationErrorResponse (KustvaktException e,
-            boolean isAuthentication, URI redirectURI, State state,
-            ResponseMode responseMode) {
-
-        ErrorObject errorObject = createErrorObject(e);
-        errorObject = errorObject.setDescription(e.getMessage());
-        if (redirectURI == null) {
-            // if (e.getStatusCode()
-            // .equals(StatusCodes.USER_REAUTHENTICATION_REQUIRED)) {
-            // return Response.status(HttpStatus.SC_UNAUTHORIZED)
-            // .entity(e.getMessage()).build();
-            // }
-
-            return Response.status(errorObject.getHTTPStatusCode())
-                    .entity(errorObject.toJSONObject()).build();
-        }
-
-        URI uri = null;
-        if (isAuthentication) {
-            uri = new AuthenticationErrorResponse(redirectURI, errorObject,
-                    state, responseMode).toURI();
-        }
-        else {
-            uri = new AuthorizationErrorResponse(redirectURI, errorObject,
-                    state, responseMode).toURI();
-        }
-
-        ResponseBuilder builder = Response.temporaryRedirect(uri)
-                .type(MediaType.APPLICATION_FORM_URLENCODED);
-        return builder.build();
-    }
-
-    private ErrorObject createErrorObject (KustvaktException e) {
-        String errorCode = e.getEntity();
-
-        ErrorObject errorObject = errorObjectMap.get(errorCode);
-        if (errorObject == null) {
-            if (errorCode != null && !errorCode.isEmpty()
-                    && !errorCode.equals("[]")) {
-                errorObject = new ErrorObject(e.getEntity(), e.getMessage());
-            }
-            else {
-                throw throwit(e);
-            }
-        }
-        return errorObject;
-    }
-
-    public Response createErrorResponse (ParseException e, State state) {
-        ErrorObject errorObject = e.getErrorObject();
-        if (errorObject == null) {
-            errorObject = com.nimbusds.oauth2.sdk.OAuth2Error.INVALID_REQUEST;
-            if (e.getMessage() != null) {
-                errorObject = errorObject.setDescription(e.getMessage());
-            }
-        }
-
-        JSONObject json = errorObject.toJSONObject();
-        if (state != null) {
-            json.put("state", state.getValue());
-        }
-
-        return Response.status(errorObject.getHTTPStatusCode()).entity(json)
-                .build();
-
-    }
-
-    public Response createTokenErrorResponse (KustvaktException e) {
-
-        String errorCode = e.getEntity();
-        ErrorObject errorObject = tokenErrorObjectMap.get(errorCode);
-        if (errorObject == null) {
-            errorObject = errorObjectMap.get(errorCode);
-            if (errorCode != null && !errorCode.isEmpty()
-                    && !errorCode.equals("[]")) {
-                errorObject = new ErrorObject(e.getEntity(), e.getMessage());
-            }
-            else {
-                throw throwit(e);
-            }
-        }
-
-        errorObject = errorObject.setDescription(e.getMessage());
-        TokenErrorResponse errorResponse = new TokenErrorResponse(errorObject);
-        Status status = determineErrorStatus(errorCode);
-        return createResponse(errorResponse, status);
-    }
-
-    public Response createResponse (AccessTokenResponse tokenResponse,
-            Status status) {
-        String jsonString = tokenResponse.toJSONObject().toJSONString();
-        return createResponse(status, jsonString);
-    }
-
-    public Response createResponse (TokenErrorResponse tokenResponse,
-            Status status) {
-        String jsonString = tokenResponse.toJSONObject().toJSONString();
-        return createResponse(status, jsonString);
-    }
-
-    private Response createResponse (Status status, Object entity) {
-        ResponseBuilder builder = Response.status(status);
-        builder.entity(entity);
-        builder.header(HttpHeaders.CACHE_CONTROL, "no-store");
-        builder.header(HttpHeaders.PRAGMA, "no-store");
-
-        if (status == Status.UNAUTHORIZED) {
-            builder.header(HttpHeaders.WWW_AUTHENTICATE,
-                    "Basic realm=\"Kustvakt\"");
-        }
-        return builder.build();
-    }
-
-    private Status determineErrorStatus (String errorCode) {
-        Status status = Status.BAD_REQUEST;
-        if (errorCode.equals(OAuth2Error.INVALID_CLIENT)
-                || errorCode.equals(OAuth2Error.UNAUTHORIZED_CLIENT)
-                || errorCode.equals(OAuth2Error.INVALID_TOKEN)) {
-            status = Status.UNAUTHORIZED;
-        }
-        else if (errorCode.equals(OAuth2Error.INVALID_GRANT)
-                || errorCode.equals(OAuth2Error.INVALID_REQUEST)
-                || errorCode.equals(OAuth2Error.INVALID_SCOPE)
-                || errorCode.equals(OAuth2Error.UNSUPPORTED_GRANT_TYPE)
-                || errorCode.equals(OAuth2Error.UNSUPPORTED_RESPONSE_TYPE)
-                || errorCode.equals(OAuth2Error.ACCESS_DENIED)) {
-            status = Status.BAD_REQUEST;
-        }
-        else if (errorCode.equals(OAuth2Error.INSUFFICIENT_SCOPE)) {
-            status = Status.FORBIDDEN;
-        }
-        else if (errorCode.equals(OAuth2Error.SERVER_ERROR)) {
-            status = Status.INTERNAL_SERVER_ERROR;
-        }
-        else if (errorCode.equals(OAuth2Error.TEMPORARILY_UNAVAILABLE)) {
-            status = Status.SERVICE_UNAVAILABLE;
-        }
-        return status;
-    }
-}
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/TRACE.java b/full/src/main/java/de/ids_mannheim/korap/web/TRACE.java
index 05d511b..80ae087 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/TRACE.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/TRACE.java
@@ -1,11 +1,12 @@
 package de.ids_mannheim.korap.web;
 
-import javax.ws.rs.HttpMethod;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
+import jakarta.ws.rs.HttpMethod;
+
 /**
  * @author hanl
  * @date 03/07/2014
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
index 9eac9d4..a777131 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/AuthenticationController.java
@@ -5,19 +5,6 @@
 import java.util.Locale;
 import java.util.Map;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.glassfish.jersey.server.ContainerRequest;
@@ -45,6 +32,18 @@
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.HeaderParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
 
 // import com.sun.xml.internal.messaging.saaj.util.Base64;
 
@@ -367,7 +366,7 @@
                 authorizationData.getPassword()== null || 
                 authorizationData.getPassword().isEmpty())
             // is actual an invalid request
-            throw kustvaktResponseHandler.throwit(StatusCodes.REQUEST_INVALID);
+            throw kustvaktResponseHandler.throwit(StatusCodes.INVALID_REQUEST);
 
         Map<String, Object> attr = new HashMap<>();
         attr.put(Attributes.HOST, host);
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2AdminController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2AdminController.java
index 957d31b..b76a049 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2AdminController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2AdminController.java
@@ -1,13 +1,5 @@
 package de.ids_mannheim.korap.web.controller;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
@@ -17,6 +9,13 @@
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import de.ids_mannheim.korap.web.filter.AdminFilter;
 import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
 
 @Controller
 @Path("{version}/admin/oauth2")
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
index f7df50b..0686a89 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2Controller.java
@@ -1,52 +1,58 @@
 package de.ids_mannheim.korap.web.controller;
 
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.time.ZonedDateTime;
 import java.util.List;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-
-import org.apache.oltu.oauth2.as.request.AbstractOAuthTokenRequest;
-import org.apache.oltu.oauth2.as.request.OAuthTokenRequest;
-import org.apache.oltu.oauth2.as.request.OAuthUnauthenticatedTokenRequest;
-import org.apache.oltu.oauth2.common.exception.OAuthProblemException;
 import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
 import org.apache.oltu.oauth2.common.message.OAuthResponse;
-import org.apache.oltu.oauth2.common.message.types.GrantType;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
-import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import com.nimbusds.oauth2.sdk.AuthorizationErrorResponse;
+import com.nimbusds.oauth2.sdk.AuthorizationGrant;
+import com.nimbusds.oauth2.sdk.ClientCredentialsGrant;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.Scope;
+import com.nimbusds.oauth2.sdk.TokenRequest;
+import com.nimbusds.oauth2.sdk.TokenRevocationRequest;
+import com.nimbusds.oauth2.sdk.auth.ClientAuthentication;
+import com.nimbusds.oauth2.sdk.auth.ClientAuthenticationMethod;
+import com.nimbusds.oauth2.sdk.auth.ClientSecretBasic;
+import com.nimbusds.oauth2.sdk.auth.ClientSecretPost;
+import com.nimbusds.oauth2.sdk.id.ClientID;
+import com.nimbusds.oauth2.sdk.token.Token;
 
 import de.ids_mannheim.korap.constant.OAuth2Scope;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
 import de.ids_mannheim.korap.oauth2.dto.OAuth2TokenDto;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2AuthorizationRequest;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeAllTokenSuperRequest;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenRequest;
-import de.ids_mannheim.korap.oauth2.oltu.OAuth2RevokeTokenSuperRequest;
-import de.ids_mannheim.korap.oauth2.oltu.service.OltuAuthorizationService;
-import de.ids_mannheim.korap.oauth2.oltu.service.OltuTokenService;
+import de.ids_mannheim.korap.oauth2.service.OAuth2AuthorizationService;
 import de.ids_mannheim.korap.oauth2.service.OAuth2ScopeService;
+import de.ids_mannheim.korap.oauth2.service.OAuth2TokenService;
 import de.ids_mannheim.korap.security.context.TokenContext;
+import de.ids_mannheim.korap.utils.ParameterChecker;
 import de.ids_mannheim.korap.web.OAuth2ResponseHandler;
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
-import de.ids_mannheim.korap.web.utils.FormRequestWrapper;
+import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriBuilder;
 
 /**
  * OAuth2Controller describes OAuth2 web API for authorization
@@ -61,16 +67,19 @@
  */
 @Controller
 @Path("{version}/oauth2")
-@ResourceFilters({ APIVersionFilter.class, AuthenticationFilter.class, BlockingFilter.class })
+@ResourceFilters({ APIVersionFilter.class, AuthenticationFilter.class,
+        BlockingFilter.class })
 @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
 public class OAuth2Controller {
 
     @Autowired
     private OAuth2ResponseHandler responseHandler;
+
     @Autowired
-    private OltuTokenService tokenService;
+    private OAuth2TokenService tokenService;
     @Autowired
-    private OltuAuthorizationService authorizationService;
+    private OAuth2AuthorizationService authorizationService;
+    
     @Autowired
     private OAuth2ScopeService scopeService;
 
@@ -102,6 +111,7 @@
     public Response requestAuthorizationCode (
             @Context HttpServletRequest request,
             @Context SecurityContext context, 
+            @FormParam("scope") String scope,
             @FormParam("state") String state,
             @FormParam("client_id") String clientId,
             @FormParam("redirect_uri") String redirectUri,
@@ -111,28 +121,30 @@
         String username = tokenContext.getUsername();
         ZonedDateTime authTime = tokenContext.getAuthenticationTime();
 
+        URI requestURI;
+        UriBuilder builder = UriBuilder.fromPath(request.getRequestURI());
+        for (String key : form.keySet()) {
+            builder.queryParam(key, form.get(key).toArray());
+        }
+        requestURI = builder.build();
+       
         try {
             scopeService.verifyScope(tokenContext, OAuth2Scope.AUTHORIZE);
-
-            HttpServletRequest requestWithForm =
-                    new FormRequestWrapper(request, form);
-            OAuth2AuthorizationRequest authzRequest =
-                    new OAuth2AuthorizationRequest(requestWithForm);
-            String uri = authorizationService.requestAuthorizationCode(
-                    requestWithForm, authzRequest, username, authTime);
+            URI uri = authorizationService.requestAuthorizationCode(
+                    requestURI, clientId, redirectUri,
+                    scope, state, username, authTime);
             return responseHandler.sendRedirect(uri);
         }
-        catch (OAuthSystemException e) {
-            throw responseHandler.throwit(e, state);
-        }
-        catch (OAuthProblemException e) {
-            e.state(state);
-            e = authorizationService.checkRedirectUri(e, clientId, redirectUri);
-            throw responseHandler.throwit(e);
-        }
         catch (KustvaktException e) {
             e = authorizationService.checkRedirectUri(e, clientId, redirectUri);
-            throw responseHandler.throwit(e, state);
+            if (e.getRedirectUri() != null) {
+                AuthorizationErrorResponse errorResponse =
+                        authorizationService.createAuthorizationError(e, state);
+                return responseHandler.sendRedirect(errorResponse.toURI());
+            }
+            else {
+                throw responseHandler.throwit(e, state);
+            } 
         }
     }
     
@@ -141,35 +153,44 @@
     public Response requestAuthorizationCode (
             @Context HttpServletRequest request,
             @Context SecurityContext context,
+            @QueryParam("response_type") String responseType,
             @QueryParam("client_id") String clientId,
             @QueryParam("redirect_uri") String redirectUri,
-            @QueryParam("state") String state
-            ) {
+            @QueryParam("scope") String scope,
+            @QueryParam("state") String state) {
 
         TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
         String username = tokenContext.getUsername();
         ZonedDateTime authTime = tokenContext.getAuthenticationTime();
 
+        URI requestURI;
+        try {
+            requestURI = new URI(request.getRequestURI()+"?"+request.getQueryString());
+        }
+        catch (URISyntaxException e) {
+            KustvaktException ke = new KustvaktException(
+                    StatusCodes.INVALID_REQUEST, "Failed parsing request URI.",
+                    OAuth2Error.INVALID_REQUEST_URI);
+            throw responseHandler.throwit(ke, state);
+        }
+        
         try {
             scopeService.verifyScope(tokenContext, OAuth2Scope.AUTHORIZE);
-
-            OAuth2AuthorizationRequest authzRequest =
-                    new OAuth2AuthorizationRequest(request);
-            String uri = authorizationService.requestAuthorizationCode(
-                    request, authzRequest, username, authTime);
+            URI uri = authorizationService.requestAuthorizationCode(
+                    requestURI, clientId, redirectUri,
+                    scope, state, username, authTime);
             return responseHandler.sendRedirect(uri);
         }
-        catch (OAuthSystemException e) {
-            throw responseHandler.throwit(e,state);
-        }
-        catch (OAuthProblemException e) {
-            e.state(state);
-            e = authorizationService.checkRedirectUri(e,clientId,redirectUri);
-            throw responseHandler.throwit(e);
-        }
         catch (KustvaktException e) {
             e = authorizationService.checkRedirectUri(e, clientId, redirectUri);
-            throw responseHandler.throwit(e,state);
+            if (e.getRedirectUri() != null) {
+                AuthorizationErrorResponse errorResponse =
+                        authorizationService.createAuthorizationError(e, state);
+                return responseHandler.sendRedirect(errorResponse.toURI());
+            }
+            else {
+                throw responseHandler.throwit(e, state);
+            } 
         }
     }
 
@@ -240,36 +261,77 @@
     @ResourceFilters({APIVersionFilter.class})
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response requestAccessToken (@Context HttpServletRequest request,
-            @FormParam("grant_type") String grantType,
+            @FormParam("client_id") String clientId,
+            @FormParam("client_secret") String clientSecret,
             MultivaluedMap<String, String> form) {
 
+        OAuthResponse oAuthResponse = null;
         try {
-            boolean grantTypeExist = grantType != null && !grantType.isEmpty();
-            AbstractOAuthTokenRequest oAuthRequest = null;
-            if (grantTypeExist && grantType
-                    .equals(GrantType.CLIENT_CREDENTIALS.toString())) {
-                oAuthRequest = new OAuthTokenRequest(
-                        new FormRequestWrapper(request, form));
+            URI requestURI;
+            UriBuilder builder = UriBuilder.fromPath(
+                    request.getRequestURL().toString());
+            for (String key : form.keySet()) {
+                builder.queryParam(key, form.get(key).toArray());
             }
-            else {
-                oAuthRequest = new OAuthUnauthenticatedTokenRequest(
-                        new FormRequestWrapper(request, form));
+            requestURI = builder.build();
+            
+            try {
+                AuthorizationGrant authGrant = AuthorizationGrant.parse(form);  
+                
+                ClientAuthentication clientAuth = null;
+                String authorizationHeader = request.getHeader("Authorization");
+                if (authorizationHeader!=null && !authorizationHeader.isEmpty() ) {
+                    clientAuth = ClientSecretBasic.parse(authorizationHeader);
+                }
+                else if (authGrant instanceof ClientCredentialsGrant) {
+                    // this doesn't allow public clients
+                    clientAuth = ClientSecretPost.parse(form);
+                }
+                
+                TokenRequest tokenRequest = null;
+                if (clientAuth!=null) {
+                    ClientAuthenticationMethod method = clientAuth.getMethod();
+                    if (method.equals(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)) {
+                        ClientSecretBasic basic = (ClientSecretBasic) clientAuth;
+                        clientSecret = basic.getClientSecret().getValue();
+                        clientId = basic.getClientID().getValue();
+                    }
+                    else if (method.equals(ClientAuthenticationMethod.CLIENT_SECRET_POST)) {
+                        ClientSecretPost post = (ClientSecretPost) clientAuth;
+                        clientSecret = post.getClientSecret().getValue();
+                        clientId = post.getClientID().getValue();
+                    }
+                    
+                    tokenRequest = new TokenRequest(requestURI,
+                            clientAuth,
+                            AuthorizationGrant.parse(form),
+                            Scope.parse(form.getFirst("scope")));
+                }
+                else {
+                    // requires ClientAuthentication for client_credentials grant
+                    tokenRequest = new TokenRequest(requestURI,
+                        new ClientID(clientId),
+                        AuthorizationGrant.parse(form),
+                        Scope.parse(form.getFirst("scope")));
+                }
+            
+                oAuthResponse = tokenService.requestAccessToken(tokenRequest,
+                        clientId, clientSecret);
             }
-
-            OAuthResponse oAuthResponse =
-                    tokenService.requestAccessToken(oAuthRequest);
-
-            return responseHandler.createResponse(oAuthResponse);
+            catch (ParseException | IllegalArgumentException e) {
+                throw new KustvaktException(StatusCodes.INVALID_REQUEST,
+                        e.getMessage(), OAuth2Error.INVALID_REQUEST); 
+            }
+            
         }
         catch (KustvaktException e) {
             throw responseHandler.throwit(e);
         }
-        catch (OAuthProblemException e) {
-            throw responseHandler.throwit(e);
-        }
         catch (OAuthSystemException e) {
             throw responseHandler.throwit(e);
         }
+        
+        return responseHandler.createResponse(oAuthResponse);
     }
 
     /**
@@ -295,21 +357,18 @@
     @ResourceFilters({APIVersionFilter.class})
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response revokeAccessToken (@Context HttpServletRequest request,
-            MultivaluedMap<String, String> form) {
+            @FormParam("client_id") String clientId,
+            @FormParam("client_secret") String clientSecret,
+            @FormParam("token") String token,
+            @FormParam("token_type") String tokenType) {
 
         try {
-            OAuth2RevokeTokenRequest revokeTokenRequest =
-                    new OAuth2RevokeTokenRequest(
-                            new FormRequestWrapper(request, form));
-            tokenService.revokeToken(revokeTokenRequest);
+            ParameterChecker.checkStringValue("client_id", clientId);
+            ParameterChecker.checkStringValue("token", token);
+            tokenService.revokeToken(clientId,clientSecret,token,tokenType);
+            
             return Response.ok("SUCCESS").build();
         }
-        catch (OAuthProblemException e) {
-            throw responseHandler.throwit(e);
-        }
-        catch (OAuthSystemException e) {
-            throw responseHandler.throwit(e);
-        }
         catch (KustvaktException e) {
             throw responseHandler.throwit(e);
         }
@@ -320,25 +379,23 @@
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
     public Response revokeTokenViaSuperClient (@Context SecurityContext context,
             @Context HttpServletRequest request,
-            MultivaluedMap<String, String> form) {
-
-        TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
-        String username = tokenContext.getUsername();
+            @FormParam("super_client_id") String superClientId,
+            @FormParam("super_client_secret") String superClientSecret,
+            @FormParam("token") String token) {
 
         try {
-            OAuth2RevokeTokenSuperRequest revokeTokenRequest =
-                    new OAuth2RevokeTokenSuperRequest(
-                            new FormRequestWrapper(request, form));
-            tokenService.revokeTokensViaSuperClient(username,
-                    revokeTokenRequest);
+            ParameterChecker.checkStringValue("super_client_id", superClientId);
+            ParameterChecker.checkStringValue("super_client_secret",
+                    superClientSecret);
+            ParameterChecker.checkStringValue("token", token);
+            
+            TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
+            String username = tokenContext.getUsername();
+            
+            tokenService.revokeTokensViaSuperClient(username, superClientId,
+                    superClientSecret, token);
             return Response.ok("SUCCESS").build();
         }
-        catch (OAuthSystemException e) {
-            throw responseHandler.throwit(e);
-        }
-        catch (OAuthProblemException e) {
-            throw responseHandler.throwit(e);
-        }
         catch (KustvaktException e) {
             throw responseHandler.throwit(e);
         }
@@ -364,25 +421,22 @@
     public Response revokeAllClientTokensViaSuperClient (
             @Context SecurityContext context,
             @Context HttpServletRequest request,
-            MultivaluedMap<String, String> form) {
+            @FormParam("client_id") String clientId,
+            @FormParam("super_client_id") String superClientId,
+            @FormParam("super_client_secret") String superClientSecret) {
 
         TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
         String username = tokenContext.getUsername();
 
         try {
-            OAuth2RevokeAllTokenSuperRequest revokeTokenRequest =
-                    new OAuth2RevokeAllTokenSuperRequest(
-                            new FormRequestWrapper(request, form));
+            ParameterChecker.checkStringValue("super_client_id", superClientId);
+            ParameterChecker.checkStringValue("super_client_secret",
+                    superClientSecret);
+           
             tokenService.revokeAllClientTokensViaSuperClient(username,
-                    revokeTokenRequest);
+                    superClientId, superClientSecret, clientId);
             return Response.ok("SUCCESS").build();
         }
-        catch (OAuthSystemException e) {
-            throw responseHandler.throwit(e);
-        }
-        catch (OAuthProblemException e) {
-            throw responseHandler.throwit(e);
-        }
         catch (KustvaktException e) {
             throw responseHandler.throwit(e);
         }
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2WithOpenIdController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2WithOpenIdController.java
deleted file mode 100644
index 685bb3f..0000000
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuth2WithOpenIdController.java
+++ /dev/null
@@ -1,241 +0,0 @@
-package de.ids_mannheim.korap.web.controller;
-
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.net.URL;
-import java.time.ZonedDateTime;
-import java.util.Map;
-import java.util.List;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.ResponseBuilder;
-import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.core.SecurityContext;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
-
-import com.nimbusds.oauth2.sdk.AccessTokenResponse;
-import com.nimbusds.oauth2.sdk.ParseException;
-import com.nimbusds.oauth2.sdk.ResponseMode;
-import com.nimbusds.oauth2.sdk.TokenRequest;
-import com.nimbusds.oauth2.sdk.http.HTTPRequest.Method;
-import com.nimbusds.oauth2.sdk.id.State;
-import de.ids_mannheim.korap.web.utils.ResourceFilters;
-
-import de.ids_mannheim.korap.constant.OAuth2Scope;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.oauth2.openid.OpenIdConfiguration;
-import de.ids_mannheim.korap.oauth2.openid.OpenIdHttpRequestWrapper;
-import de.ids_mannheim.korap.oauth2.openid.service.JWKService;
-import de.ids_mannheim.korap.oauth2.openid.service.OpenIdAuthorizationService;
-import de.ids_mannheim.korap.oauth2.openid.service.OpenIdConfigService;
-import de.ids_mannheim.korap.oauth2.openid.service.OpenIdTokenService;
-import de.ids_mannheim.korap.oauth2.service.OAuth2ScopeService;
-import de.ids_mannheim.korap.security.context.TokenContext;
-import de.ids_mannheim.korap.web.OpenIdResponseHandler;
-import de.ids_mannheim.korap.web.filter.APIVersionFilter;
-import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
-import de.ids_mannheim.korap.web.filter.BlockingFilter;
-import de.ids_mannheim.korap.web.utils.MapUtils;
-
-/**
- * Describes OAuth2 webAPI with OpenId Connect implementation, an
- * additional authentication protocol allowing clients to verify
- * user authentication data represented by ID tokens.
- * 
- * @author margaretha
- *
- */
-@Controller
-@Path("{version}/oauth2/openid")
-@ResourceFilters({ APIVersionFilter.class })
-public class OAuth2WithOpenIdController {
-
-    @Autowired
-    private OpenIdAuthorizationService authzService;
-    @Autowired
-    private OpenIdTokenService tokenService;
-    @Autowired
-    private JWKService jwkService;
-    @Autowired
-    private OpenIdConfigService configService;
-    @Autowired
-    private OAuth2ScopeService scopeService;
-
-    @Autowired
-    private OpenIdResponseHandler openIdResponseHandler;
-
-    /**
-     * Required parameters for OpenID authentication requests:
-     * 
-     * <ul>
-     * <li>scope: MUST contain "openid" for OpenID Connect
-     * requests</li>
-     * <li>response_type: only "code" is supported</li>
-     * <li>client_id: client identifier given by Kustvakt during
-     * client registration</li>
-     * <li>redirect_uri: MUST match a pre-registered redirect uri
-     * during client registration</li>
-     * </ul>
-     * 
-     * Other parameters:
-     * 
-     * <ul>
-     * <li>state (recommended): Opaque value used to maintain state
-     * between the request and the callback.</li>
-     * <li>response_mode (optional) : mechanism to be used for
-     * returning parameters, only "query" is supported</li>
-     * <li>nonce (optional): String value used to associate a Client
-     * session with an ID Token,
-     * and to mitigate replay attacks. </li>
-     * <li>display (optional): specifies how the Authorization Server
-     * displays the authentication and consent user interface
-     * pages. Options: page (default), popup, touch, wap. This
-     * parameter is more relevant for Kalamar. </li>
-     * <li>prompt (optional): specifies if the Authorization Server
-     * prompts the End-User for reauthentication and consent. Defined
-     * values: none, login, consent, select_account </li>
-     * <li>max_age (optional): maximum Authentication Age.</li>
-     * <li>ui_locales (optional): preferred languages and scripts for
-     * the user interface represented as a space-separated list of
-     * BCP47 [RFC5646] </li>
-     * <li>id_token_hint (optional): ID Token previously issued by the
-     * Authorization Server being passed as a hint</li>
-     * <li>login_hint (optional): hint to the Authorization Server
-     * about the login identifier the End-User might use to log
-     * in</li>
-     * <li>acr_values (optional): requested Authentication Context
-     * Class Reference values. </li>
-     * </ul>
-     * 
-     * @see "OpenID Connect Core 1.0 specification"
-     * 
-     * @param request
-     * @param context
-     * @param form
-     * @return a redirect to client redirect uri
-     */
-    @POST
-    @Path("authorize")
-    @ResourceFilters({ AuthenticationFilter.class, BlockingFilter.class })
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
-    public Response requestAuthorizationCode (
-            @Context HttpServletRequest request,
-            @Context SecurityContext context,
-            MultivaluedMap<String, String> form) {
-
-        TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
-        String username = tokenContext.getUsername();
-        ZonedDateTime authTime = tokenContext.getAuthenticationTime();
-
-        Map<String, String> map = MapUtils.toMap(form);
-        State state = authzService.retrieveState(map);
-        ResponseMode responseMode = authzService.retrieveResponseMode(map);
-
-        boolean isAuthentication = false;
-        if (map.containsKey("scope") && map.get("scope").contains("openid")) {
-            isAuthentication = true;
-        }
-
-        URI uri = null;
-        try {
-            scopeService.verifyScope(tokenContext, OAuth2Scope.AUTHORIZE);
-
-            if (isAuthentication) {
-                authzService.checkRedirectUriParam(map);
-            }
-            uri = authzService.requestAuthorizationCode(form, username,
-                    isAuthentication, authTime);
-        }
-        catch (ParseException e) {
-            return openIdResponseHandler.createErrorResponse(e, state);
-        }
-        catch (KustvaktException e) {
-            return openIdResponseHandler.createAuthorizationErrorResponse(e,
-                    isAuthentication, e.getRedirectUri(), state, responseMode);
-        }
-
-        ResponseBuilder builder = Response.temporaryRedirect(uri);
-        return builder.build();
-    }
-
-    @POST
-    @Path("token")
-    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
-    @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
-    public Response requestAccessToken (
-            @Context HttpServletRequest servletRequest,
-            MultivaluedMap<String, String> form) {
-
-        Map<String, String> map = MapUtils.toMap(form);
-        Method method = Method.valueOf(servletRequest.getMethod());
-        URL url = null;
-        try {
-            url = new URL(servletRequest.getRequestURL().toString());
-        }
-        catch (MalformedURLException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-
-        try {
-            OpenIdHttpRequestWrapper httpRequest =
-                    new OpenIdHttpRequestWrapper(method, url);
-            httpRequest.toHttpRequest(servletRequest, (Map<String, List<String>>) form);
-
-            TokenRequest tokenRequest = TokenRequest.parse(httpRequest);
-            AccessTokenResponse tokenResponse =
-                    tokenService.requestAccessToken(tokenRequest);
-            return openIdResponseHandler.createResponse(tokenResponse,
-                    Status.OK);
-        }
-        catch (ParseException e) {
-            return openIdResponseHandler.createErrorResponse(e, null);
-        }
-        catch (KustvaktException e) {
-            return openIdResponseHandler.createTokenErrorResponse(e);
-        }
-    }
-
-    /**
-     * Retrieves Kustvakt public keys of JWK (Json Web Key) set
-     * format.
-     * 
-     * @return json string representation of the public keys
-     * 
-     * @see "RFC 8017 regarding RSA specifications"
-     * @see "RFC 7517 regarding JWK (Json Web Key) and JWK Set"
-     */
-    @GET
-    @Path("jwks")
-    @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
-    public String requestPublicKeys () {
-        return jwkService.generatePublicKeySetJson();
-    }
-
-    /**
-     * When supporting discovery, must be available at
-     * {issuer_uri}/.well-known/openid-configuration
-     * 
-     * @return
-     * 
-     * @return
-     */
-    @GET
-    @Path("config")
-    @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
-    public OpenIdConfiguration requestOpenIdConfig () {
-        return configService.retrieveOpenIdConfigInfo();
-    }
-}
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthClientController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthClientController.java
index ae27c80..bace018 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthClientController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/OAuthClientController.java
@@ -2,18 +2,6 @@
 
 import java.util.List;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
@@ -30,6 +18,17 @@
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.input.OAuth2ClientJson;
 import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * Defines controllers for OAuth2 clients, namely applications
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/PluginController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/PluginController.java
index 006698b..c10c4fa 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/PluginController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/PluginController.java
@@ -2,21 +2,9 @@
 
 import java.util.List;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
-import de.ids_mannheim.korap.web.utils.ResourceFilters;
-
 import de.ids_mannheim.korap.constant.OAuth2Scope;
 import de.ids_mannheim.korap.dto.InstalledPluginDto;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
@@ -28,6 +16,16 @@
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
+import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
 
 @Controller
 @Path("{version}/plugins")
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/QueryReferenceController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/QueryReferenceController.java
index d6f1548..caa059c 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/QueryReferenceController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/QueryReferenceController.java
@@ -2,25 +2,9 @@
 
 import java.util.List;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.core.SecurityContext;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
-import de.ids_mannheim.korap.web.utils.ResourceFilters;
-
 import de.ids_mannheim.korap.constant.OAuth2Scope;
 import de.ids_mannheim.korap.constant.QueryType;
 import de.ids_mannheim.korap.dto.QueryDto;
@@ -36,6 +20,20 @@
 import de.ids_mannheim.korap.web.filter.DemoUserFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 import de.ids_mannheim.korap.web.input.QueryJson;
+import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * QueryReferenceController defines web APIs related to the
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/ResourceController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/ResourceController.java
index 9e01afe..074b14b 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/ResourceController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/ResourceController.java
@@ -2,20 +2,18 @@
 
 import java.util.List;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
-import de.ids_mannheim.korap.web.utils.ResourceFilters;
-
 import de.ids_mannheim.korap.dto.ResourceDto;
 import de.ids_mannheim.korap.service.ResourceService;
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
+import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
 
 /**
  * Provides information about free resources.
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserController.java
index b0b6d6d..8e461f4 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserController.java
@@ -1,12 +1,5 @@
 package de.ids_mannheim.korap.web.controller;
 
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.SecurityContext;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
@@ -21,6 +14,12 @@
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.SecurityContext;
 
 @Controller
 @Path("{version}/user")
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupAdminController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupAdminController.java
index 6a5f146..e5edce5 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupAdminController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupAdminController.java
@@ -2,14 +2,6 @@
 
 import java.util.List;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
@@ -21,6 +13,13 @@
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import de.ids_mannheim.korap.web.filter.AdminFilter;
 import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
 
 @Controller
 @Path("{version}/admin/group")
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
index 4cd48e5..19c97d7 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserGroupController.java
@@ -2,26 +2,11 @@
 
 import java.util.List;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-
 import org.apache.http.HttpStatus;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
 import de.ids_mannheim.korap.constant.OAuth2Scope;
-import de.ids_mannheim.korap.constant.UserGroupStatus;
 import de.ids_mannheim.korap.dto.UserGroupDto;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.oauth2.service.OAuth2ScopeService;
@@ -33,6 +18,19 @@
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * UserGroupController defines web APIs related to user groups,
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserSettingController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserSettingController.java
index dd8d6cd..bf57a1e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/UserSettingController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/UserSettingController.java
@@ -2,23 +2,9 @@
 
 import java.util.Map;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.SecurityContext;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
-import de.ids_mannheim.korap.web.utils.ResourceFilters;
-
 import de.ids_mannheim.korap.constant.OAuth2Scope;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
@@ -30,6 +16,18 @@
 import de.ids_mannheim.korap.web.filter.AuthenticationFilter;
 import de.ids_mannheim.korap.web.filter.BlockingFilter;
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
+import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * UserSettingController defines web APIs related to user default
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusAdminController.java b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusAdminController.java
index 9a79535..c6ffcdf 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusAdminController.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/controller/VirtualCorpusAdminController.java
@@ -2,15 +2,6 @@
 
 import java.util.List;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
@@ -24,6 +15,14 @@
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import de.ids_mannheim.korap.web.filter.AdminFilter;
 import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.FormParam;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 @Controller
 @Path("{version}/admin/vc")
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 e421a70..bd9e13c 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
@@ -2,21 +2,6 @@
 
 import java.util.List;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.core.SecurityContext;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 
@@ -41,6 +26,20 @@
 import de.ids_mannheim.korap.web.filter.PiwikFilter;
 import de.ids_mannheim.korap.web.input.QueryJson;
 import de.ids_mannheim.korap.web.utils.ResourceFilters;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * VirtualCorpusController defines web APIs related to virtual corpus
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/APIVersionFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/APIVersionFilter.java
index 853557a..ed0c2c3 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/APIVersionFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/APIVersionFilter.java
@@ -2,17 +2,15 @@
 
 import java.util.List;
 
-import javax.annotation.Priority;
-import javax.ws.rs.NotFoundException;
-import javax.ws.rs.core.PathSegment;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
-
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.NotFoundException;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.core.PathSegment;
 
 /**
  * Checks API version in URL path.
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
index 885ce41..18a12d8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/AdminFilter.java
@@ -1,12 +1,5 @@
 package de.ids_mannheim.korap.web.filter;
 
-import javax.annotation.Priority;
-import javax.servlet.ServletContext;
-import javax.ws.rs.Priorities;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.SecurityContext;
-
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -16,6 +9,12 @@
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.utils.JerseyUtils;
 import de.ids_mannheim.korap.web.KustvaktResponseHandler;
+import jakarta.annotation.Priority;
+import jakarta.servlet.ServletContext;
+import jakarta.ws.rs.Priorities;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * Verifies admin credentials or token before allowing access to
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 bb5d6c1..e24a7a4 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
@@ -1,10 +1,5 @@
 package de.ids_mannheim.korap.web.filter;
 
-import javax.annotation.Priority;
-import javax.ws.rs.Priorities;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.glassfish.jersey.server.ContainerRequest;
@@ -21,6 +16,10 @@
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.utils.TimeUtils;
 import de.ids_mannheim.korap.web.KustvaktResponseHandler;
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.Priorities;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
 
 /** Authentication filter extracts an authentication token from 
  * authorization header and uses an authentication provider 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
index bb14e10..09c811c 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/BlockingFilter.java
@@ -3,16 +3,15 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import javax.annotation.Priority;
-import javax.ws.rs.Priorities;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
-import javax.ws.rs.core.SecurityContext;
-
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.web.KustvaktResponseHandler;
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.Priorities;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * @author hanl
@@ -21,6 +20,7 @@
  *       endpoint filter to block access to an endpoint, in case no
  *       anonymous access should be allowed!
  */
+
 @Component
 @Priority(Priorities.AUTHORIZATION)
 public class BlockingFilter implements ContainerRequestFilter {
@@ -28,6 +28,7 @@
     @Autowired
     private KustvaktResponseHandler kustvaktResponseHandler;
 
+    
     @Override
     public void filter (ContainerRequestContext request) {
         TokenContext context;
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/DemoFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/DemoFilter.java
index e020a8d..55ad2ae 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/DemoFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/DemoFilter.java
@@ -1,11 +1,5 @@
 package de.ids_mannheim.korap.web.filter;
 
-import javax.annotation.Priority;
-import javax.ws.rs.Priorities;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
-import javax.ws.rs.core.SecurityContext;
-
 import org.glassfish.jersey.server.ContainerRequest;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
@@ -13,6 +7,11 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.security.context.KustvaktContext;
 import de.ids_mannheim.korap.security.context.TokenContext;
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.Priorities;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * @author hanl
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/DemoUserFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/DemoUserFilter.java
index 22b43f0..330ece2 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/DemoUserFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/DemoUserFilter.java
@@ -2,14 +2,6 @@
 
 import java.security.Principal;
 
-import javax.annotation.Priority;
-import javax.ws.rs.Priorities;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.SecurityContext;
-import javax.ws.rs.core.UriInfo;
-
 import org.glassfish.jersey.server.ContainerRequest;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -20,6 +12,13 @@
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.user.User;
 import de.ids_mannheim.korap.utils.TimeUtils;
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.Priorities;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.core.UriInfo;
 
 /**
  * Created by hanl on 7/15/14.
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
index c4b539a..c69e18e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/NonDemoBlockingFilter.java
@@ -1,18 +1,18 @@
 package de.ids_mannheim.korap.web.filter;
 
+
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import javax.annotation.Priority;
-import javax.ws.rs.Priorities;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
-import javax.ws.rs.core.SecurityContext;
-
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.security.context.TokenContext;
 import de.ids_mannheim.korap.web.KustvaktResponseHandler;
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.Priorities;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.core.SecurityContext;
 
 /**
  * EM: pretty much identical to {@link BlockingFilter}, should be deleted? 
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/filter/PiwikFilter.java b/full/src/main/java/de/ids_mannheim/korap/web/filter/PiwikFilter.java
index 955e219..88961f2 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/filter/PiwikFilter.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/filter/PiwikFilter.java
@@ -8,13 +8,6 @@
 import java.util.Map;
 import java.util.Random;
 
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
-import javax.ws.rs.core.UriBuilder;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.glassfish.jersey.client.ClientConfig;
@@ -22,6 +15,12 @@
 import org.springframework.beans.factory.annotation.Autowired;
 
 import de.ids_mannheim.korap.authentication.AuthenticationManager;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.core.UriBuilder;
 import net.minidev.json.JSONArray;
 
 /**
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/utils/FormRequestWrapper.java b/full/src/main/java/de/ids_mannheim/korap/web/utils/FormRequestWrapper.java
index 12c7825..12c4f01 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/utils/FormRequestWrapper.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/utils/FormRequestWrapper.java
@@ -1,11 +1,11 @@
 package de.ids_mannheim.korap.web.utils;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import javax.ws.rs.core.MultivaluedMap;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Map;
+
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletRequestWrapper;
+import jakarta.ws.rs.core.MultivaluedMap;
 
 /**
  * Helper class to wrapp multivaluedmap into a hashmap. Depending on
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/utils/JsonExceptionMapper.java b/full/src/main/java/de/ids_mannheim/korap/web/utils/JsonExceptionMapper.java
index 126f34d..a7efdf8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/utils/JsonExceptionMapper.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/utils/JsonExceptionMapper.java
@@ -1,14 +1,14 @@
 package de.ids_mannheim.korap.web.utils;
 
-import javax.annotation.Priority;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
 
 import com.fasterxml.jackson.databind.JsonMappingException;
 
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.web.CoreResponseHandler;
+import jakarta.annotation.Priority;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
 
 /**
  * Creates appropriate responses in case of incorrect JSON
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/utils/LocaleFactory.java b/full/src/main/java/de/ids_mannheim/korap/web/utils/LocaleFactory.java
index cb72ba5..268e7c8 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/utils/LocaleFactory.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/utils/LocaleFactory.java
@@ -1,12 +1,14 @@
 package de.ids_mannheim.korap.web.utils;
 
-import org.glassfish.hk2.api.Factory;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.ext.Provider;
 import java.util.List;
 import java.util.Locale;
 
+import org.glassfish.hk2.api.Factory;
+
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.ext.Provider;
+
 @Provider
 public class LocaleFactory implements Factory<Locale> {
     @Context
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/utils/MapUtils.java b/full/src/main/java/de/ids_mannheim/korap/web/utils/MapUtils.java
index 7d1913f..497519a 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/utils/MapUtils.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/utils/MapUtils.java
@@ -6,7 +6,7 @@
 import java.util.Set;
 import java.util.stream.Collectors;
 
-import javax.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.MultivaluedMap;
 
 /**
  * Utility methods for maps
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/utils/NotFoundMapper.java b/full/src/main/java/de/ids_mannheim/korap/web/utils/NotFoundMapper.java
index a05983b..20b6632 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/utils/NotFoundMapper.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/utils/NotFoundMapper.java
@@ -4,15 +4,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import javax.ws.rs.NotFoundException;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ResourceContext;
-import javax.ws.rs.core.Context;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.UriBuilder;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
-
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 import org.eclipse.jetty.http.HttpStatus;
@@ -20,6 +11,14 @@
 import org.springframework.stereotype.Component;
 
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
+import jakarta.ws.rs.NotFoundException;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ResourceContext;
+import jakarta.ws.rs.core.Context;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriBuilder;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
 
 /**
  * Handles not found API version by redirecting the request URI to a
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/utils/ResourceFilters.java b/full/src/main/java/de/ids_mannheim/korap/web/utils/ResourceFilters.java
index ab0d4ea..94e5dc7 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/utils/ResourceFilters.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/utils/ResourceFilters.java
@@ -6,8 +6,8 @@
 import java.lang.annotation.Target;
 
 /**
- * Defines the list of {@link javax.ws.rs.container.ContainerRequestFilter}
- * and {@link javax.ws.rs.container.ContainerResponseFilter}
+ * Defines the list of {@link jakarta.ws.rs.container.ContainerRequestFilter}
+ * and {@link jakarta.ws.rs.container.ContainerResponseFilter}
  * classes associated with a resource method.
  * <p>
  * This annotation can be specified on a class or on method(s). Specifying it
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/utils/ResourceFiltersFeature.java b/full/src/main/java/de/ids_mannheim/korap/web/utils/ResourceFiltersFeature.java
index 62b7745..db728e7 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/utils/ResourceFiltersFeature.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/utils/ResourceFiltersFeature.java
@@ -1,13 +1,13 @@
 package de.ids_mannheim.korap.web.utils;
 
-import javax.ws.rs.container.DynamicFeature;
-import javax.ws.rs.container.ResourceInfo;
-import javax.ws.rs.core.FeatureContext;
-import javax.ws.rs.ext.Provider;
+import jakarta.ws.rs.container.DynamicFeature;
+import jakarta.ws.rs.container.ResourceInfo;
+import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.ext.Provider;
 
 /**
- * Registers {@link javax.ws.rs.container.ContainerRequestFilter}
- * and {@link javax.ws.rs.container.ContainerResponseFilter}
+ * Registers {@link jakarta.ws.rs.container.ContainerRequestFilter}
+ * and {@link jakarta.ws.rs.container.ContainerResponseFilter}
  * classes for a resource method annotated with {@link ResourceFilters}.
  */
 @Provider
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/utils/SearchResourceFilters.java b/full/src/main/java/de/ids_mannheim/korap/web/utils/SearchResourceFilters.java
index 12dbf57..1505d0e 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/utils/SearchResourceFilters.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/utils/SearchResourceFilters.java
@@ -6,8 +6,8 @@
 import java.lang.annotation.Target;
 
 /**
- * Defines the list of {@link javax.ws.rs.container.ContainerRequestFilter}
- * and {@link javax.ws.rs.container.ContainerResponseFilter}
+ * Defines the list of {@link jakarta.ws.rs.container.ContainerRequestFilter}
+ * and {@link jakarta.ws.rs.container.ContainerResponseFilter}
  * classes associated with a resource method.
  * <p>
  * This annotation can be specified on a class or on method(s). Specifying it
diff --git a/full/src/main/java/de/ids_mannheim/korap/web/utils/SearchResourceFiltersFeature.java b/full/src/main/java/de/ids_mannheim/korap/web/utils/SearchResourceFiltersFeature.java
index 45a7c4e..5c2e6e2 100644
--- a/full/src/main/java/de/ids_mannheim/korap/web/utils/SearchResourceFiltersFeature.java
+++ b/full/src/main/java/de/ids_mannheim/korap/web/utils/SearchResourceFiltersFeature.java
@@ -2,21 +2,20 @@
 
 import java.util.List;
 
-import javax.ws.rs.container.DynamicFeature;
-import javax.ws.rs.container.ResourceInfo;
-import javax.ws.rs.core.FeatureContext;
-import javax.ws.rs.ext.Provider;
-
 import org.glassfish.jersey.model.internal.CommonConfig;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
 import de.ids_mannheim.korap.web.filter.APIVersionFilter;
 import edu.emory.mathcs.backport.java.util.Arrays;
+import jakarta.ws.rs.container.DynamicFeature;
+import jakarta.ws.rs.container.ResourceInfo;
+import jakarta.ws.rs.core.FeatureContext;
+import jakarta.ws.rs.ext.Provider;
 
 /**
- * Registers {@link javax.ws.rs.container.ContainerRequestFilter}
- * and {@link javax.ws.rs.container.ContainerResponseFilter}
+ * Registers {@link jakarta.ws.rs.container.ContainerRequestFilter}
+ * and {@link jakarta.ws.rs.container.ContainerResponseFilter}
  * classes for a resource method annotated with {@link ResourceFilters}.
  */
 @Provider
diff --git a/full/src/main/resources/basic-config.xml b/full/src/main/resources/basic-config.xml
index 2ba0d1a..c8cfdaa 100644
--- a/full/src/main/resources/basic-config.xml
+++ b/full/src/main/resources/basic-config.xml
@@ -221,12 +221,6 @@
 	<bean id="oauth2ResponseHandler" class="de.ids_mannheim.korap.web.OAuth2ResponseHandler">
 	</bean>
 
-	<bean id="mdGenerator" class="org.apache.oltu.oauth2.as.issuer.MD5Generator">
-	</bean>
-	<bean id="oauthIssuer" class="org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl">
-		<constructor-arg index="0" ref="mdGenerator" />
-	</bean>
-
 	<bean id="kustvakt_userdb" class="de.ids_mannheim.korap.handlers.EntityDao">
 		<constructor-arg ref="kustvakt_db" />
 	</bean>
@@ -333,7 +327,7 @@
 		<constructor-arg index="0" value="${mail.username}" />
 		<constructor-arg index="1" value="${mail.password}" />
 	</bean>
-	<bean id="smtpSession" class="javax.mail.Session" factory-method="getInstance">
+	<bean id="smtpSession" class="jakarta.mail.Session" factory-method="getInstance">
 		<constructor-arg index="0">
 			<props>
 				<prop key="mail.smtp.submitter">${mail.username}</prop>
diff --git a/full/src/main/resources/default-config.xml b/full/src/main/resources/default-config.xml
index 7cda1cd..f726e2a 100644
--- a/full/src/main/resources/default-config.xml
+++ b/full/src/main/resources/default-config.xml
@@ -46,13 +46,13 @@
 		</property>
 	</bean>
 
-	<bean id='cacheManager' class='org.springframework.cache.ehcache.EhCacheCacheManager'
+	<!-- <bean id='cacheManager' class='org.springframework.cache.ehcache.EhCacheCacheManager'
 		p:cacheManager-ref='ehcache' />
 
 	<bean id='ehcache'
 		class='org.springframework.cache.ehcache.EhCacheManagerFactoryBean'
 		p:configLocation='classpath:ehcache.xml' p:shared='true' />
-
+ -->
 	<!--class="org.apache.commons.dbcp2.BasicDataSource" -->
 	<!-- org.springframework.jdbc.datasource.SingleConnectionDataSource -->
 	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
@@ -242,26 +242,12 @@
 	<bean id="oauth2ResponseHandler" class="de.ids_mannheim.korap.web.OAuth2ResponseHandler">
 	</bean>
 
-	<bean id="mdGenerator" class="org.apache.oltu.oauth2.as.issuer.MD5Generator">
-	</bean>
-	<bean id="oauthIssuer" class="org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl">
-		<constructor-arg index="0" ref="mdGenerator" />
-	</bean>
-
 	<bean name="kustvakt_encryption" class="de.ids_mannheim.korap.encryption.KustvaktEncryption">
 		<constructor-arg ref="kustvakt_config" />
 	</bean>
 
 	<!-- authentication providers to use -->
 
-	<!-- <bean id="openid_auth"
-		class="de.ids_mannheim.korap.authentication.OpenIDconnectAuthentication">
-		<constructor-arg type="de.ids_mannheim.korap.config.KustvaktConfiguration"
-			ref="kustvakt_config" />
-		<constructor-arg
-			type="de.ids_mannheim.korap.interfaces.db.PersistenceClient" ref="kustvakt_db" />
-	</bean> -->
-
 	<!-- <bean id="session_auth"
 		class="de.ids_mannheim.korap.authentication.SessionAuthentication">
 		<constructor-arg type="de.ids_mannheim.korap.config.KustvaktConfiguration"
@@ -276,7 +262,6 @@
 	<util:list id="kustvakt_authproviders"
 		value-type="de.ids_mannheim.korap.interfaces.AuthenticationIface">
 		<!-- <ref bean="session_auth" /> -->
-		<!-- <ref bean="openid_auth" /> -->
 		<ref bean="oauth2_auth" />
 	</util:list>
 
@@ -326,7 +311,7 @@
 		<constructor-arg index="0" value="${mail.username}" />
 		<constructor-arg index="1" value="${mail.password}" />
 	</bean>
-	<bean id="smtpSession" class="javax.mail.Session" factory-method="getInstance">
+	<bean id="smtpSession" class="jakarta.mail.Session" factory-method="getInstance">
 		<constructor-arg index="0">
 			<props>
 				<prop key="mail.smtp.submitter">${mail.username}</prop>
diff --git a/full/src/main/resources/properties/hibernate.properties b/full/src/main/resources/properties/hibernate.properties
index 23979b2..e394a88 100644
--- a/full/src/main/resources/properties/hibernate.properties
+++ b/full/src/main/resources/properties/hibernate.properties
@@ -1,4 +1,4 @@
-hibernate.dialect=org.hibernate.dialect.SQLiteDialect
+hibernate.dialect=org.hibernate.community.dialect.SQLiteDialect
 hibernate.hbm2ddl.auto=none
 hibernate.show_sql=false
 hibernate.cache.use_query_cache=false
diff --git a/full/src/main/resources/service.properties b/full/src/main/resources/service.properties
index cf2899d..2f428f5 100644
--- a/full/src/main/resources/service.properties
+++ b/full/src/main/resources/service.properties
@@ -1,3 +1,4 @@
 kustvakt.version=${project.version}
 krill.version=${krill.version}
-koral.version=${koral.version}
\ No newline at end of file
+koral.version=${koral.version}
+kustvakt.cache=true
\ No newline at end of file
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 0de58d3..3c8f808 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
@@ -6,9 +6,6 @@
 import java.util.HashMap;
 import java.util.Map;
 
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 
@@ -28,6 +25,8 @@
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
 import de.ids_mannheim.korap.web.controller.OAuth2TestBase;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 public class APIAuthenticationTest extends OAuth2TestBase {
 
diff --git a/full/src/test/java/de/ids_mannheim/korap/authentication/AuthenticationFilterTest.java b/full/src/test/java/de/ids_mannheim/korap/authentication/AuthenticationFilterTest.java
index 1aebf69..892219b 100644
--- a/full/src/test/java/de/ids_mannheim/korap/authentication/AuthenticationFilterTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/authentication/AuthenticationFilterTest.java
@@ -5,12 +5,11 @@
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
 
-import javax.ws.rs.core.Response;
-
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import jakarta.ws.rs.core.Response;
 
 public class AuthenticationFilterTest extends SpringJerseyTest {
 
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 e5b1f38..fd59d79 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
@@ -4,10 +4,6 @@
 
 import java.net.URI;
 import java.security.GeneralSecurityException;
-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;
 import org.junit.jupiter.api.AfterEach;
@@ -35,6 +31,9 @@
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.web.controller.OAuth2TestBase;
 import de.ids_mannheim.korap.web.input.OAuth2ClientJson;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 public class LdapOAuth2Test extends OAuth2TestBase {
 
@@ -103,8 +102,9 @@
         String clientSecret = node.at("/client_secret").asText();
         testRequestTokenWithAuthorization(clientId, clientSecret, accessToken);
     }
-
-    private void testRegisterPublicClient(String accessToken) throws ProcessingException, KustvaktException {
+    
+    private void testRegisterPublicClient (String accessToken)
+            throws KustvaktException {
         OAuth2ClientJson json = new OAuth2ClientJson();
         json.setName("LDAP test client");
         json.setType(OAuth2ClientType.PUBLIC);
@@ -116,8 +116,9 @@
         OAuth2Client client = clientDao.retrieveClientById(clientId);
         assertEquals(testUsername, client.getRegisteredBy());
     }
-
-    private JsonNode testRegisterConfidentialClient(String accessToken) throws ProcessingException, KustvaktException {
+    
+    private JsonNode testRegisterConfidentialClient (String accessToken)
+            throws KustvaktException {
         OAuth2ClientJson json = new OAuth2ClientJson();
         json.setName("LDAP test client");
         json.setType(OAuth2ClientType.CONFIDENTIAL);
diff --git a/full/src/test/java/de/ids_mannheim/korap/authentication/RandomCodeGeneratorTest.java b/full/src/test/java/de/ids_mannheim/korap/authentication/RandomCodeGeneratorTest.java
index c23f168..a3694f0 100644
--- a/full/src/test/java/de/ids_mannheim/korap/authentication/RandomCodeGeneratorTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/authentication/RandomCodeGeneratorTest.java
@@ -4,8 +4,6 @@
 
 import java.security.NoSuchAlgorithmException;
 
-import org.apache.oltu.oauth2.as.issuer.MD5Generator;
-import org.apache.oltu.oauth2.common.exception.OAuthSystemException;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -26,7 +24,7 @@
     }
 
     @Disabled
-    public void testRandomGeneratorPerformance() throws OAuthSystemException, NoSuchAlgorithmException, KustvaktException {
+    public void testRandomGeneratorPerformance() throws NoSuchAlgorithmException, KustvaktException {
         long min = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
         String code;
         while (true) {
@@ -44,12 +42,4 @@
             System.out.println("d : " + duration + " min :" + min + ", max: " + max);
         }
     }
-
-    @Disabled
-    public void testMD5Generator() throws OAuthSystemException, NoSuchAlgorithmException, KustvaktException {
-        MD5Generator m = new MD5Generator();
-        String value = m.generateValue();
-        value = m.generateValue(value);
-        System.out.println(value);
-    }
 }
diff --git a/full/src/test/java/de/ids_mannheim/korap/cache/TotalResultTest.java b/full/src/test/java/de/ids_mannheim/korap/cache/TotalResultTest.java
index 9b63639..5beb40b 100644
--- a/full/src/test/java/de/ids_mannheim/korap/cache/TotalResultTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/cache/TotalResultTest.java
@@ -3,8 +3,6 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -13,16 +11,36 @@
 import de.ids_mannheim.korap.core.service.SearchService;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 public class TotalResultTest extends SpringJerseyTest {
 
     @Autowired
     private SearchService searchService;
+    
+    @Test
+    public void testClearCache () {
+        for (int i = 1; i < 10; i++) {
+            searchService.getTotalResultCache().storeInCache(i, "10");
+        }
+        
+        searchService.getTotalResultCache().clearCache();
+        
+        assertEquals(0, searchService.getTotalResultCache()
+                .getAllCacheElements().size());
+    }
 
     @Test
-    public void testSearchWithPaging() throws KustvaktException {
-        assertEquals(0, searchService.getTotalResultCache().getAllCacheElements().size());
-        Response response = target().path(API_VERSION).path("search").queryParam("q", "[orth=die]").queryParam("ql", "poliqarp").queryParam("page", "1").request().get();
+    public void testSearchWithPaging () throws KustvaktException {
+        searchService.getTotalResultCache().clearCache();
+        
+        assertEquals(0, searchService.getTotalResultCache()
+                .getAllCacheElements().size());
+        
+        Response response = target().path(API_VERSION).path("search")
+                .queryParam("q", "[orth=die]").queryParam("ql", "poliqarp")
+                .queryParam("page", "1").request().get();
         assertEquals(Status.OK.getStatusCode(), response.getStatus());
         String entity = response.readEntity(String.class);
         JsonNode node = JsonUtils.readTree(entity);
diff --git a/full/src/test/java/de/ids_mannheim/korap/config/StaticContextLoaderListener.java b/full/src/test/java/de/ids_mannheim/korap/config/StaticContextLoaderListener.java
index 5dd00a0..d4cf8d9 100644
--- a/full/src/test/java/de/ids_mannheim/korap/config/StaticContextLoaderListener.java
+++ b/full/src/test/java/de/ids_mannheim/korap/config/StaticContextLoaderListener.java
@@ -1,10 +1,11 @@
 package de.ids_mannheim.korap.config;
 
-import javax.servlet.ServletContextEvent;
 
 import org.springframework.web.context.ContextLoaderListener;
 import org.springframework.web.context.WebApplicationContext;
 
+import jakarta.servlet.ServletContextEvent;
+
 /**
  * A hack to inject the application context generated by
  * SpringJUnit4ClassRunner in the test suite.
diff --git a/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusDaoTest.java b/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusDaoTest.java
index 826a687..02c4642 100644
--- a/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusDaoTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/dao/VirtualCorpusDaoTest.java
@@ -6,7 +6,7 @@
 import java.util.Iterator;
 import java.util.List;
 
-import javax.persistence.PersistenceException;
+import jakarta.persistence.PersistenceException;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -52,11 +52,14 @@
     }
 
     @Test
-    public void testNonUniqueVC() throws KustvaktException {
-        PersistenceException exception = assertThrows(PersistenceException.class, () -> {
-            dao.createQuery("system-vc", ResourceType.SYSTEM, QueryType.VIRTUAL_CORPUS, User.CorpusAccess.FREE, "corpusSigle=GOE", "definition", "description", "experimental", false, "system", null, null);
-        });
-        assertEquals(exception.getMessage(), "org.hibernate.exception.GenericJDBCException: could not execute statement");
+    public void testNonUniqueVC () throws KustvaktException {
+        
+        PersistenceException exception = assertThrows(PersistenceException.class, ()->{
+            dao.createQuery("system-vc", ResourceType.SYSTEM,
+                    QueryType.VIRTUAL_CORPUS, User.CorpusAccess.FREE,
+                    "corpusSigle=GOE", "definition", "description", "experimental",
+                    false, "system", null, null);
+        });        
     }
 
     @Test
diff --git a/full/src/test/java/de/ids_mannheim/korap/misc/LocalQueryTest.java b/full/src/test/java/de/ids_mannheim/korap/misc/LocalQueryTest.java
index e37f5d2..a7b5c01 100644
--- a/full/src/test/java/de/ids_mannheim/korap/misc/LocalQueryTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/misc/LocalQueryTest.java
@@ -3,7 +3,8 @@
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import java.io.IOException;
-import javax.annotation.PostConstruct;
+
+import jakarta.annotation.PostConstruct;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/full/src/test/java/de/ids_mannheim/korap/misc/MapUtilsTest.java b/full/src/test/java/de/ids_mannheim/korap/misc/MapUtilsTest.java
index cca0f47..35e995e 100644
--- a/full/src/test/java/de/ids_mannheim/korap/misc/MapUtilsTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/misc/MapUtilsTest.java
@@ -3,12 +3,12 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.util.Map;
-import javax.ws.rs.core.MultivaluedHashMap;
-import javax.ws.rs.core.MultivaluedMap;
 
 import org.junit.jupiter.api.Test;
 import de.ids_mannheim.korap.web.utils.MapUtils;
 import edu.emory.mathcs.backport.java.util.Arrays;
+import jakarta.ws.rs.core.MultivaluedHashMap;
+import jakarta.ws.rs.core.MultivaluedMap;
 
 public class MapUtilsTest {
 
diff --git a/full/src/test/java/de/ids_mannheim/korap/rewrite/FoundryRewriteTest.java b/full/src/test/java/de/ids_mannheim/korap/rewrite/FoundryRewriteTest.java
index c079a25..65d3752 100644
--- a/full/src/test/java/de/ids_mannheim/korap/rewrite/FoundryRewriteTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/rewrite/FoundryRewriteTest.java
@@ -5,16 +5,10 @@
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.MediaType;
-
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import com.fasterxml.jackson.databind.JsonNode;
 
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
@@ -23,6 +17,10 @@
 import de.ids_mannheim.korap.query.serialize.QuerySerializer;
 import de.ids_mannheim.korap.user.KorAPUser;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 /**
  * @author hanl, margaretha
diff --git a/full/src/test/java/de/ids_mannheim/korap/rewrite/QueryRewriteTest.java b/full/src/test/java/de/ids_mannheim/korap/rewrite/QueryRewriteTest.java
index dcaadbc..8862def 100644
--- a/full/src/test/java/de/ids_mannheim/korap/rewrite/QueryRewriteTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/rewrite/QueryRewriteTest.java
@@ -5,13 +5,12 @@
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
 
-import javax.ws.rs.core.Response;
-
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import jakarta.ws.rs.core.Response;
 
 /**
  * @author diewald
diff --git a/full/src/test/java/de/ids_mannheim/korap/rewrite/VirtualCorpusRewriteTest.java b/full/src/test/java/de/ids_mannheim/korap/rewrite/VirtualCorpusRewriteTest.java
index 135b516..170ffd0 100644
--- a/full/src/test/java/de/ids_mannheim/korap/rewrite/VirtualCorpusRewriteTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/rewrite/VirtualCorpusRewriteTest.java
@@ -12,8 +12,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.cache.VirtualCorpusCache;
 import de.ids_mannheim.korap.config.Attributes;
@@ -24,6 +22,7 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.util.QueryException;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import jakarta.ws.rs.core.Response;
 
 /**
  * @author margaretha
diff --git a/full/src/test/java/de/ids_mannheim/korap/scenario/ICCTest.java b/full/src/test/java/de/ids_mannheim/korap/scenario/ICCTest.java
index f83c127..0119a21 100644
--- a/full/src/test/java/de/ids_mannheim/korap/scenario/ICCTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/scenario/ICCTest.java
@@ -4,9 +4,6 @@
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
 import org.junit.jupiter.api.Test;
 import org.springframework.test.context.ContextConfiguration;
 import com.fasterxml.jackson.databind.JsonNode;
@@ -16,6 +13,8 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 /**
  * <p>Test scenario for ICC (International Comparable Corpus)
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/ApiVersionTest.java b/full/src/test/java/de/ids_mannheim/korap/web/ApiVersionTest.java
index 4826743..e06fe0d 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/ApiVersionTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/ApiVersionTest.java
@@ -3,15 +3,14 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.net.URI;
-import javax.ws.rs.core.MediaType;
 
 import org.eclipse.jetty.http.HttpStatus;
 import org.junit.jupiter.api.Test;
 
-import javax.ws.rs.core.Response;
-
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
 
 /**
  * @author margaretha
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/InitialSuperClientTest.java b/full/src/test/java/de/ids_mannheim/korap/web/InitialSuperClientTest.java
index 2cdb620..a936e6b 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/InitialSuperClientTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/InitialSuperClientTest.java
@@ -5,14 +5,11 @@
 
 import java.io.File;
 import java.io.IOException;
-import javax.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import com.fasterxml.jackson.databind.JsonNode;
 
-import javax.ws.rs.core.Response;
-
 import de.ids_mannheim.korap.config.FullConfiguration;
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
@@ -21,6 +18,8 @@
 import de.ids_mannheim.korap.oauth2.service.OAuth2InitClientService;
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.web.controller.OAuth2TestBase;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 public class InitialSuperClientTest extends OAuth2TestBase {
 
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/JettyServerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/JettyServerTest.java
index 873f0a9..0255c45 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/JettyServerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/JettyServerTest.java
@@ -12,11 +12,13 @@
 import org.eclipse.jetty.server.handler.HandlerList;
 import org.eclipse.jetty.server.handler.ShutdownHandler;
 import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 /**
  * @author margaretha
  */
+@Disabled
 public class JettyServerTest {
 
     @BeforeAll
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/SearchKrillTest.java b/full/src/test/java/de/ids_mannheim/korap/web/SearchKrillTest.java
index 31df174..c4476c2 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/SearchKrillTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/SearchKrillTest.java
@@ -4,7 +4,7 @@
 import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
-import javax.annotation.PostConstruct;
+import jakarta.annotation.PostConstruct;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/AdminLoadVCTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/AdminLoadVCTest.java
index 62f6a56..c7bc757 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/AdminLoadVCTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/AdminLoadVCTest.java
@@ -4,17 +4,18 @@
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
 import org.junit.jupiter.api.Test;
+
 import com.google.common.net.HttpHeaders;
+
 import de.ids_mannheim.korap.cache.VirtualCorpusCache;
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 public class AdminLoadVCTest extends SpringJerseyTest {
 
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/AnnotationControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/AnnotationControllerTest.java
index 7a61c36..9626114 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/AnnotationControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/AnnotationControllerTest.java
@@ -5,16 +5,16 @@
 
 import java.util.Iterator;
 import java.util.Map.Entry;
-import javax.ws.rs.client.Entity;
 
 import org.junit.jupiter.api.Test;
-import com.fasterxml.jackson.databind.JsonNode;
 
-import javax.ws.rs.core.Response;
+import com.fasterxml.jackson.databind.JsonNode;
 
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Response;
 
 public class AnnotationControllerTest extends SpringJerseyTest {
 
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/AvailabilityTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/AvailabilityTest.java
index fa58f95..ca4c915 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/AvailabilityTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/AvailabilityTest.java
@@ -7,10 +7,9 @@
 import org.junit.jupiter.api.Test;
 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.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/FreeResourceControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/FreeResourceControllerTest.java
index a6b4457..e8a5d79 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/FreeResourceControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/FreeResourceControllerTest.java
@@ -5,8 +5,7 @@
 import org.junit.jupiter.api.Test;
 import org.springframework.test.context.ContextConfiguration;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response;
 
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/IndexControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/IndexControllerTest.java
index 10891d0..ef70ac5 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/IndexControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/IndexControllerTest.java
@@ -9,16 +9,16 @@
 import java.nio.file.LinkOption;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
 
 import org.apache.http.HttpStatus;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/InfoControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/InfoControllerTest.java
index 3d5e3f1..fd12bdb 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/InfoControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/InfoControllerTest.java
@@ -5,9 +5,8 @@
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.config.SpringJerseyTest;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/MatchInfoControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/MatchInfoControllerTest.java
index 85745aa..09a72be 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/MatchInfoControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/MatchInfoControllerTest.java
@@ -7,9 +7,8 @@
 import org.junit.jupiter.api.Test;
 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 jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/MetadataControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/MetadataControllerTest.java
index bfa59e7..147d893 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/MetadataControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/MetadataControllerTest.java
@@ -7,9 +7,8 @@
 import org.junit.jupiter.api.Test;
 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 jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/MultipleCorpusQueryTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/MultipleCorpusQueryTest.java
index 4ec1fe8..26a121f 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/MultipleCorpusQueryTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/MultipleCorpusQueryTest.java
@@ -5,10 +5,9 @@
 
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
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 ed61f10..c35014e 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
@@ -5,10 +5,11 @@
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.IOException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
 import org.apache.oltu.oauth2.common.message.types.GrantType;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AdminControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AdminControllerTest.java
index 5ea99fe..2a143cb 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AdminControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AdminControllerTest.java
@@ -3,11 +3,11 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
 import org.junit.jupiter.api.Order;
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 732d8c1..9e1542d 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
@@ -4,11 +4,12 @@
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import java.net.URI;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MultivaluedMap;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
 import org.apache.oltu.oauth2.common.message.types.TokenType;
@@ -58,16 +59,20 @@
         authForm.param("scope", "search");
         Response response = requestAuthorizationCode(authForm, userAuthHeader);
         URI redirectUri = response.getLocation();
-        MultivaluedMap<String, String> params = UriComponent.decodeQuery(redirectUri, true);
+
+        MultivaluedMap<String, String> params =
+                UriComponent.decodeQuery(redirectUri, true);
         String code = params.get("code").get(0);
-        String scopes = params.get("scope").get(0);
-        assertEquals(scopes, "search");
-        response = requestTokenWithAuthorizationCodeAndForm(confidentialClientId, clientSecret, code);
+
+
+        response = requestTokenWithAuthorizationCodeAndForm(
+                confidentialClientId, clientSecret, code);
         String entity = response.readEntity(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());
+        assertEquals(TokenType.BEARER.toString(),
+                node.at("/token_type").asText());
         assertNotNull(node.at("/expires_in").asText());
     }
 }
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AuthorizationTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AuthorizationTest.java
new file mode 100644
index 0000000..d9861c2
--- /dev/null
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2AuthorizationTest.java
@@ -0,0 +1,301 @@
+package de.ids_mannheim.korap.web.controller;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.net.URI;
+import org.junit.jupiter.api.Test;
+
+import org.apache.oltu.oauth2.common.error.OAuthError;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
+
+import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
+import de.ids_mannheim.korap.exceptions.KustvaktException;
+import de.ids_mannheim.korap.exceptions.StatusCodes;
+import de.ids_mannheim.korap.utils.JsonUtils;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+
+public class OAuth2AuthorizationTest extends OAuth2TestBase {
+    
+    private String userAuthHeader;
+
+    public OAuth2AuthorizationTest () throws KustvaktException {
+        userAuthHeader = HttpAuthorizationHandler
+                .createBasicAuthorizationHeaderValue("dory", "password");
+    }
+    
+    @Test
+    public void testAuthorizeUnauthenticated () throws KustvaktException {
+
+        Response response = requestAuthorizationCode("code", publicClientId, "",
+                "search match_info", "", "");
+        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
+        String entity = response.readEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(StatusCodes.AUTHORIZATION_FAILED,
+                node.at("/errors/0/0").asInt());
+        assertEquals("Unauthorized operation for user: guest",
+                node.at("/errors/0/1").asText());
+    }
+    @Test
+    public void testAuthorizeConfidentialClient () throws KustvaktException {
+        // with registered redirect URI
+        Response response =
+                requestAuthorizationCode("code", confidentialClientId, "",
+                        "match_info search client_info", state, userAuthHeader);
+
+        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+                response.getStatus());
+        URI redirectUri = response.getLocation();
+        MultivaluedMap<String, String> params =
+                getQueryParamsFromURI(redirectUri);
+        assertNotNull(params.getFirst("code"));
+        assertEquals(state, params.getFirst("state"));
+    }
+
+    @Test
+    public void testAuthorizePublicClient () throws KustvaktException {
+        // with registered redirect URI
+        String code = requestAuthorizationCode(publicClientId, userAuthHeader);
+        assertNotNull(code);
+    }
+
+    @Test
+    public void testAuthorizeWithRedirectUri () throws KustvaktException {
+        Response response =
+                requestAuthorizationCode("code", publicClientId2,
+                        "https://public.com/redirect", "search match_info", 
+                        "", userAuthHeader);
+        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+                response.getStatus());
+
+        URI redirectUri = response.getLocation();
+        assertEquals("https", redirectUri.getScheme());
+        assertEquals("public.com", redirectUri.getHost());
+        assertEquals("/redirect", redirectUri.getPath());
+
+        assertTrue(redirectUri.getQuery().startsWith("code="));
+    }
+
+    @Test
+    public void testAuthorizeWithoutScope () throws KustvaktException {
+        Response response = requestAuthorizationCode("code",
+                confidentialClientId, "", "", "", userAuthHeader);
+        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+                response.getStatus());
+
+        URI redirectUri = response.getLocation();
+        assertEquals(redirectUri.getScheme(), "https");
+        assertEquals(redirectUri.getHost(), "third.party.com");
+        assertEquals(redirectUri.getPath(), "/confidential/redirect");
+
+        String[] queryParts = redirectUri.getQuery().split("&");
+        assertEquals("error_description=scope+is+required",
+                queryParts[1]);
+        assertEquals("error=invalid_scope", queryParts[0]);
+    }
+
+    @Test
+    public void testAuthorizeMissingClientId () throws KustvaktException {
+        Response response = requestAuthorizationCode("code", "", "", "search",
+                "", userAuthHeader);
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+        String entity = response.readEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals("Missing parameter: client_id",
+                node.at("/error_description").asText());
+    }
+
+    @Test
+    public void testAuthorizeMissingRedirectUri () throws KustvaktException {
+        Response response = requestAuthorizationCode("code",
+                publicClientId2, "", "search", state, userAuthHeader);
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+        String entity = response.readEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(OAuth2Error.INVALID_REQUEST.getCode(),
+                node.at("/error").asText());
+        assertEquals("Missing parameter: redirect URI",
+                node.at("/error_description").asText());
+        assertEquals(state, node.at("/state").asText());
+    }
+
+    @Test
+    public void testAuthorizeMissingResponseType() throws KustvaktException {
+        Response response = requestAuthorizationCode("",
+                confidentialClientId, "", "search", "", userAuthHeader);
+        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+                response.getStatus());
+
+        assertEquals("https://third.party.com/confidential/redirect?"
+                + "error=invalid_request_uri&"
+                + "error_description=Missing+response_type+parameter"
+                , response.getLocation().toString());
+    }
+    
+    @Test
+    public void testAuthorizeMissingResponseTypeWithoutClientId () throws KustvaktException {
+        Response response = requestAuthorizationCode("",
+                "", "", "search", "", userAuthHeader);
+        
+        assertEquals(Status.BAD_REQUEST.getStatusCode(),
+                response.getStatus());
+        String entity = response.readEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        
+        assertEquals(OAuthError.CodeResponse.INVALID_REQUEST,
+                node.at("/error").asText());
+        assertEquals("Missing parameter: client_id",
+                node.at("/error_description").asText());
+    }
+
+    @Test
+    public void testAuthorizeInvalidClientId () throws KustvaktException {
+        Response response = requestAuthorizationCode("code",
+                "unknown-client-id", "", "search", "", userAuthHeader);
+        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
+        String entity = response.readEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(OAuth2Error.INVALID_CLIENT.getCode(), node.at("/error").asText());
+        assertEquals("Unknown client: unknown-client-id",
+                node.at("/error_description").asText());
+    }
+
+    @Test
+    public void testAuthorizeDifferentRedirectUri () throws KustvaktException {
+        String redirectUri = "https://different.uri/redirect";
+        Response response = requestAuthorizationCode("code",
+                confidentialClientId, redirectUri, "", state, userAuthHeader);
+        
+        testInvalidRedirectUri(response.readEntity(String.class), 
+                response.getHeaderString("Content-Type"),true,
+                response.getStatus());
+    }
+
+    @Test
+    public void testAuthorizeWithRedirectUriLocalhost ()
+            throws KustvaktException {
+        Response response = requestAuthorizationCode("code", publicClientId2,
+                "http://localhost:1410", "search", state, userAuthHeader);
+        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+                response.getStatus());
+
+        URI redirectUri = response.getLocation();
+        MultivaluedMap<String, String> params =
+                getQueryParamsFromURI(redirectUri);
+        assertNotNull(params.getFirst("code"));
+        assertEquals(state, params.getFirst("state"));
+    }
+
+    @Test
+    public void testAuthorizeWithRedirectUriFragment ()
+            throws KustvaktException {
+        Response response = requestAuthorizationCode("code",
+                publicClientId2, "http://public.com/index.html#redirect", "search",
+                state, userAuthHeader);
+        testInvalidRedirectUri(response.readEntity(String.class), 
+                response.getHeaderString("Content-Type"),true,
+                response.getStatus());
+    }
+
+    @Test
+    public void testAuthorizeInvalidRedirectUri () throws KustvaktException {
+        // host not allowed by Apache URI Validator
+        String redirectUri = "https://public.uri/redirect";
+        Response response = requestAuthorizationCode("code",
+                publicClientId2, redirectUri, "", state, userAuthHeader);
+        testInvalidRedirectUri(response.readEntity(String.class), 
+                response.getHeaderString("Content-Type"),true,
+                response.getStatus());
+    }
+
+    @Test
+    public void testAuthorizeInvalidResponseType () throws KustvaktException {
+        // without redirect URI in the request
+        Response response = requestAuthorizationCode("string",
+                confidentialClientId, "", "search", state, userAuthHeader);
+        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+                response.getStatus());
+
+        assertEquals("https://third.party.com/confidential/redirect?"
+                + "error=unsupported_response_type"
+                + "&error_description=Unsupported+response+type.+Only+code+is+supported."
+                + "&state=thisIsMyState" ,
+                response.getLocation().toString());
+
+        // with redirect URI, and no registered redirect URI
+        response = requestAuthorizationCode("string", publicClientId2,
+                "https://public.client.com/redirect", "search", state,
+                userAuthHeader);
+        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+                response.getStatus());
+
+        assertEquals("https://public.client.com/redirect?"
+                + "error=unsupported_response_type"
+                + "&error_description=Unsupported+response+type.+Only+code+is+supported."
+                + "&state=thisIsMyState", 
+                response.getLocation().toString());
+
+        // with different redirect URI
+        String redirectUri = "https://different.uri/redirect";
+        response = requestAuthorizationCode("string", confidentialClientId,
+                redirectUri, "", state, userAuthHeader);
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
+        assertEquals(OAuthError.CodeResponse.INVALID_REQUEST,
+                node.at("/error").asText());
+        assertEquals("Invalid redirect URI",
+                node.at("/error_description").asText());
+        assertEquals(state, node.at("/state").asText());
+
+        // without redirect URI in the request and no registered
+        // redirect URI
+        response = requestAuthorizationCode("string", publicClientId2, "", "",
+                state, userAuthHeader);
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+        node = JsonUtils.readTree(response.readEntity(String.class));
+        assertEquals(OAuthError.CodeResponse.INVALID_REQUEST,
+                node.at("/error").asText());
+        assertEquals("Missing parameter: redirect URI",
+                node.at("/error_description").asText());
+        assertEquals(state, node.at("/state").asText());
+    }
+
+    @Test
+    public void testAuthorizeInvalidScope () throws KustvaktException {
+        String scope = "read_address";
+        Response response = requestAuthorizationCode("code",
+                confidentialClientId, "", scope, state, userAuthHeader);
+        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+                response.getStatus());
+
+        assertEquals(
+                "https://third.party.com/confidential/redirect?"
+                + "error=invalid_scope&error_description=Invalid+"
+                +"scope&state=thisIsMyState",
+                response.getLocation().toString());
+    }
+
+    @Test
+    public void testAuthorizeUnsupportedTokenResponseType ()
+            throws KustvaktException {
+        Response response = requestAuthorizationCode("token",
+                confidentialClientId, "", "search", state, userAuthHeader);
+        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
+                response.getStatus());
+
+        assertEquals("https://third.party.com/confidential/redirect?"
+                + "error=unsupported_response_type"
+                + "&error_description=Unsupported+response+type.+Only+code+is+supported."
+                + "&state=thisIsMyState", response.getLocation().toString());
+    }
+
+}
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
index d210ffd..127e2d2 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2ClientControllerTest.java
@@ -11,11 +11,12 @@
 import java.util.List;
 import java.util.Map.Entry;
 import java.util.Set;
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.http.entity.ContentType;
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 32d33ae..6374959 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
@@ -4,14 +4,8 @@
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import java.net.URI;
 import java.time.ZonedDateTime;
 import java.util.Set;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-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.error.OAuthError;
@@ -29,6 +23,11 @@
 import de.ids_mannheim.korap.oauth2.entity.AccessScope;
 import de.ids_mannheim.korap.oauth2.entity.RefreshToken;
 import de.ids_mannheim.korap.utils.JsonUtils;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 /**
  * @author margaretha
@@ -45,174 +44,8 @@
     }
 
     @Test
-    public void testAuthorizeConfidentialClient() throws KustvaktException {
-        // with registered redirect URI
-        Response response = requestAuthorizationCode("code", confidentialClientId, "", "match_info search client_info", state, userAuthHeader);
-        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(), response.getStatus());
-        URI redirectUri = response.getLocation();
-        MultivaluedMap<String, String> params = getQueryParamsFromURI(redirectUri);
-        assertNotNull(params.getFirst("code"));
-        assertEquals(state, params.getFirst("state"));
-        assertEquals(params.getFirst("scope"), "match_info search client_info");
-    }
-
-    @Test
-    public void testAuthorizePublicClient() throws KustvaktException {
-        // with registered redirect URI
-        String code = requestAuthorizationCode(publicClientId, userAuthHeader);
-        assertNotNull(code);
-    }
-
-    @Test
-    public void testAuthorizeWithRedirectUri() throws KustvaktException {
-        Response response = requestAuthorizationCode("code", publicClientId2, "https://public.com/redirect", "search match_info", "", userAuthHeader);
-        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(), response.getStatus());
-        URI redirectUri = response.getLocation();
-        assertEquals(redirectUri.getScheme(), "https");
-        assertEquals(redirectUri.getHost(), "public.com");
-        assertEquals(redirectUri.getPath(), "/redirect");
-        String[] queryParts = redirectUri.getQuery().split("&");
-        assertTrue(queryParts[0].startsWith("code="));
-        assertEquals(queryParts[1], "scope=match_info+search");
-    }
-
-    @Test
-    public void testAuthorizeWithoutScope() throws KustvaktException {
-        Response response = requestAuthorizationCode("code", confidentialClientId, "", "", "", userAuthHeader);
-        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(), response.getStatus());
-        URI redirectUri = response.getLocation();
-        assertEquals(redirectUri.getScheme(), "https");
-        assertEquals(redirectUri.getHost(), "third.party.com");
-        assertEquals(redirectUri.getPath(), "/confidential/redirect");
-        String[] queryParts = redirectUri.getQuery().split("&");
-        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", "", "", "search", "", userAuthHeader);
-        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(node.at("/error_description").asText(), "Missing parameters: client_id");
-    }
-
-    @Test
-    public void testAuthorizeMissingRedirectUri() throws KustvaktException {
-        Response response = requestAuthorizationCode("code", publicClientId2, "", "search", state, userAuthHeader);
-        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuthError.CodeResponse.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Missing parameter: redirect URI");
-        assertEquals(state, node.at("/state").asText());
-    }
-
-    @Test
-    public void testAuthorizeMissingResponseType() throws KustvaktException {
-        Response response = requestAuthorizationCode("", confidentialClientId, "", "search", "", userAuthHeader);
-        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(), response.getStatus());
-        assertEquals("https://third.party.com/confidential/redirect?" + "error_description=Missing+parameters%3A+response_type&" + "error=invalid_request", response.getLocation().toString());
-    }
-
-    @Test
-    public void testAuthorizeMissingResponseTypeWithoutClientId() throws KustvaktException {
-        Response response = requestAuthorizationCode("", "", "", "search", "", userAuthHeader);
-        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuthError.CodeResponse.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Missing parameters: response_type client_id");
-    }
-
-    @Test
-    public void testAuthorizeInvalidClientId() throws KustvaktException {
-        Response response = requestAuthorizationCode("code", "unknown-client-id", "", "search", "", userAuthHeader);
-        assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_CLIENT, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Unknown client: unknown-client-id");
-    }
-
-    @Test
-    public void testAuthorizeDifferentRedirectUri() throws KustvaktException {
-        String redirectUri = "https://different.uri/redirect";
-        Response response = requestAuthorizationCode("code", confidentialClientId, redirectUri, "", state, userAuthHeader);
-        testInvalidRedirectUri(response.readEntity(String.class), response.getHeaderString("Content-Type"), true, response.getStatus());
-    }
-
-    @Test
-    public void testAuthorizeWithRedirectUriLocalhost() throws KustvaktException {
-        Response response = requestAuthorizationCode("code", publicClientId2, "http://localhost:1410", "search", state, userAuthHeader);
-        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(), response.getStatus());
-        URI redirectUri = response.getLocation();
-        MultivaluedMap<String, String> params = getQueryParamsFromURI(redirectUri);
-        assertNotNull(params.getFirst("code"));
-        assertEquals(state, params.getFirst("state"));
-        assertEquals(params.getFirst("scope"), "search");
-    }
-
-    @Test
-    public void testAuthorizeWithRedirectUriFragment() throws KustvaktException {
-        Response response = requestAuthorizationCode("code", publicClientId2, "http://public.com/index.html#redirect", "search", state, userAuthHeader);
-        testInvalidRedirectUri(response.readEntity(String.class), response.getHeaderString("Content-Type"), true, response.getStatus());
-    }
-
-    @Test
-    public void testAuthorizeInvalidRedirectUri() throws KustvaktException {
-        // host not allowed by Apache URI Validator
-        String redirectUri = "https://public.uri/redirect";
-        Response response = requestAuthorizationCode("code", publicClientId2, redirectUri, "", state, userAuthHeader);
-        testInvalidRedirectUri(response.readEntity(String.class), response.getHeaderString("Content-Type"), true, response.getStatus());
-    }
-
-    @Test
-    public void testAuthorizeInvalidResponseType() throws KustvaktException {
-        // without redirect URI in the request
-        Response response = requestAuthorizationCode("string", confidentialClientId, "", "search", state, userAuthHeader);
-        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(), response.getStatus());
-        assertEquals("https://third.party.com/confidential/redirect?" + "error_description=Invalid+response_type+parameter+" + "value&state=thisIsMyState&" + "error=invalid_request", response.getLocation().toString());
-        // with redirect URI, and no registered redirect URI
-        response = requestAuthorizationCode("string", publicClientId2, "https://public.client.com/redirect", "", state, userAuthHeader);
-        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(), response.getStatus());
-        assertEquals("https://public.client.com/redirect?error_description=" + "Invalid+response_type+parameter+value&state=thisIsMyState&" + "error=invalid_request", response.getLocation().toString());
-        // with different redirect URI
-        String redirectUri = "https://different.uri/redirect";
-        response = requestAuthorizationCode("string", confidentialClientId, redirectUri, "", state, userAuthHeader);
-        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
-        JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
-        assertEquals(OAuthError.CodeResponse.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Invalid redirect URI");
-        assertEquals(state, node.at("/state").asText());
-        // without redirect URI in the request and no registered
-        // redirect URI
-        response = requestAuthorizationCode("string", publicClientId2, "", "", state, userAuthHeader);
-        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
-        node = JsonUtils.readTree(response.readEntity(String.class));
-        assertEquals(OAuthError.CodeResponse.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Missing parameter: redirect URI");
-        assertEquals(state, node.at("/state").asText());
-    }
-
-    @Test
-    public void testAuthorizeInvalidScope() throws KustvaktException {
-        String scope = "read_address";
-        Response response = requestAuthorizationCode("code", confidentialClientId, "", scope, state, userAuthHeader);
-        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(), response.getStatus());
-        assertEquals("https://third.party.com/confidential/redirect?" + "error_description=read_address+is+an+invalid+scope&" + "state=thisIsMyState&error=invalid_scope", response.getLocation().toString());
-    }
-
-    @Test
-    public void testAuthorizeUnsupportedTokenResponseType() throws KustvaktException {
-        Response response = requestAuthorizationCode("token", confidentialClientId, "", "search", state, userAuthHeader);
-        assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(), response.getStatus());
-        assertEquals("https://third.party.com/confidential/redirect?" + "error_description=response_type+token+is+not+" + "supported&state=thisIsMyState&error=unsupported_" + "response_type", response.getLocation().toString());
-    }
-
-    @Test
-    public void testRequestTokenAuthorizationPublic() throws KustvaktException {
+    public void testRequestTokenAuthorizationPublic ()
+            throws KustvaktException {
         String code = requestAuthorizationCode(publicClientId, userAuthHeader);
         Response response = requestTokenWithAuthorizationCodeAndForm(publicClientId, clientSecret, code);
         String entity = response.readEntity(String.class);
@@ -230,9 +63,9 @@
         Response response = requestAuthorizationCode("code", confidentialClientId, "", scope, state, userAuthHeader);
         MultivaluedMap<String, String> params = getQueryParamsFromURI(response.getLocation());
         String code = params.get("code").get(0);
-        String scopes = params.get("scope").get(0);
-        assertEquals(scopes, "search");
-        response = requestTokenWithAuthorizationCodeAndForm(confidentialClientId, clientSecret, code);
+
+        response = requestTokenWithAuthorizationCodeAndForm(
+                confidentialClientId, clientSecret, code);
         String entity = response.readEntity(String.class);
         JsonNode node = JsonUtils.readTree(entity);
         assertNotNull(node.at("/access_token").asText());
@@ -420,8 +253,24 @@
     }
 
     @Test
-    public void testRequestTokenPasswordGrantMissingClientSecret() throws KustvaktException {
-        Response response = requestTokenWithDoryPassword(confidentialClientId, "");
+    public void testRequestTokenPasswordGrantMissingClientSecret ()
+            throws KustvaktException {
+        Response response =
+                requestTokenWithDoryPassword(confidentialClientId, "");
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+        String entity = response.readEntity(String.class);
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(OAuthError.TokenResponse.INVALID_REQUEST,
+                node.at("/error").asText());
+        assertNotNull(node.at("/error_description").asText());
+    }
+    
+    @Test
+    public void testRequestTokenPasswordGrantEmptyClientSecret ()
+            throws KustvaktException {
+        Response response =
+                requestTokenWithDoryPassword(confidentialClientId, "");
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         String entity = response.readEntity(String.class);
         JsonNode node = JsonUtils.readTree(entity);
@@ -435,8 +284,23 @@
         String entity = response.readEntity(String.class);
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuthError.TokenResponse.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Missing parameters: client_id");
+        assertEquals(OAuthError.TokenResponse.INVALID_REQUEST,
+                node.at("/error").asText());
+        assertNotNull(node.at("/error_description").asText());
+    }
+    
+    @Test
+    public void testRequestTokenPasswordGrantEmptyClientId ()
+            throws KustvaktException {
+        Response response =
+                requestTokenWithDoryPassword("", clientSecret);
+        String entity = response.readEntity(String.class);
+        assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+        JsonNode node = JsonUtils.readTree(entity);
+        assertEquals(OAuthError.TokenResponse.INVALID_REQUEST,
+                node.at("/error").asText());
+        assertNotNull(node.at("/error_description").asText());
     }
 
     @Test
@@ -470,8 +334,9 @@
         String entity = response.readEntity(String.class);
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuthError.TokenResponse.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Missing parameters: client_secret");
+        assertEquals(OAuthError.TokenResponse.INVALID_REQUEST,
+                node.at("/error").asText());
+        assertNotNull(node.at("/error_description").asText());
     }
 
     @Test
@@ -511,8 +376,9 @@
         String entity = response.readEntity(String.class);
         assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
         JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(node.get("error_description").asText(), "Invalid grant_type parameter value");
-        assertEquals(OAuthError.TokenResponse.INVALID_REQUEST, node.get("error").asText());
+        assertNotNull(node.get("error_description").asText());
+        assertEquals(OAuthError.TokenResponse.INVALID_REQUEST,
+                node.get("error").asText());
     }
 
     private void testRequestRefreshTokenInvalidScope(String clientId, String refreshToken) 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
deleted file mode 100644
index 020ced2..0000000
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2OpenIdControllerTest.java
+++ /dev/null
@@ -1,334 +0,0 @@
-package de.ids_mannheim.korap.web.controller;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.net.URI;
-import java.security.NoSuchAlgorithmException;
-import java.security.spec.InvalidKeySpecException;
-import java.text.ParseException;
-import java.util.Date;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
-
-import org.apache.http.entity.ContentType;
-import org.apache.oltu.oauth2.common.message.types.TokenType;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.util.UriComponentsBuilder;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.google.common.net.HttpHeaders;
-import com.nimbusds.jose.JOSEException;
-import com.nimbusds.jose.JWSVerifier;
-import com.nimbusds.jose.crypto.RSASSAVerifier;
-import com.nimbusds.jose.jwk.JWKSet;
-import com.nimbusds.jose.jwk.RSAKey;
-import com.nimbusds.jwt.JWTClaimsSet;
-import com.nimbusds.jwt.SignedJWT;
-import com.nimbusds.oauth2.sdk.GrantType;
-
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.client.Entity;
-
-import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
-import de.ids_mannheim.korap.config.Attributes;
-import de.ids_mannheim.korap.config.FullConfiguration;
-import de.ids_mannheim.korap.config.SpringJerseyTest;
-import de.ids_mannheim.korap.exceptions.KustvaktException;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
-import de.ids_mannheim.korap.utils.JsonUtils;
-
-public class OAuth2OpenIdControllerTest extends SpringJerseyTest {
-
-    @Autowired
-    private FullConfiguration config;
-
-    private String redirectUri = "https://korap.ids-mannheim.de/confidential/redirect";
-
-    private String username = "dory";
-
-    private Response sendAuthorizationRequest(Form form) throws KustvaktException {
-        return target().path(API_VERSION).path("oauth2").path("openid").path("authorize").request().header(Attributes.AUTHORIZATION, HttpAuthorizationHandler.createBasicAuthorizationHeaderValue(username, "password")).header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32").header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED).post(Entity.form(form));
-    }
-
-    private Response sendTokenRequest(Form form) throws KustvaktException {
-        return target().path(API_VERSION).path("oauth2").path("openid").path("token").request().header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32").header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED).post(Entity.form(form));
-    }
-
-    @Test
-    public void testRequestAuthorizationCode() throws ProcessingException, KustvaktException {
-        Form form = new Form();
-        form.param("response_type", "code");
-        form.param("client_id", "fCBbQkAyYzI4NzUxMg");
-        testRequestAuthorizationCodeWithoutOpenID(form, redirectUri);
-        form.param("scope", "openid");
-        testRequestAuthorizationCodeMissingRedirectUri(form);
-        testRequestAuthorizationCodeInvalidRedirectUri(form);
-        form.param("redirect_uri", redirectUri);
-        form.param("state", "thisIsMyState");
-        Response response = sendAuthorizationRequest(form);
-        URI location = response.getLocation();
-        assertEquals(redirectUri, location.getScheme() + "://" + location.getHost() + location.getPath());
-        MultiValueMap<String, String> params = UriComponentsBuilder.fromUri(location).build().getQueryParams();
-        assertNotNull(params.getFirst("code"));
-        assertEquals(params.getFirst("state"), "thisIsMyState");
-    }
-
-    private void testRequestAuthorizationCodeWithoutOpenID(Form form, String redirectUri) throws KustvaktException {
-        Response response = sendAuthorizationRequest(form);
-        URI location = response.getLocation();
-        // System.out.println(location.toString());
-        assertEquals(redirectUri, location.getScheme() + "://" + location.getHost() + location.getPath());
-    }
-
-    private void testRequestAuthorizationCodeMissingRedirectUri(Form form) throws KustvaktException {
-        Response response = sendAuthorizationRequest(form);
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "redirect_uri is required");
-    }
-
-    private void testRequestAuthorizationCodeInvalidRedirectUri(Form form) throws KustvaktException {
-        form.param("redirect_uri", "blah");
-        Response response = sendAuthorizationRequest(form);
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Invalid redirect URI");
-        form.asMap().remove("redirect_uri");
-    }
-
-    @Test
-    public void testRequestAuthorizationCodeMissingClientID() throws KustvaktException {
-        Form form = new Form();
-        form.param("scope", "openid");
-        form.param("redirect_uri", redirectUri);
-        // error response is represented in JSON because redirect URI
-        // cannot be verified without client id
-        // Besides client_id is a mandatory parameter in a normal
-        // OAuth2 authorization request, thus it is checked first,
-        // before redirect_uri. see
-        // com.nimbusds.oauth2.sdk.AuthorizationRequest
-        Response response = sendAuthorizationRequest(form);
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Invalid request: Missing client_id parameter");
-    }
-
-    @Test
-    public void testRequestAuthorizationCodeMissingResponseType() throws KustvaktException {
-        Form form = new Form();
-        form.param("scope", "openid");
-        form.param("redirect_uri", redirectUri);
-        form.param("client_id", "blah");
-        // client_id has not been verified yet
-        // MUST NOT automatically redirect the user-agent to the
-        // invalid redirection URI.
-        Response response = sendAuthorizationRequest(form);
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Invalid request: Missing response_type parameter");
-    }
-
-    private void testRequestAuthorizationCodeUnsupportedResponseType(Form form, String type) throws KustvaktException {
-        Response response = sendAuthorizationRequest(form);
-        URI location = response.getLocation();
-        assertEquals(MediaType.APPLICATION_FORM_URLENCODED, response.getMediaType().toString());
-        MultiValueMap<String, String> params = UriComponentsBuilder.fromUri(location).build().getQueryParams();
-        assertEquals(params.getFirst("error"), "invalid_request");
-        assertEquals("unsupported+response_type%3A+" + type, params.getFirst("error_description"));
-    }
-
-    /**
-     * We don't support implicit grant. Implicit grant allows
-     * response_type:
-     * <ul>
-     * <li>id_token</li>
-     * <li>id_token token</li>
-     * </ul>
-     *
-     * @throws KustvaktException
-     */
-    @Test
-    public void testRequestAuthorizationCodeUnsupportedImplicitFlow() throws KustvaktException {
-        Form form = new Form();
-        form.param("scope", "openid");
-        form.param("redirect_uri", redirectUri);
-        form.param("response_type", "id_token");
-        form.param("client_id", "fCBbQkAyYzI4NzUxMg");
-        form.param("nonce", "nonce");
-        testRequestAuthorizationCodeUnsupportedResponseType(form, "id_token");
-        form.asMap().remove("response_type");
-        form.param("response_type", "id_token token");
-        testRequestAuthorizationCodeUnsupportedResponseType(form, "id_token");
-    }
-
-    /**
-     * Hybrid flow is not supported. Hybrid flow allows
-     * response_type:
-     * <ul>
-     * <li>code id_token</li>
-     * <li>code token</li>
-     * <li>code id_token token</li>
-     * </ul>
-     *
-     * @throws KustvaktExceptiony); assertTrue(signedJWT.verify(verifier));
-     */
-    @Test
-    public void testRequestAuthorizationCodeUnsupportedHybridFlow() throws KustvaktException {
-        Form form = new Form();
-        form.param("scope", "openid");
-        form.param("redirect_uri", redirectUri);
-        form.param("response_type", "code id_token");
-        form.param("client_id", "fCBbQkAyYzI4NzUxMg");
-        form.param("nonce", "nonce");
-        testRequestAuthorizationCodeUnsupportedResponseType(form, "id_token");
-        form.asMap().remove("response_type");
-        form.param("response_type", "code token");
-        testRequestAuthorizationCodeUnsupportedResponseType(form, "token");
-    }
-
-    @Test
-    public void testRequestAccessTokenWithAuthorizationCode() throws KustvaktException, ParseException, InvalidKeySpecException, NoSuchAlgorithmException, JOSEException {
-        String client_id = "fCBbQkAyYzI4NzUxMg";
-        String nonce = "thisIsMyNonce";
-        Form form = new Form();
-        form.param("response_type", "code");
-        form.param("client_id", client_id);
-        form.param("redirect_uri", redirectUri);
-        form.param("scope", "openid");
-        form.param("state", "thisIsMyState");
-        form.param("nonce", nonce);
-        Response response = sendAuthorizationRequest(form);
-        URI location = response.getLocation();
-        MultiValueMap<String, String> params = UriComponentsBuilder.fromUri(location).build().getQueryParams();
-        assertEquals(params.getFirst("state"), "thisIsMyState");
-        String code = params.getFirst("code");
-        Form tokenForm = new Form();
-        testRequestAccessTokenMissingGrant(tokenForm);
-        tokenForm.param("grant_type", "authorization_code");
-        tokenForm.param("code", code);
-        testRequestAccessTokenMissingClientId(tokenForm);
-        tokenForm.param("client_id", client_id);
-        testRequestAccessTokenMissingClientSecret(tokenForm);
-        tokenForm.param("client_secret", "secret");
-        tokenForm.param("redirect_uri", redirectUri);
-        Response tokenResponse = sendTokenRequest(tokenForm);
-        String entity = tokenResponse.readEntity(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());
-        String id_token = node.at("/id_token").asText();
-        assertNotNull(id_token);
-        verifyingIdToken(id_token, username, client_id, nonce);
-    }
-
-    private void testRequestAccessTokenMissingGrant(Form tokenForm) throws KustvaktException {
-        Response response = sendTokenRequest(tokenForm);
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Invalid request: Missing grant_type parameter");
-    }
-
-    private void testRequestAccessTokenMissingClientId(Form tokenForm) throws KustvaktException {
-        Response response = sendTokenRequest(tokenForm);
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals("Invalid request: Missing required client_id " + "parameter", node.at("/error_description").asText());
-    }
-
-    private void testRequestAccessTokenMissingClientSecret(Form tokenForm) throws KustvaktException {
-        Response response = sendTokenRequest(tokenForm);
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Missing parameter: client_secret");
-    }
-
-    private void verifyingIdToken(String id_token, String username, String client_id, String nonce) throws ParseException, InvalidKeySpecException, NoSuchAlgorithmException, JOSEException {
-        JWKSet keySet = config.getPublicKeySet();
-        RSAKey publicKey = (RSAKey) keySet.getKeyByKeyId(config.getRsaKeyId());
-        SignedJWT signedJWT = SignedJWT.parse(id_token);
-        JWSVerifier verifier = new RSASSAVerifier(publicKey);
-        assertTrue(signedJWT.verify(verifier));
-        JWTClaimsSet claimsSet = signedJWT.getJWTClaimsSet();
-        assertEquals(client_id, claimsSet.getAudience().get(0));
-        assertEquals(username, claimsSet.getSubject());
-        assertEquals(config.getIssuerURI().toString(), claimsSet.getIssuer());
-        assertTrue(new Date().before(claimsSet.getExpirationTime()));
-        assertNotNull(claimsSet.getClaim(Attributes.AUTHENTICATION_TIME));
-        assertEquals(nonce, claimsSet.getClaim("nonce"));
-    }
-
-    // no openid
-    @Test
-    public void testRequestAccessTokenWithPassword() throws KustvaktException, ParseException, InvalidKeySpecException, NoSuchAlgorithmException, JOSEException {
-        // public client
-        String client_id = "8bIDtZnH6NvRkW2Fq";
-        Form tokenForm = new Form();
-        testRequestAccessTokenMissingGrant(tokenForm);
-        tokenForm.param("grant_type", GrantType.PASSWORD.toString());
-        testRequestAccessTokenMissingUsername(tokenForm);
-        tokenForm.param("username", username);
-        testRequestAccessTokenMissingPassword(tokenForm);
-        tokenForm.param("password", "pass");
-        tokenForm.param("client_id", client_id);
-        Response tokenResponse = sendTokenRequest(tokenForm);
-        String entity = tokenResponse.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.UNAUTHORIZED_CLIENT, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Password grant is not allowed for third party clients");
-    }
-
-    private void testRequestAccessTokenMissingUsername(Form tokenForm) throws KustvaktException {
-        Response response = sendTokenRequest(tokenForm);
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Invalid request: Missing or empty username parameter");
-    }
-
-    private void testRequestAccessTokenMissingPassword(Form tokenForm) throws KustvaktException {
-        Response response = sendTokenRequest(tokenForm);
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
-        assertEquals(node.at("/error_description").asText(), "Invalid request: Missing or empty password parameter");
-    }
-
-    @Test
-    public void testPublicKeyAPI() throws KustvaktException {
-        Response response = target().path(API_VERSION).path("oauth2").path("openid").path("jwks").request().get();
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(1, node.at("/keys").size());
-        node = node.at("/keys/0");
-        assertEquals(node.at("/kty").asText(), "RSA");
-        assertEquals(config.getRsaKeyId(), node.at("/kid").asText());
-        assertNotNull(node.at("/e").asText());
-        assertNotNull(node.at("/n").asText());
-    }
-
-    @Test
-    public void testOpenIDConfiguration() throws KustvaktException {
-        Response response = target().path(API_VERSION).path("oauth2").path("openid").path("config").request().get();
-        String entity = response.readEntity(String.class);
-        JsonNode node = JsonUtils.readTree(entity);
-        assertNotNull(node.at("/issuer"));
-        assertNotNull(node.at("/authorization_endpoint"));
-        assertNotNull(node.at("/token_endpoint"));
-        assertNotNull(node.at("/response_types_supported"));
-        assertNotNull(node.at("/subject_types_supported"));
-        assertNotNull(node.at("/id_token_signing_alg_values_supported"));
-    }
-}
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2PluginTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2PluginTest.java
index 18ffdc9..62b96f7 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2PluginTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2PluginTest.java
@@ -16,11 +16,11 @@
 import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
 import org.junit.jupiter.api.Test;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2RClientTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2RClientTest.java
index 0810483..30bb832 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2RClientTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/OAuth2RClientTest.java
@@ -5,9 +5,10 @@
 
 import java.io.IOException;
 import java.net.URI;
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.util.MultiValueMap;
@@ -71,7 +72,6 @@
         MultiValueMap<String, String> params = UriComponentsBuilder.fromUri(redirectUri).build().getQueryParams();
         String code = params.getFirst("code");
         assertNotNull(code);
-        assertEquals(params.getFirst("scope"), "search");
         return code;
     }
 }
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 307af6c..f922624 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
@@ -7,18 +7,7 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.Form;
-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.error.OAuthError;
 import org.apache.oltu.oauth2.common.message.types.GrantType;
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.client.ClientProperties;
@@ -29,6 +18,7 @@
 
 import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.net.HttpHeaders;
+import com.nimbusds.oauth2.sdk.OAuth2Error;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
@@ -38,7 +28,6 @@
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.exceptions.StatusCodes;
 import de.ids_mannheim.korap.oauth2.constant.OAuth2ClientType;
-import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
 import de.ids_mannheim.korap.oauth2.dao.AccessTokenDao;
 import de.ids_mannheim.korap.oauth2.dao.OAuth2ClientDao;
 import de.ids_mannheim.korap.oauth2.dao.RefreshTokenDao;
@@ -48,6 +37,16 @@
 import de.ids_mannheim.korap.utils.JsonUtils;
 import de.ids_mannheim.korap.utils.TimeUtils;
 import de.ids_mannheim.korap.web.input.OAuth2ClientJson;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.client.Invocation.Builder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MultivaluedMap;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import static org.junit.jupiter.api.Assertions.*;
 
@@ -135,8 +134,9 @@
             request = request.queryParam("state", state);
         }
         
-        return request.request().header(Attributes.AUTHORIZATION, authHeader)
-                .get();
+        Builder builder = request.request().header(Attributes.AUTHORIZATION, authHeader);
+        
+        return builder.get();
     }
 
     protected String requestAuthorizationCode (String clientId,
@@ -249,7 +249,9 @@
         Form form = new Form();
         form.param("grant_type", "password");
         form.param("client_id", clientId);
-        form.param("client_secret", clientSecret);
+        if (clientSecret !=null && !clientSecret.isEmpty()) {
+            form.param("client_secret", clientSecret);
+        }
         form.param("username", username);
         form.param("password", password);
 
@@ -277,7 +279,7 @@
 
         String entity = response.readEntity(String.class);
         JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuth2Error.INVALID_GRANT, node.at("/error").asText());
+        assertEquals(OAuth2Error.INVALID_GRANT.getCode(), node.at("/error").asText());
         assertEquals("Refresh token has been revoked",
                 node.at("/error_description").asText());
     }
@@ -465,7 +467,7 @@
     protected void testInvalidRedirectUri (String entity, String contentType,
             boolean includeState, int status) throws KustvaktException {
         JsonNode node = JsonUtils.readTree(entity);
-        assertEquals(OAuthError.CodeResponse.INVALID_REQUEST,
+        assertEquals(OAuth2Error.INVALID_REQUEST.getCode(),
                 node.at("/error").asText());
         assertEquals("Invalid redirect URI",
                 node.at("/error_description").asText());
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/QueryReferenceControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/QueryReferenceControllerTest.java
index f440cc3..89e2cb5 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/QueryReferenceControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/QueryReferenceControllerTest.java
@@ -6,11 +6,10 @@
 import org.junit.jupiter.api.Test;
 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.core.Response.Status;
-import javax.ws.rs.client.Entity;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.client.Entity;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/QueryReferenceSearchTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/QueryReferenceSearchTest.java
index 4000d3c..e709d1b 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/QueryReferenceSearchTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/QueryReferenceSearchTest.java
@@ -4,8 +4,7 @@
 
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response;
 
 import de.ids_mannheim.korap.exceptions.KustvaktException;
 import de.ids_mannheim.korap.utils.JsonUtils;
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 bacf602..b1d8add 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
@@ -6,9 +6,10 @@
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.Iterator;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/ResourceInfoControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/ResourceInfoControllerTest.java
index 4f0ce21..8f30d17 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/ResourceInfoControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/ResourceInfoControllerTest.java
@@ -5,8 +5,8 @@
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java
index 0beb2ab..f683f01 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchControllerTest.java
@@ -6,17 +6,16 @@
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.net.HttpHeaders;
-
-import javax.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchNetworkEndpointTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchNetworkEndpointTest.java
index 3c2d277..1938b51 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchNetworkEndpointTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchNetworkEndpointTest.java
@@ -8,7 +8,8 @@
 import java.io.IOException;
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.commons.io.IOUtils;
 import org.junit.jupiter.api.AfterEach;
@@ -19,8 +20,7 @@
 import org.mockserver.model.Header;
 import org.springframework.beans.factory.annotation.Autowired;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response;
 
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.config.SpringJerseyTest;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchPipeTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchPipeTest.java
index 7f11f9a..9591933 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchPipeTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchPipeTest.java
@@ -15,7 +15,8 @@
 import java.net.URL;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.commons.io.IOUtils;
 import org.junit.jupiter.api.AfterEach;
@@ -25,8 +26,7 @@
 import org.mockserver.integration.ClientAndServer;
 import org.mockserver.model.Header;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response;
 
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchPublicMetadataTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchPublicMetadataTest.java
index d49756e..1d1db61 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchPublicMetadataTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchPublicMetadataTest.java
@@ -3,15 +3,14 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.net.HttpHeaders;
-
-import javax.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response;
 
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchTokenSnippetTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchTokenSnippetTest.java
index f261d01..c0e9fa7 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchTokenSnippetTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/SearchTokenSnippetTest.java
@@ -4,12 +4,11 @@
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response;
 
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/StatisticsControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/StatisticsControllerTest.java
index 753b7da..8bcb604 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/StatisticsControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/StatisticsControllerTest.java
@@ -4,15 +4,15 @@
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.IOException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response;
 
 import de.ids_mannheim.korap.config.SpringJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/TokenExpiryTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/TokenExpiryTest.java
index 3055eef..7cc5e6f 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/TokenExpiryTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/TokenExpiryTest.java
@@ -3,10 +3,11 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.io.IOException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.http.HttpStatus;
 import org.apache.http.entity.ContentType;
@@ -66,10 +67,20 @@
         Form form = new Form();
         form.param("response_type", "code");
         form.param("client_id", "fCBbQkAyYzI4NzUxMg");
-        form.param("redirect_uri", "https://korap.ids-mannheim.de/confidential/redirect");
-        form.param("scope", "openid");
+        form.param("redirect_uri",
+                "https://korap.ids-mannheim.de/confidential/redirect");
+        form.param("scope", "search");
         form.param("max_age", "1");
-        Response response = target().path(API_VERSION).path("oauth2").path("openid").path("authorize").request().header(Attributes.AUTHORIZATION, "Bearer " + token).header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32").header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED).post(Entity.form(form));
+
+        Response response =
+                target().path(API_VERSION).path("oauth2").path("authorize")
+                        .request()
+                        .header(Attributes.AUTHORIZATION, "Bearer " + token)
+                        .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+                        .header(HttpHeaders.CONTENT_TYPE,
+                                ContentType.APPLICATION_FORM_URLENCODED)
+                        .post(Entity.form(form));
+
         assertEquals(HttpStatus.SC_UNAUTHORIZED, response.getStatus());
         String entity = response.readEntity(String.class);
         JsonNode node = JsonUtils.readTree(entity);
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 c135828..4ecbe46 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
@@ -3,9 +3,10 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.net.URI;
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.util.MultiValueMap;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerAdminTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerAdminTest.java
index 8cac40a..99cf31a 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerAdminTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerAdminTest.java
@@ -2,17 +2,16 @@
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
 
 import org.junit.jupiter.api.Test;
 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.core.Response.Status;
-import javax.ws.rs.client.Entity;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.client.Entity;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
index 8742128..52e3bb3 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserGroupControllerTest.java
@@ -3,18 +3,18 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 import java.util.Set;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
+
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 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.core.Response.Status;
-import javax.ws.rs.client.Entity;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.client.Entity;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserSettingControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserSettingControllerTest.java
index 7aac962..7f7078e 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/UserSettingControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/UserSettingControllerTest.java
@@ -5,14 +5,14 @@
 
 import java.util.HashMap;
 import java.util.Map;
-import javax.ws.rs.client.Entity;
+
+import jakarta.ws.rs.client.Entity;
 
 import org.junit.jupiter.api.Test;
 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 jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.config.Attributes;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VCReferenceTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VCReferenceTest.java
index 9cce1a0..382535d 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VCReferenceTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VCReferenceTest.java
@@ -12,11 +12,11 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.net.HttpHeaders;
 
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.cache.VirtualCorpusCache;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusAccessTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusAccessTest.java
index f86b01a..beb1308 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusAccessTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusAccessTest.java
@@ -2,9 +2,9 @@
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.http.HttpStatus;
 import org.junit.jupiter.api.Test;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusClientTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusClientTest.java
index 8df65a1..225a331 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusClientTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusClientTest.java
@@ -2,8 +2,8 @@
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerAdminTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerAdminTest.java
index 807d649..e93582f 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerAdminTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusControllerAdminTest.java
@@ -2,12 +2,12 @@
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
 import org.junit.jupiter.api.Test;
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 a30a810..fe45cec 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
@@ -7,10 +7,11 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-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 jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
 import org.junit.jupiter.api.Test;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusFieldTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusFieldTest.java
index 495e0fc..1e06bd3 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusFieldTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusFieldTest.java
@@ -9,10 +9,9 @@
 import org.springframework.beans.factory.annotation.Autowired;
 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.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
 import de.ids_mannheim.korap.cache.VirtualCorpusCache;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusInfoTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusInfoTest.java
index 2fe7a47..168edbb 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusInfoTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusInfoTest.java
@@ -3,12 +3,12 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusListTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusListTest.java
index 7e794d2..df1ac17 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusListTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusListTest.java
@@ -2,9 +2,9 @@
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusSharingTest.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusSharingTest.java
index 120a5fa..288c9e3 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusSharingTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusSharingTest.java
@@ -3,11 +3,11 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.http.HttpStatus;
 import org.junit.jupiter.api.Test;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusTestBase.java b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusTestBase.java
index 821a338..7293e04 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusTestBase.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/controller/VirtualCorpusTestBase.java
@@ -9,11 +9,11 @@
 import java.util.Map.Entry;
 import java.util.Set;
 
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.apache.http.entity.ContentType;
 import org.glassfish.jersey.server.ContainerRequest;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/lite/InfoControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/lite/InfoControllerTest.java
index 2b3cd0c..f8b2b1d 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/lite/InfoControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/lite/InfoControllerTest.java
@@ -6,8 +6,8 @@
 import org.springframework.beans.factory.annotation.Autowired;
 import com.fasterxml.jackson.databind.JsonNode;
 
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.config.LiteJerseyTest;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteMultipleCorpusQueryTest.java b/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteMultipleCorpusQueryTest.java
index 7746eae..c037f20 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteMultipleCorpusQueryTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteMultipleCorpusQueryTest.java
@@ -6,9 +6,9 @@
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
 
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ProcessingException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.config.LiteJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchControllerTest.java
index 0ec56c6..60b6550 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchControllerTest.java
@@ -9,11 +9,12 @@
 import java.io.IOException;
 import java.net.URI;
 import java.util.Iterator;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.Form;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.eclipse.jetty.http.HttpStatus;
 import org.junit.jupiter.api.Disabled;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchPipeTest.java b/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchPipeTest.java
index bc45ad0..f747934 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchPipeTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchPipeTest.java
@@ -25,8 +25,8 @@
 import org.mockserver.model.Header;
 import com.fasterxml.jackson.databind.JsonNode;
 
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.config.LiteJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchTokenSnippetTest.java b/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchTokenSnippetTest.java
index 57d1a89..75b9920 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchTokenSnippetTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteSearchTokenSnippetTest.java
@@ -7,8 +7,8 @@
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
 
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.config.LiteJerseyTest;
 import de.ids_mannheim.korap.exceptions.KustvaktException;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteStatisticControllerTest.java b/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteStatisticControllerTest.java
index c48e58e..65e57c3 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteStatisticControllerTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/lite/LiteStatisticControllerTest.java
@@ -4,11 +4,12 @@
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.io.IOException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+
+import jakarta.ws.rs.client.Entity;
+import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import org.junit.jupiter.api.Test;
 import com.fasterxml.jackson.databind.JsonNode;
diff --git a/full/src/test/java/de/ids_mannheim/korap/web/lite/SearchNetworkEndpointTest.java b/full/src/test/java/de/ids_mannheim/korap/web/lite/SearchNetworkEndpointTest.java
index 5590183..fa72cee 100644
--- a/full/src/test/java/de/ids_mannheim/korap/web/lite/SearchNetworkEndpointTest.java
+++ b/full/src/test/java/de/ids_mannheim/korap/web/lite/SearchNetworkEndpointTest.java
@@ -18,9 +18,8 @@
 import org.mockserver.model.Header;
 import org.springframework.beans.factory.annotation.Autowired;
 import com.fasterxml.jackson.databind.JsonNode;
-
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
 
 import de.ids_mannheim.korap.config.KustvaktConfiguration;
 import de.ids_mannheim.korap.config.LiteJerseyTest;
diff --git a/full/src/test/resources/kustvakt-test.conf b/full/src/test/resources/kustvakt-test.conf
index 893d04b..913e2ed 100644
--- a/full/src/test/resources/kustvakt-test.conf
+++ b/full/src/test/resources/kustvakt-test.conf
@@ -91,29 +91,6 @@
 
 oauth2.initial.super.client=true
 
-# OpenId
-# multiple values are separated by space
-openid.grant.types = authorization_code
-openid.response.types = code
-openid.response.modes = query
-openid.client.auth.methods = client_secret_basic client_secret_post
-openid.token.signing.algorithms = RS256
-openid.subject.types = public
-openid.display.types = page
-openid.supported.scopes = openid email auth_time
-openid.support.claim.param = false
-openid.claim.types = normal
-openid.supported.claims = iss sub aud exp iat
-openid.ui.locales = en
-#openid.privacy.policy = 
-#openid.term.of.service =
-openid.service.doc = https://github.com/KorAP/Kustvakt/wiki
-
-# JWK
-# must be set for openid
-rsa.private = kustvakt_rsa.key
-rsa.public = kustvakt_rsa_public.key
-rsa.key.id = 74caa3a9-217c-49e6-94e9-2368fdd02c35
 
 # see SecureRandom Number Generation Algorithms
 # optional
diff --git a/full/src/test/resources/kustvakt_rsa.key b/full/src/test/resources/kustvakt_rsa.key
deleted file mode 100644
index 1db25e9..0000000
--- a/full/src/test/resources/kustvakt_rsa.key
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "p": "y7t3f2VRo5TN3IsCjshSWWwe4H1-Xd7iBbtPS_fmBeaVDbLr-05LsGRJxXzKheMJ5DwBzhvWAlCig5uSJG3Gk4i0LgLY5YO33shb9qqqEnF54ZkJbiqxSs5l_dggzZgYB5z0riVl2VA3yfNm1qJIE2eipBouUjBEXMOEtJlOrFc",
-  "kty": "RSA",
-  "q": "v4HHIpOddl_78fVQgvZCsINygpLuniJ3sVShLhX7LnCU0Eb4TMK_Fyz9_JPb3YFvEoPpQw3kfnAhkOBTATTpXzg_dNtR6eQfvDJfHl9R6FuSoVTJoNAO_rqEpKzQOGXl4ohBxVjhXcbEo6GEVp4pZAeXMM8D02IWfvGbJd0Yw0k",
-  "d": "OJFnms4n3ajWKvK26aOh_r8JGgQwbQNIXpx8UqFnc_EB4nzxcLns8-FGKa9Vg3VMAs8cFC4iM9evx1084yqsCeSKgwiV5ZVQkwnp35Gd5BslZxuH8kCdR1mL5y0V0RMwgW-W1ry_YtdhBSIze8XCJXB7udNk7bviiJylEm8OouyxAq-5uUy_qMWYk-mtDSpmPW9SfFf91c6P7-ataDFcd_zxFotd1UwXDVDaPfUnxpOA6Jh1WsvIFhX4IzETuUG8n5C-j6FrK_YlU7U-zFzzF8qWTthQVj5l7A0zOGmq6OC9mv_xtnSc6z9I-HklWFXa8eDsc2JasYqJY8CmTDSy8Q",
-  "e": "AQAB",
-  "kid": "74caa3a9-217c-49e6-94e9-2368fdd02c35",
-  "qi": "Iv8_jAuCTdU7xZ1GXK0Zaql3Azu1-qXiZseod9urLFFZK6OvxrhH0BexG_P1tRikUfEUQiyqNVCU544Z0Y0AdDbgb5aEYNa3Bkb5WAHHXsLDtzXSsxgvR4Pzg3PhT3HTrLkgTlWy9g0u7bwfhb-KTRszcw4SyFXz9o62xJLPJZo",
-  "dp": "pA8_qHhHqMoAiNPsaFyKa_Y0WyTTqPX93w26SnvDYQcRCqoFfCbNrqrj-UOHtw9gfMmRzo795HlYlVCm--zmlxHjvpWOYiyS2bVQ0S8Xq6hztKbPQEbi5FGXMjZkHAuZdi__nWkCPmBpvJfkPX0LO40eHLX0jTzPIEBWUjSOdRs",
-  "dq": "GtnydumlqWRZ6hoQWNx4i1FS6_X4GRoSGD4af2C7oE5Ov0lEJVck_fXkAtcke9FbJohyW2GGSSglvK-HU-L8WcqEMzlRKe8_d97EMXkB_gdg7tf5kV-6yoKSeJh2dYHsErAyMJ5-suxcw-iwqohwm0LpMwHDso7NQq1TqKJwh2k",
-  "n": "mGgmGYIN06ibCh98nsXp0a77xRQNnB9rKpRGKm41tVi0zLQWqmEdDh2CmrMiOOxTJFSlAuAVkwK-KVQZ5Men5dJvRyTwZPtBWSJZk32Znj3VshFloSQlQU-g3oh3c2htP03EDtBLmecZMI-OUV1hRCvrRUrS-qF24CJ-rheFsCmpSievEJDQqTTfXcbAG2DdRQJHWb3y1iyNojB_mV1H2Gztg9DGEZarloqXoTFeDcxs7SpZJqAWCWTJQk8n6Ye79SfGMNrzaaqN9aHx__6FU-GFdZexlWE0CemQcfx_hTEkCTa2EsGgI_GETQIjeCZRB29x91E3AlWVvEgA591pzw"
-}
\ No newline at end of file
diff --git a/full/src/test/resources/kustvakt_rsa_public.key b/full/src/test/resources/kustvakt_rsa_public.key
deleted file mode 100644
index 28c2fad..0000000
--- a/full/src/test/resources/kustvakt_rsa_public.key
+++ /dev/null
@@ -1,6 +0,0 @@
-{"keys": [{
-  "kty": "RSA",
-  "e": "AQAB",
-  "kid": "74caa3a9-217c-49e6-94e9-2368fdd02c35",
-  "n": "mGgmGYIN06ibCh98nsXp0a77xRQNnB9rKpRGKm41tVi0zLQWqmEdDh2CmrMiOOxTJFSlAuAVkwK-KVQZ5Men5dJvRyTwZPtBWSJZk32Znj3VshFloSQlQU-g3oh3c2htP03EDtBLmecZMI-OUV1hRCvrRUrS-qF24CJ-rheFsCmpSievEJDQqTTfXcbAG2DdRQJHWb3y1iyNojB_mV1H2Gztg9DGEZarloqXoTFeDcxs7SpZJqAWCWTJQk8n6Ye79SfGMNrzaaqN9aHx__6FU-GFdZexlWE0CemQcfx_hTEkCTa2EsGgI_GETQIjeCZRB29x91E3AlWVvEgA591pzw"
-}]}
\ No newline at end of file
diff --git a/full/src/test/resources/test-config-icc.xml b/full/src/test/resources/test-config-icc.xml
index fed99a6..466b052 100644
--- a/full/src/test/resources/test-config-icc.xml
+++ b/full/src/test/resources/test-config-icc.xml
@@ -44,14 +44,15 @@
 			</array>
 		</property>
 	</bean>
-
+	
+	<!-- 
 	<bean id='cacheManager' class='org.springframework.cache.ehcache.EhCacheCacheManager'
 		p:cacheManager-ref='ehcache' />
 
 	<bean id='ehcache'
 		class='org.springframework.cache.ehcache.EhCacheManagerFactoryBean'
 		p:configLocation='classpath:ehcache.xml' p:shared='true' />
-
+ 	-->
 	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
 		lazy-init="true">
 		<!-- <property name="driverClassName" value="${jdbc.driverClassName}" /> -->
@@ -228,12 +229,6 @@
 	<bean id="oauth2ResponseHandler" class="de.ids_mannheim.korap.web.OAuth2ResponseHandler">
 	</bean>
 
-	<bean id="mdGenerator" class="org.apache.oltu.oauth2.as.issuer.MD5Generator">
-	</bean>
-	<bean id="oauthIssuer" class="org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl">
-		<constructor-arg index="0" ref="mdGenerator" />
-	</bean>
-
 	<bean name="kustvakt_encryption" class="de.ids_mannheim.korap.encryption.KustvaktEncryption">
 		<constructor-arg ref="kustvakt_config" />
 	</bean>
@@ -296,7 +291,7 @@
 		<constructor-arg index="0" value="${mail.username}" />
 		<constructor-arg index="1" value="${mail.password}" />
 	</bean>
-	<bean id="smtpSession" class="javax.mail.Session" factory-method="getInstance">
+	<bean id="smtpSession" class="jakarta.mail.Session" factory-method="getInstance">
 		<constructor-arg index="0">
 			<props>
 				<prop key="mail.smtp.submitter">${mail.username}</prop>
diff --git a/full/src/test/resources/test-config.xml b/full/src/test/resources/test-config.xml
index a49795e..6abc135 100644
--- a/full/src/test/resources/test-config.xml
+++ b/full/src/test/resources/test-config.xml
@@ -45,12 +45,12 @@
 		</property>
 	</bean>
 
-	<bean id='cacheManager' class='org.springframework.cache.ehcache.EhCacheCacheManager'
+	<!-- <bean id='cacheManager' class='org.springframework.cache.ehcache.EhCacheCacheManager'
 		p:cacheManager-ref='ehcache' />
 
 	<bean id='ehcache'
 		class='org.springframework.cache.ehcache.EhCacheManagerFactoryBean'
-		p:configLocation='classpath:ehcache.xml' p:shared='true' />
+		p:configLocation='classpath:ehcache.xml' p:shared='true' /> -->
 
 	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
 		lazy-init="true">
@@ -224,25 +224,11 @@
 	<bean id="oauth2ResponseHandler" class="de.ids_mannheim.korap.web.OAuth2ResponseHandler">
 	</bean>
 
-	<bean id="mdGenerator" class="org.apache.oltu.oauth2.as.issuer.MD5Generator">
-	</bean>
-	<bean id="oauthIssuer" class="org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl">
-		<constructor-arg index="0" ref="mdGenerator" />
-	</bean>
-
 	<bean name="kustvakt_encryption" class="de.ids_mannheim.korap.encryption.KustvaktEncryption">
 		<constructor-arg ref="kustvakt_config" />
 	</bean>
 
 	<!-- authentication providers to use -->
-	<!-- <bean id="openid_auth"
-		class="de.ids_mannheim.korap.authentication.OpenIDconnectAuthentication">
-		<constructor-arg type="de.ids_mannheim.korap.config.KustvaktConfiguration"
-			ref="kustvakt_config" />
-		<constructor-arg
-			type="de.ids_mannheim.korap.interfaces.db.PersistenceClient" ref="kustvakt_db" />
-	</bean> -->
-
 	<bean id="basic_auth"
 		class="de.ids_mannheim.korap.authentication.BasicAuthentication" />
 
@@ -263,7 +249,6 @@
 		value-type="de.ids_mannheim.korap.interfaces.AuthenticationIface">
 		<ref bean="basic_auth" />
 		<ref bean="session_auth" />
-		<!-- <ref bean="openid_auth" /> -->
 		<ref bean="oauth2_auth" />
 	</util:list>
 
@@ -310,7 +295,7 @@
 		<constructor-arg index="0" value="${mail.username}" />
 		<constructor-arg index="1" value="${mail.password}" />
 	</bean>
-	<bean id="smtpSession" class="javax.mail.Session" factory-method="getInstance">
+	<bean id="smtpSession" class="jakarta.mail.Session" factory-method="getInstance">
 		<constructor-arg index="0">
 			<props>
 				<prop key="mail.smtp.submitter">${mail.username}</prop>
diff --git a/full/src/test/resources/test-hibernate.properties b/full/src/test/resources/test-hibernate.properties
index 23979b2..e394a88 100644
--- a/full/src/test/resources/test-hibernate.properties
+++ b/full/src/test/resources/test-hibernate.properties
@@ -1,4 +1,4 @@
-hibernate.dialect=org.hibernate.dialect.SQLiteDialect
+hibernate.dialect=org.hibernate.community.dialect.SQLiteDialect
 hibernate.hbm2ddl.auto=none
 hibernate.show_sql=false
 hibernate.cache.use_query_cache=false