Allow admin access using admin token for the clean token API
Change-Id: Id3c6db09b59cd7384f508a5b1d19c0b3084892b9
diff --git a/full/Changes b/full/Changes
index 0ceb78d..e4c7a6c 100644
--- a/full/Changes
+++ b/full/Changes
@@ -11,6 +11,8 @@
- Allowed OAuth2 clients to use localhost as redirect URIs.
2023-02-03
- Fixed content-type in error responses by changing it to application/json
+2023-02-06
+- Allow admin access using admin token for the clean token API
# version 0.69.1
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 9027071..0ca1368 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
@@ -2,28 +2,21 @@
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.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.oauth2.service.OAuth2AdminService;
-import de.ids_mannheim.korap.oauth2.service.OAuth2ScopeService;
-import de.ids_mannheim.korap.security.context.TokenContext;
import de.ids_mannheim.korap.web.OAuth2ResponseHandler;
import de.ids_mannheim.korap.web.filter.APIVersionFilter;
import de.ids_mannheim.korap.web.filter.AdminFilter;
+import de.ids_mannheim.korap.web.utils.ResourceFilters;
@Controller
@Path("{version}/oauth2/admin")
@@ -34,26 +27,18 @@
@Autowired
private OAuth2AdminService adminService;
@Autowired
- private OAuth2ScopeService scopeService;
- @Autowired
private OAuth2ResponseHandler responseHandler;
- @GET
+ /**
+ * Removes expired or invalid access and refresh tokens from
+ * database and cache
+ *
+ * @return Response status OK, if successful
+ */
+ @POST
@Path("token/clean")
- public Response cleanExpiredInvalidToken (
- @Context SecurityContext securityContext) {
-
- TokenContext context =
- (TokenContext) securityContext.getUserPrincipal();
-
- try {
- scopeService.verifyScope(context, OAuth2Scope.ADMIN);
- adminService.cleanTokens();
-
- }
- catch (KustvaktException e) {
- throw responseHandler.throwit(e);
- }
+ public Response cleanExpiredInvalidToken () {
+ adminService.cleanTokens();
return Response.ok().build();
}
@@ -68,7 +53,6 @@
* When degrading super clients, all existing tokens and
* authorization codes are invalidated.
*
- * @param securityContext
* @param clientId
* OAuth2 client id
* @param super
@@ -79,13 +63,9 @@
@Path("client/privilege")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response updateClientPrivilege (
- @Context SecurityContext securityContext,
@FormParam("client_id") String clientId,
@FormParam("super") String isSuper) {
- TokenContext context =
- (TokenContext) securityContext.getUserPrincipal();
try {
- scopeService.verifyScope(context, OAuth2Scope.ADMIN);
adminService.updatePrivilege(clientId, Boolean.valueOf(isSuper));
return Response.ok("SUCCESS").build();
}
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 db29dec..42431c8 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,8 +3,11 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.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 org.apache.http.entity.ContentType;
import org.junit.Test;
@@ -12,10 +15,6 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.net.HttpHeaders;
-import javax.ws.rs.ProcessingException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.Response.Status;
import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
import de.ids_mannheim.korap.config.Attributes;
@@ -59,25 +58,37 @@
return response;
}
- private void updateClientPriviledge (String clientId, boolean isSuper)
+ private Response updateClientPrivilegeWithAdminToken (String clientId)
throws ProcessingException,
KustvaktException {
+
Form form = new Form();
form.param("client_id", clientId);
- form.param("super", Boolean.toString(isSuper));
+ form.param("super", Boolean.toString(false));
+ form.param("token", "secret"); //adminToken
+
+ Response response = target().path(API_VERSION).path("oauth2")
+ .path("admin").path("client").path("privilege")
+ .request()
+ .header(HttpHeaders.CONTENT_TYPE,
+ ContentType.APPLICATION_FORM_URLENCODED)
+ .post(Entity.form(form));
+ return response;
+ }
+
+
+ private void testUpdateClientPriviledgeUnauthorized (Form form)
+ throws ProcessingException, KustvaktException {
Response response = updateClientPrivilege(username, form);
JsonNode node = JsonUtils.readTree(response.readEntity(String.class));
assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
assertEquals(StatusCodes.AUTHORIZATION_FAILED,
node.at("/errors/0/0").asInt());
-
- response = updateClientPrivilege("admin", form);
- assertEquals(Status.OK.getStatusCode(), response.getStatus());
}
@Test
- public void testCleanExpiredTokens () {
+ public void testCleanExpiredTokensUsingAdminToken () {
int refreshTokensBefore =
refreshDao.retrieveInvalidRefreshTokens().size();
assertTrue(refreshTokensBefore > 0);
@@ -85,11 +96,13 @@
int accessTokensBefore = accessDao.retrieveInvalidAccessTokens().size();
assertTrue(accessTokensBefore > 0);
+ Form form = new Form();
+ form.param("token", "secret");
+
target().path(API_VERSION).path("oauth2").path("admin").path("token")
.path("clean")
.request()
- .header(Attributes.AUTHORIZATION, adminAuthHeader)
- .get();
+ .post(Entity.form(form));
assertEquals(0, refreshDao.retrieveInvalidRefreshTokens().size());
assertEquals(0, accessDao.retrieveInvalidAccessTokens().size());
@@ -116,7 +129,7 @@
.path("clean")
.request()
.header(Attributes.AUTHORIZATION, adminAuthHeader)
- .get();
+ .post(null);
assertEquals(0, accessDao.retrieveInvalidAccessTokens().size());
}
@@ -137,10 +150,22 @@
clientAuthHeader);
String accessToken = node.at("/access_token").asText();
- updateClientPriviledge(clientId, true);
+ //update client priviledge to super client
+ Form form = new Form();
+ form.param("client_id", clientId);
+ form.param("super", Boolean.toString(true));
+
+ testUpdateClientPriviledgeUnauthorized(form);
+
+ response = updateClientPrivilege("admin", form);
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
testAccessTokenAfterUpgradingClient(clientId, accessToken);
- updateClientPriviledge(clientId, false);
+ // degrade a super client to a common client
+
+ updateClientPrivilegeWithAdminToken(clientId);
+
testAccessTokenAfterDegradingSuperClient(clientId, accessToken);
deregisterClient(username, clientId);