Fixed revoking latest access token when refreshing OAuth2 access token.
Change-Id: I8b2a0a4eb4ca3b7374e2347dececb9801f1ba0df
diff --git a/full/Changes b/full/Changes
index ed71a4d..18e2c34 100644
--- a/full/Changes
+++ b/full/Changes
@@ -13,6 +13,7 @@
users when deregistering/deleting a client (margaretha)
- Fixed update OAuth2 access token (margaretha)
- Implemented reset client secret (margaretha)
+ - Fixed revoking latest access token when refreshing OAuth2 access token (margaretha)
# version 0.60.5
diff --git a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java
index c53fbb6..bb9baa5 100644
--- a/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java
+++ b/full/src/main/java/de/ids_mannheim/korap/oauth2/oltu/service/OltuTokenService.java
@@ -136,6 +136,7 @@
}
if (!latestAccessToken.isRevoked()) {
+ latestAccessToken.setRevoked(true);
tokenDao.updateAccessToken(latestAccessToken);
}
@@ -324,7 +325,7 @@
return OAuthASResponse.tokenResponse(Status.OK.getStatusCode())
.setAccessToken(accessToken)
.setTokenType(TokenType.BEARER.toString())
- .setExpiresIn(String.valueOf(config.getTokenTTL()))
+ .setExpiresIn(String.valueOf(config.getAccessTokenExpiry()))
.setRefreshToken(refreshToken)
.setScope(String.join(" ", scopes)).buildJSONMessage();
}
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
index 45735ed..91e724a 100644
--- 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
@@ -174,7 +174,7 @@
authenticationTime = authenticateUser(username, password, scopeSet);
AccessToken accessToken =
- new BearerAccessToken(config.getTokenTTL(), scope);
+ new BearerAccessToken(config.getAccessTokenExpiry(), scope);
RefreshToken refreshToken = new RefreshToken();
@@ -228,7 +228,7 @@
.toArray(String[]::new);
Scope scope = new Scope(scopeArray);
AccessToken accessToken =
- new BearerAccessToken(config.getTokenTTL(), scope);
+ new BearerAccessToken(config.getAccessTokenExpiry(), scope);
RefreshToken refreshToken = new RefreshToken();
tokenDao.storeAccessToken(accessToken.getValue(),
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 61f8237..082f976 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
@@ -198,14 +198,20 @@
}
/**
- * Revoking an access token also revokes its refresh token, vice
- * versa.
+ * Revokes either an access token or a refresh token. Revoking a
+ * refresh token also revokes all access token associated with the
+ * refresh token.
*
* RFC 7009
* Client authentication for confidential client
*
* @param request
* @param form
+ * containing
+ * client_id,
+ * client_secret (required for confidential clients),
+ * token,
+ * token_type (optional)
* @return 200 if token invalidation is successful or the given
* token is invalid
*/
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 8282baa..98f3434 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
@@ -9,6 +9,7 @@
import javax.ws.rs.core.Response.Status;
import org.apache.http.entity.ContentType;
+import org.apache.oltu.oauth2.common.message.types.GrantType;
import org.junit.Test;
import com.fasterxml.jackson.databind.JsonNode;
@@ -26,10 +27,12 @@
public class OAuth2AccessTokenTest extends SpringJerseyTest {
- private String requestToken () throws KustvaktException {
+ private String clientId = "fCBbQkAyYzI4NzUxMg";
+
+ private JsonNode requestToken () throws KustvaktException {
MultivaluedMap<String, String> form = new MultivaluedMapImpl();
form.add("grant_type", "password");
- form.add("client_id", "fCBbQkAyYzI4NzUxMg");
+ form.add("client_id", clientId);
form.add("client_secret", "secret");
form.add("username", "dory");
form.add("password", "password");
@@ -41,7 +44,7 @@
String entity = response.getEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
- return node.at("/access_token").asText();
+ return node;
}
@Test
@@ -78,11 +81,10 @@
@Test
public void testTokenAccessScope () throws KustvaktException, IOException {
- String accessToken = requestToken();
+ String accessToken = requestToken().at("/access_token").asText();
testListVCScopeNotAuthorized(accessToken);
testListVCAccessBearerNotAuthorize(accessToken);
testSearchWithOAuth2Token(accessToken);
-
}
private void testListVCScopeNotAuthorized (String accessToken)
@@ -159,7 +161,7 @@
@Test
public void testRevokeAccessTokenConfidentialClient ()
throws KustvaktException {
- String accessToken = requestToken();
+ String accessToken = requestToken().at("/access_token").asText();
MultivaluedMap<String, String> form = new MultivaluedMapImpl();
form.add("token", accessToken);
form.add("client_id", "fCBbQkAyYzI4NzUxMg");
@@ -171,7 +173,7 @@
.entity(form).post(ClientResponse.class);
assertEquals(Status.OK.getStatusCode(), response.getStatus());
-
+
testSearchWithRevokedToken(accessToken);
}
@@ -186,10 +188,41 @@
String entity = response.getEntity(String.class);
assertEquals(ClientResponse.Status.UNAUTHORIZED.getStatusCode(),
response.getStatus());
-
- JsonNode node = JsonUtils.readTree(entity);
- assertEquals(StatusCodes.INVALID_ACCESS_TOKEN, node.at("/errors/0/0").asInt());
- assertEquals("Access token has been revoked", node.at("/errors/0/1").asText());
+ JsonNode node = JsonUtils.readTree(entity);
+ assertEquals(StatusCodes.INVALID_ACCESS_TOKEN,
+ node.at("/errors/0/0").asInt());
+ assertEquals("Access token has been revoked",
+ node.at("/errors/0/1").asText());
+
+ }
+
+ @Test
+ public void testRevocationAfterRequestRefreshToken ()
+ throws KustvaktException {
+ JsonNode node = requestToken();
+ String accessToken = node.at("/access_token").asText();
+ String refreshToken = node.at("/refresh_token").asText();
+
+ MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+ form.add("grant_type", GrantType.REFRESH_TOKEN.toString());
+ form.add("client_id", clientId);
+ form.add("client_secret", "secret");
+ form.add("refresh_token", refreshToken);
+
+ ClientResponse response = resource().path("oauth2").path("token")
+ .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
+ .header(HttpHeaders.CONTENT_TYPE,
+ ContentType.APPLICATION_FORM_URLENCODED)
+ .entity(form).post(ClientResponse.class);
+
+ String entity = response.getEntity(String.class);
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+
+ node = JsonUtils.readTree(entity);
+ assertNotNull(node.at("/access_token").asText());
+ assertEquals(refreshToken,node.at("/refresh_token").asText());
+
+ testSearchWithRevokedToken(accessToken);
}
}
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 3985fd6..5da5fe9 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
@@ -21,6 +21,13 @@
import de.ids_mannheim.korap.exceptions.StatusCodes;
import de.ids_mannheim.korap.utils.JsonUtils;
+/**
+ * Before running this test:
+ * set oauth2.access.token.expiry = 3S
+ *
+ * @author margaretha
+ *
+ */
public class TokenExpiryTest extends SpringJerseyTest {
@Test
@@ -45,7 +52,7 @@
Thread.sleep(1000);
testRequestAuthorizationCodeAuthenticationTooOld(token);
-
+
Thread.sleep(1500);
testSearchWithExpiredToken(token);
}