Deprecate API token (JWT) web-service.
Change-Id: I818bf5cbe81b078c1beaf24d8f81929c946c561c
diff --git a/full/Changes b/full/Changes
index 94a3963..f00ffc2 100644
--- a/full/Changes
+++ b/full/Changes
@@ -19,6 +19,10 @@
2023-02-15
- Moved user-group retrieval API to UserGroupAdminController
and changed the service path URL of UserGroupAdminController.
+2023-02-20
+- Deprecate API token (JWT) web-service
+
+
# version 0.69.1
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 2137ab8..9d66617 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
@@ -29,6 +29,7 @@
*
* Created by hanl on 5/23/14.
*/
+@Deprecated
public class APIAuthentication implements AuthenticationIface {
private static Logger jlog = LogManager.getLogger(APIAuthentication.class);
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 e061644..597ae0e 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
@@ -1,8 +1,6 @@
package de.ids_mannheim.korap.web.controller;
-import java.util.Date;
import java.util.HashMap;
-import java.util.Iterator; // 07.02.17/FB
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -17,18 +15,15 @@
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
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.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.glassfish.jersey.server.ContainerRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
-import org.glassfish.jersey.server.ContainerRequest;
-import de.ids_mannheim.korap.web.utils.ResourceFilters;
-
import de.ids_mannheim.korap.authentication.AuthenticationManager;
import de.ids_mannheim.korap.authentication.http.AuthorizationData;
import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
@@ -43,13 +38,13 @@
import de.ids_mannheim.korap.user.User;
import de.ids_mannheim.korap.utils.JsonUtils;
import de.ids_mannheim.korap.utils.ServiceInfo;
-import de.ids_mannheim.korap.utils.TimeUtils;
import de.ids_mannheim.korap.web.KustvaktResponseHandler;
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.filter.DemoUserFilter;
import de.ids_mannheim.korap.web.filter.PiwikFilter;
+import de.ids_mannheim.korap.web.utils.ResourceFilters;
// import com.sun.xml.internal.messaging.saaj.util.Base64;
@@ -76,7 +71,7 @@
@Autowired
private HttpAuthorizationHandler authorizationHandler;
- private static Boolean DEBUG_LOG = false;
+ private static Boolean DEBUG_LOG = true;
//todo: bootstrap function to transmit certain default configuration settings and examples (example user queries,
// default usersettings, etc.)
@@ -172,6 +167,7 @@
// }
+ @Deprecated
@GET
@Path("apiToken")
//@ResourceFilters({HeaderFilter.class})
@@ -183,117 +179,144 @@
@QueryParam("scope") String scopes,
// @Context WebServiceContext wsContext, // FB
@Context SecurityContext secCtx) {
-
- List<String> auth =
- headers.getRequestHeader(ContainerRequest.AUTHORIZATION);
- if (auth == null || auth.isEmpty()) {
- throw kustvaktResponseHandler
- .throwit(new KustvaktException(StatusCodes.MISSING_PARAMETER,
- "Authorization header is missing.",
- "Authorization header"));
- }
- AuthorizationData authorizationData;
- try {
- authorizationData = authorizationHandler.
- parseAuthorizationHeaderValue(auth.get(0));
- if (authorizationData.getAuthenticationScheme().equals(AuthenticationScheme.BASIC)){
- authorizationData = authorizationHandler.parseBasicToken(authorizationData);
- }
- else {
- // EM: throw exception that auth scheme is not supported?
- }
-
- }
- catch (KustvaktException e) {
- throw kustvaktResponseHandler.throwit(e);
- }
-
if (DEBUG_LOG == true) {
- System.out.printf("Debug: AuthService.requestAPIToken...:\n");
- System.out.printf("Debug: auth.size=%d\n", auth.size());
- System.out.printf("auth.get(0)='%s'\n", auth.get(0));
- /* hide password etc. - FB
- if( auth.size() > 0 )
- {
- Iterator it = auth.iterator();
- while( it.hasNext() )
- System.out.printf(" header '%s'\n", it.next());
- }
- if( values.length > 0 )
- {
- for(int i=0; i< values.length; i++)
- {
- System.out.printf(" values[%d]='%s'\n", i, values[i]);
- }
- }
- */
- MultivaluedMap<String, String> headerMap =
- headers.getRequestHeaders();
- if (headerMap != null && headerMap.size() > 0) {
- Iterator<String> it = headerMap.keySet().iterator();
- while (it.hasNext()) {
- String key = (String) it.next();
- List<String> vals = headerMap.get(key);
-// System.out.printf("Debug: requestAPIToken: '%s' = '%s'\n",
-// key, vals);
- }
-
- }
-// System.out.printf("Debug: requestAPIToken: isSecure = %s.\n",
-// secCtx.isSecure() ? "yes" : "no");
- } // DEBUG_LOG
-
- if (authorizationData.getUsername() == null ||
- authorizationData.getUsername().isEmpty() ||
- authorizationData.getPassword()== null ||
- authorizationData.getPassword().isEmpty())
- // is actual an invalid request
- throw kustvaktResponseHandler.throwit(StatusCodes.REQUEST_INVALID);
-
- Map<String, Object> attr = new HashMap<>();
- if (scopes != null && !scopes.isEmpty())
- attr.put(Attributes.SCOPE, scopes);
- attr.put(Attributes.HOST, host);
- attr.put(Attributes.USER_AGENT, agent);
-
- TokenContext context;
- try {
- // User user = controller.authenticate(0, values[0], values[1], attr); Implementation by Hanl
- User user = controller.authenticate(AuthenticationMethod.LDAP,
- authorizationData.getUsername(), authorizationData.getPassword(), attr); // Implementation with IdM/LDAP
- // Userdata data = this.controller.getUserData(user, UserDetails.class); // Implem. by Hanl
- // todo: is this necessary?
- // attr.putAll(data.fields());
+ String warning = "Access to API token (JWT) web service";
- // EM: add authentication time
- Date authenticationTime = TimeUtils.getNow().toDate();
- attr.put(Attributes.AUTHENTICATION_TIME, authenticationTime);
- // -- EM
-
- controller.setAccessAndLocation(user, headers);
- if (DEBUG_LOG == true) System.out.printf(
- "Debug: /apiToken/: location=%s, access='%s'.\n",
- user.locationtoString(), user.accesstoString());
- attr.put(Attributes.LOCATION, user.getLocation());
- attr.put(Attributes.CORPUS_ACCESS, user.getCorpusAccess());
- context = controller.createTokenContext(user, attr,
- TokenType.API);
-// context = controller.createTokenContext(user, attr,
-// Attributes.API_AUTHENTICATION);
+ List<String> auth =
+ headers.getRequestHeader(ContainerRequest.AUTHORIZATION);
+ if (auth != null && !auth.isEmpty()) {
+ try {
+ AuthorizationData authorizationData = authorizationHandler
+ .parseAuthorizationHeaderValue(auth.get(0));
+ if (authorizationData.getAuthenticationScheme()
+ .equals(AuthenticationScheme.BASIC)) {
+ authorizationData = authorizationHandler
+ .parseBasicToken(authorizationData);
+ jlog.warn(warning + " with username:"+authorizationData.getUsername());
+ }
+ }
+ catch (KustvaktException e) {}
+ }
+ else {
+ jlog.warn(warning);
+ }
}
- catch (KustvaktException e) {
- throw kustvaktResponseHandler.throwit(e);
- }
-
- try {
- return Response.ok(context.toJson()).build();
- }
- catch (KustvaktException e) {
- throw kustvaktResponseHandler.throwit(e);
- }
+ throw kustvaktResponseHandler.throwit(new KustvaktException(
+ StatusCodes.DEPRECATED,
+ "API token is no longer supported. Please use OAuth2 procedure instead."));
}
+// List<String> auth =
+// headers.getRequestHeader(ContainerRequest.AUTHORIZATION);
+// if (auth == null || auth.isEmpty()) {
+// throw kustvaktResponseHandler
+// .throwit(new KustvaktException(StatusCodes.MISSING_PARAMETER,
+// "Authorization header is missing.",
+// "Authorization header"));
+// }
+//
+// AuthorizationData authorizationData;
+// try {
+// authorizationData = authorizationHandler.
+// parseAuthorizationHeaderValue(auth.get(0));
+// if (authorizationData.getAuthenticationScheme().equals(AuthenticationScheme.BASIC)){
+// authorizationData = authorizationHandler.parseBasicToken(authorizationData);
+// }
+// else {
+// // EM: throw exception that auth scheme is not supported?
+// }
+//
+// }
+// catch (KustvaktException e) {
+// throw kustvaktResponseHandler.throwit(e);
+// }
+//
+// if (DEBUG_LOG == true) {
+// System.out.printf("Debug: AuthService.requestAPIToken...:\n");
+// System.out.printf("Debug: auth.size=%d\n", auth.size());
+// System.out.printf("auth.get(0)='%s'\n", auth.get(0));
+// /* hide password etc. - FB
+// if( auth.size() > 0 )
+// {
+// Iterator it = auth.iterator();
+// while( it.hasNext() )
+// System.out.printf(" header '%s'\n", it.next());
+// }
+// if( values.length > 0 )
+// {
+// for(int i=0; i< values.length; i++)
+// {
+// System.out.printf(" values[%d]='%s'\n", i, values[i]);
+// }
+// }
+// */
+// MultivaluedMap<String, String> headerMap =
+// headers.getRequestHeaders();
+// if (headerMap != null && headerMap.size() > 0) {
+// Iterator<String> it = headerMap.keySet().iterator();
+// while (it.hasNext()) {
+// String key = (String) it.next();
+// List<String> vals = headerMap.get(key);
+//// System.out.printf("Debug: requestAPIToken: '%s' = '%s'\n",
+//// key, vals);
+// }
+//
+// }
+//// System.out.printf("Debug: requestAPIToken: isSecure = %s.\n",
+//// secCtx.isSecure() ? "yes" : "no");
+// } // DEBUG_LOG
+//
+// if (authorizationData.getUsername() == null ||
+// authorizationData.getUsername().isEmpty() ||
+// authorizationData.getPassword()== null ||
+// authorizationData.getPassword().isEmpty())
+// // is actual an invalid request
+// throw kustvaktResponseHandler.throwit(StatusCodes.REQUEST_INVALID);
+//
+// Map<String, Object> attr = new HashMap<>();
+// if (scopes != null && !scopes.isEmpty())
+// attr.put(Attributes.SCOPE, scopes);
+// attr.put(Attributes.HOST, host);
+// attr.put(Attributes.USER_AGENT, agent);
+//
+// TokenContext context;
+// try {
+// // User user = controller.authenticate(0, values[0], values[1], attr); Implementation by Hanl
+// User user = controller.authenticate(AuthenticationMethod.LDAP,
+// authorizationData.getUsername(), authorizationData.getPassword(), attr); // Implementation with IdM/LDAP
+// // Userdata data = this.controller.getUserData(user, UserDetails.class); // Implem. by Hanl
+// // todo: is this necessary?
+// // attr.putAll(data.fields());
+//
+// // EM: add authentication time
+// Date authenticationTime = TimeUtils.getNow().toDate();
+// attr.put(Attributes.AUTHENTICATION_TIME, authenticationTime);
+// // -- EM
+//
+// controller.setAccessAndLocation(user, headers);
+// if (DEBUG_LOG == true) System.out.printf(
+// "Debug: /apiToken/: location=%s, access='%s'.\n",
+// user.locationtoString(), user.accesstoString());
+// attr.put(Attributes.LOCATION, user.getLocation());
+// attr.put(Attributes.CORPUS_ACCESS, user.getCorpusAccess());
+// context = controller.createTokenContext(user, attr,
+// TokenType.API);
+//// context = controller.createTokenContext(user, attr,
+//// Attributes.API_AUTHENTICATION);
+// }
+// catch (KustvaktException e) {
+// throw kustvaktResponseHandler.throwit(e);
+// }
+//
+// try {
+// return Response.ok(context.toJson()).build();
+// }
+// catch (KustvaktException e) {
+// throw kustvaktResponseHandler.throwit(e);
+// }
+// }
+
// todo:
@Deprecated
diff --git a/full/src/main/resources/log4j2.properties b/full/src/main/resources/log4j2.properties
index 661aab6..c366776 100644
--- a/full/src/main/resources/log4j2.properties
+++ b/full/src/main/resources/log4j2.properties
@@ -21,3 +21,10 @@
logger.file.appenderRefs = file
logger.file.appenderRef.file.ref = MAINLOG
logger.file.additivity=false
+
+loggers=file
+logger.console.name=de.ids_mannheim.korap.web.controller.AuthenticationController
+logger.console.level = warn
+logger.console.appenderRefs = file
+logger.console.appenderRef.file.ref = MAINLOG
+logger.console.additivity=false
\ 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 086169b..a36a27b 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,27 +6,54 @@
import java.util.HashMap;
import java.util.Map;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.net.HttpHeaders;
import com.nimbusds.jose.JOSEException;
+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.constant.TokenType;
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.user.KorAPUser;
import de.ids_mannheim.korap.user.User;
+import de.ids_mannheim.korap.utils.JsonUtils;
import de.ids_mannheim.korap.utils.TimeUtils;
+import de.ids_mannheim.korap.web.controller.OAuth2TestBase;
-public class APIAuthenticationTest extends SpringJerseyTest {
+public class APIAuthenticationTest extends OAuth2TestBase {
@Autowired
private FullConfiguration config;
@Test
+ public void testDeprecatedService () throws KustvaktException {
+
+ String userAuthHeader = HttpAuthorizationHandler
+ .createBasicAuthorizationHeaderValue("dory", "password");
+
+ Response response = target().path(API_VERSION).path("auth")
+ .path("apiToken").request()
+ .header(Attributes.AUTHORIZATION, userAuthHeader)
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32").get();
+
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
+
+ String entity = response.readEntity(String.class);
+ JsonNode node = JsonUtils.readTree(entity);
+
+ assertEquals(StatusCodes.DEPRECATED, node.at("/errors/0/0").asInt());
+ }
+
+ @Test
public void testCreateGetTokenContext () throws KustvaktException,
IOException, InterruptedException, JOSEException {
User user = new KorAPUser();
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 911e716..f44c1c8 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
@@ -81,7 +81,7 @@
assertEquals(19387, node.at("/sentences").asInt());
assertEquals(514, node.at("/paragraphs").asInt());
- assertEquals(StatusCodes.DEPRECATED_PARAMETER,
+ assertEquals(StatusCodes.DEPRECATED,
node.at("/warnings/0/0").asInt());
assertEquals("Parameter corpusQuery is deprecated in favor of cq.",
node.at("/warnings/0/1").asText());
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 29471a0..e2d36c6 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
@@ -105,7 +105,7 @@
assertEquals(node.get("documents").asInt(),11);
assertEquals(node.get("tokens").asInt(),665842);
- assertEquals(StatusCodes.DEPRECATED_PARAMETER,
+ assertEquals(StatusCodes.DEPRECATED,
node.at("/warnings/0/0").asInt());
assertEquals("Parameter corpusQuery is deprecated in favor of cq.",
node.at("/warnings/0/1").asText());
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 3b1d086..4518d1d 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
@@ -6,15 +6,16 @@
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 org.apache.http.HttpStatus;
import org.apache.http.entity.ContentType;
+import org.junit.Ignore;
import org.junit.Test;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.net.HttpHeaders;
-import javax.ws.rs.core.Response;
import de.ids_mannheim.korap.config.Attributes;
import de.ids_mannheim.korap.config.SpringJerseyTest;
@@ -31,7 +32,8 @@
*
*/
public class TokenExpiryTest extends SpringJerseyTest {
-
+
+ @Ignore
@Test
public void requestToken ()
throws KustvaktException, InterruptedException, IOException {
diff --git a/full/src/test/resources/log4j2-test.properties b/full/src/test/resources/log4j2-test.properties
index 2810e0c..872b150 100644
--- a/full/src/test/resources/log4j2-test.properties
+++ b/full/src/test/resources/log4j2-test.properties
@@ -35,9 +35,9 @@
logger.console.appenderRef.file.ref = STDOUT
logger.console.additivity=false
-#loggers=console
-#logger.console.name=de.ids_mannheim.korap
-#logger.console.level = info
-#logger.console.appenderRefs = stdout
-#logger.console.appenderRef.file.ref = STDOUT
-#logger.console.additivity=false
+loggers=console
+logger.console.name=de.ids_mannheim.korap.web.controller.AuthenticationController
+logger.console.level = warn
+logger.console.appenderRefs = stdout
+logger.console.appenderRef.file.ref = STDOUT
+logger.console.additivity=false