Updated OAuth2 token list with token type and user clientId parameters.
Change-Id: Id7171fa09913cb2ab8bcefd7bce3003388ce93d4
diff --git a/full/Changes b/full/Changes
index 8d3d4a2..fd9f56e 100644
--- a/full/Changes
+++ b/full/Changes
@@ -5,6 +5,9 @@
2021-02-26
- Added query access roles and fixed vc access roles (margaretha)
- Added delete query webservice and tests (margaretha)
+2021-03-25
+ - Updated OAuth2 token list with token type and user clientId
+ parameters (margaretha)
# version 0.63
26/10/2020
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 b82819d..f3cc60a 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
@@ -183,4 +183,32 @@
return q.getResultList();
}
+ public List<AccessToken> retrieveAccessTokenByUser (String username, String clientId)
+ throws KustvaktException {
+ ParameterChecker.checkStringValue(username, "username");
+
+ CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+ CriteriaQuery<AccessToken> query =
+ builder.createQuery(AccessToken.class);
+
+ Root<AccessToken> root = query.from(AccessToken.class);
+ root.fetch(AccessToken_.client);
+ Predicate condition = builder.and(
+ builder.equal(root.get(AccessToken_.userId), username),
+ builder.equal(root.get(AccessToken_.isRevoked), false),
+ builder.greaterThan(
+ root.<ZonedDateTime> get(AccessToken_.expiryDate),
+ ZonedDateTime
+ .now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE))));
+ if (clientId != null && !clientId.isEmpty()) {
+ OAuth2Client client = clientDao.retrieveClientById(clientId);
+ condition = builder.and(condition,
+ builder.equal(root.get(AccessToken_.client), client));
+ }
+
+ query.select(root);
+ query.where(condition);
+ TypedQuery<AccessToken> q = entityManager.createQuery(query);
+ return q.getResultList();
+ }
}
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 0bcc54d..585d8b6 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
@@ -143,7 +143,8 @@
return q.getResultList();
}
- public List<RefreshToken> retrieveRefreshTokenByUser (String username)
+ public List<RefreshToken> retrieveRefreshTokenByUser (String username,
+ String clientId)
throws KustvaktException {
ParameterChecker.checkStringValue(username, "username");
@@ -160,6 +161,12 @@
root.<ZonedDateTime> get(RefreshToken_.expiryDate),
ZonedDateTime
.now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE))));
+ if (clientId != null && !clientId.isEmpty()) {
+ OAuth2Client client = clientDao.retrieveClientById(clientId);
+ condition = builder.and(condition,
+ builder.equal(root.get(RefreshToken_.client), client));
+ }
+
query.select(root);
query.where(condition);
TypedQuery<RefreshToken> q = entityManager.createQuery(query);
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 abab7ce..d066063 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
@@ -104,7 +104,7 @@
* credentials.
*
* TODO: should create a new refresh token when the old refresh
- * token is used
+ * token is used (DONE)
*
* @param refreshTokenStr
* @param scopes
@@ -322,9 +322,9 @@
* Base64.
*
* <br /><br />
- * Additionally, a refresh token is issued. It can be used to
- * request a new access token without requiring user
- * reauthentication.
+ * 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
@@ -512,17 +512,17 @@
}
}
- public List<OAuth2TokenDto> listUserRefreshToken (String username, String clientId,
- String clientSecret) throws KustvaktException {
+ public List<OAuth2TokenDto> listUserRefreshToken (String username, String superClientId,
+ String superClientSecret, String clientId) throws KustvaktException {
- OAuth2Client client = clientService.authenticateClient(clientId, clientSecret);
+ 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);
+ List<RefreshToken> tokens = refreshDao.retrieveRefreshTokenByUser(username, clientId);
List<OAuth2TokenDto> dtoList = new ArrayList<>(tokens.size());
for (RefreshToken t : tokens){
OAuth2Client tokenClient = t.getClient();
@@ -552,6 +552,48 @@
}
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));
+ dto.setExpiryDate(t.getExpiryDate().format(f));
+ 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.setScopes(scopes);
+ dtoList.add(dto);
+ }
+ return dtoList;
+ }
public String clearAccessTokenCache (String adminToken, String accessToken,
ServletContext context) throws KustvaktException {
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 17fb0a4..e043837 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
@@ -30,6 +30,8 @@
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;
@@ -130,13 +132,20 @@
* Grants a client an access token, namely a string used in
* authenticated requests representing user authorization for
* the client to access user resources. An additional refresh
- * token strictly associated to the access token is also granted.
+ * token strictly associated to the access token is also granted
+ * for confidential clients. Both public and confidential clients
+ * may issue multiple access tokens.
*
* <br /><br />
*
- * Clients may request refresh access token using this endpoint.
- * This request will grants a new access token. The refresh token
- * is not changed and can be used until it expires.
+ * Confidential clients may request refresh access token using
+ * this endpoint. This request will grant a new access token.
+ *
+ * Usually the given refresh token is not changed and can be used
+ * until it expires. However, currently there is a limitation of
+ * one access token per one refresh token. Thus, the given refresh
+ * token will be revoked, and a new access token and a new refresh
+ * token will be returned.
*
* <br /><br />
*
@@ -260,7 +269,6 @@
}
}
-
@POST
@Path("revoke/super")
@ResourceFilters({ AuthenticationFilter.class, BlockingFilter.class })
@@ -290,7 +298,7 @@
throw responseHandler.throwit(e);
}
}
-
+
/**
* Revokes all tokens of a client for the authenticated user from
* a super client. This service is not part of the OAUTH2
@@ -343,22 +351,35 @@
@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
public List<OAuth2TokenDto> listUserRefreshToken (
@Context SecurityContext context,
- @FormParam("client_id") String clientId,
- @FormParam("client_secret") String clientSecret) {
+ @FormParam("super_client_id") String superClientId,
+ @FormParam("super_client_secret") String superClientSecret,
+ @FormParam("client_id") String clientId, // optional
+ @FormParam("token_type") String tokenType) {
TokenContext tokenContext = (TokenContext) context.getUserPrincipal();
String username = tokenContext.getUsername();
try {
- return tokenService.listUserRefreshToken(username, clientId,
- clientSecret);
+ if (tokenType.equals("access_token")) {
+ return tokenService.listUserAccessToken(username, superClientId,
+ superClientSecret, clientId);
+ }
+ else if (tokenType.equals("refresh_token")) {
+ return tokenService.listUserRefreshToken(username,
+ superClientId, superClientSecret, clientId);
+ }
+ else {
+ throw new KustvaktException(StatusCodes.MISSING_PARAMETER,
+ "Missing token_type parameter value",
+ OAuth2Error.INVALID_REQUEST);
+ }
}
catch (KustvaktException e) {
throw responseHandler.throwit(e);
}
}
-
+
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Path("token/clear")
@@ -367,8 +388,8 @@
@FormParam("access_token") String accessToken,
@Context ServletContext context) {
try {
- String response = tokenService.clearAccessTokenCache(adminToken, accessToken,
- context);
+ String response = tokenService.clearAccessTokenCache(adminToken,
+ accessToken, context);
return Response.ok(response).build();
}
catch (KustvaktException e) {
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 be97272..3b1a187 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
@@ -41,7 +41,7 @@
public String userAuthHeader;
public static String ACCESS_TOKEN_TYPE = "access_token";
public static String REFRESH_TOKEN_TYPE = "refresh_token";
-
+
public OAuth2ControllerTest () throws KustvaktException {
userAuthHeader = HttpAuthorizationHandler
.createBasicAuthorizationHeaderValue("dory", "password");
@@ -181,8 +181,7 @@
node.at("/token_type").asText());
assertEquals(31536000, node.at("/expires_in").asInt());
- testRevokeToken(accessToken, publicClientId,null,
- ACCESS_TOKEN_TYPE);
+ testRevokeToken(accessToken, publicClientId, null, ACCESS_TOKEN_TYPE);
assertTrue(node.at("/refresh_token").isMissingNode());
}
@@ -217,17 +216,14 @@
assertNotNull(node.at("/expires_in").asText());
testRequestTokenWithUsedAuthorization(code);
-
+
String refreshToken = node.at("/refresh_token").asText();
-
+
testRequestRefreshTokenInvalidScope(confidentialClientId, refreshToken);
testRequestRefreshTokenInvalidClient(refreshToken);
testRequestRefreshTokenInvalidRefreshToken(confidentialClientId);
-
- testRevokeToken(refreshToken, confidentialClientId,clientSecret,
- REFRESH_TOKEN_TYPE);
- testRequestTokenWithRevokedRefreshToken(confidentialClientId,
- clientSecret, refreshToken);
+
+ testRequestRefreshToken(confidentialClientId, clientSecret, refreshToken);
}
private void testRequestTokenWithUsedAuthorization (String code)
@@ -337,7 +333,7 @@
assertEquals(TokenType.BEARER.toString(),
node.at("/token_type").asText());
assertNotNull(node.at("/expires_in").asText());
-
+
RefreshToken refreshToken = refreshTokenDao
.retrieveRefreshToken(node.at("/refresh_token").asText());
Set<AccessScope> scopes = refreshToken.getScopes();
@@ -348,8 +344,8 @@
@Test
public void testRequestTokenPasswordGrantConfidentialNonSuper ()
throws KustvaktException {
- ClientResponse response =
- requestTokenWithDoryPassword(confidentialClientId, clientSecret);
+ ClientResponse response = requestTokenWithDoryPassword(
+ confidentialClientId, clientSecret);
String entity = response.getEntity(String.class);
assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
@@ -363,7 +359,8 @@
@Test
public void testRequestTokenPasswordGrantPublic ()
throws KustvaktException {
- ClientResponse response = requestTokenWithDoryPassword(publicClientId, "");
+ ClientResponse response =
+ requestTokenWithDoryPassword(publicClientId, "");
String entity = response.getEntity(String.class);
assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
@@ -384,12 +381,13 @@
form.add("username", "dory");
form.add("password", "password");
- ClientResponse response = resource().path(API_VERSION).path("oauth2").path("token")
- .header(HttpHeaders.AUTHORIZATION,
- "Basic ZkNCYlFrQXlZekk0TnpVeE1nOnNlY3JldA==")
- .header(HttpHeaders.CONTENT_TYPE,
- ContentType.APPLICATION_FORM_URLENCODED)
- .entity(form).post(ClientResponse.class);
+ ClientResponse response =
+ resource().path(API_VERSION).path("oauth2").path("token")
+ .header(HttpHeaders.AUTHORIZATION,
+ "Basic ZkNCYlFrQXlZekk0TnpVeE1nOnNlY3JldA==")
+ .header(HttpHeaders.CONTENT_TYPE,
+ ContentType.APPLICATION_FORM_URLENCODED)
+ .entity(form).post(ClientResponse.class);
String entity = response.getEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
assertNotNull(node.at("/access_token").asText());
@@ -414,12 +412,13 @@
form.add("username", "dory");
form.add("password", "password");
- ClientResponse response = resource().path(API_VERSION).path("oauth2").path("token")
- .header(HttpHeaders.AUTHORIZATION,
- "Basic ZkNCYlFrQXlZekk0TnpVeE1nOnNlY3JldA==")
- .header(HttpHeaders.CONTENT_TYPE,
- ContentType.APPLICATION_FORM_URLENCODED)
- .entity(form).post(ClientResponse.class);
+ ClientResponse response =
+ resource().path(API_VERSION).path("oauth2").path("token")
+ .header(HttpHeaders.AUTHORIZATION,
+ "Basic ZkNCYlFrQXlZekk0TnpVeE1nOnNlY3JldA==")
+ .header(HttpHeaders.CONTENT_TYPE,
+ ContentType.APPLICATION_FORM_URLENCODED)
+ .entity(form).post(ClientResponse.class);
String entity = response.getEntity(String.class);
JsonNode node = JsonUtils.readTree(entity);
assertNotNull(node.at("/access_token").asText());
@@ -447,7 +446,8 @@
@Test
public void testRequestTokenPasswordGrantMissingClientId ()
throws KustvaktException {
- ClientResponse response = requestTokenWithDoryPassword(null, clientSecret);
+ ClientResponse response =
+ requestTokenWithDoryPassword(null, clientSecret);
String entity = response.getEntity(String.class);
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
@@ -544,11 +544,12 @@
MultivaluedMap<String, String> form = new MultivaluedMapImpl();
form.add("grant_type", "blahblah");
- ClientResponse response = resource().path(API_VERSION).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);
+ ClientResponse response =
+ resource().path(API_VERSION).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.BAD_REQUEST.getStatusCode(), response.getStatus());
@@ -569,46 +570,54 @@
form.add("refresh_token", refreshToken);
form.add("scope", "search serialize_query");
- ClientResponse response = resource().path(API_VERSION).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);
+ ClientResponse response =
+ resource().path(API_VERSION).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);
JsonNode node = JsonUtils.readTree(entity);
assertEquals(OAuth2Error.INVALID_SCOPE, node.at("/error").asText());
}
- private void testRequestRefreshTokenPublicClient (String clientId,
+ private void testRequestRefreshToken (String clientId, String clientSecret,
String refreshToken) throws KustvaktException {
MultivaluedMap<String, String> form = new MultivaluedMapImpl();
form.add("grant_type", GrantType.REFRESH_TOKEN.toString());
form.add("client_id", clientId);
+ form.add("client_secret", clientSecret);
form.add("refresh_token", refreshToken);
- ClientResponse response = resource().path(API_VERSION).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);
+ ClientResponse response =
+ resource().path(API_VERSION).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());
JsonNode node = JsonUtils.readTree(entity);
assertNotNull(node.at("/access_token").asText());
- assertNotNull(node.at("/refresh_token").asText());
+
+ String newRefreshToken = node.at("/refresh_token").asText();
+ assertNotNull(newRefreshToken);
assertEquals(TokenType.BEARER.toString(),
node.at("/token_type").asText());
assertNotNull(node.at("/expires_in").asText());
- assertTrue(!node.at("/refresh_token").asText().equals(refreshToken));
+ assertTrue(!newRefreshToken.equals(refreshToken));
- RefreshToken rt = refreshTokenDao.retrieveRefreshToken(refreshToken);
- assertEquals(true, rt.isRevoked());
- Set<AccessScope> scopes = rt.getScopes();
- assertEquals(3, scopes.size());
+ testRequestTokenWithRevokedRefreshToken(clientId, clientSecret,
+ refreshToken);
+
+ testRevokeToken(newRefreshToken, clientId, clientSecret,
+ REFRESH_TOKEN_TYPE);
+ testRequestTokenWithRevokedRefreshToken(clientId, clientSecret,
+ newRefreshToken);
}
private void testRequestRefreshTokenInvalidClient (String refreshToken)
@@ -618,11 +627,12 @@
form.add("client_id", "iBr3LsTCxOj7D2o0A5m");
form.add("refresh_token", refreshToken);
- ClientResponse response = resource().path(API_VERSION).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);
+ ClientResponse response =
+ resource().path(API_VERSION).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);
JsonNode node = JsonUtils.readTree(entity);
@@ -637,11 +647,12 @@
form.add("client_secret", clientSecret);
form.add("refresh_token", "Lia8s8w8tJeZSBlaQDrYV8ion3l");
- ClientResponse response = resource().path(API_VERSION).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);
+ ClientResponse response =
+ resource().path(API_VERSION).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);
JsonNode node = JsonUtils.readTree(entity);
@@ -654,21 +665,51 @@
form.add("token_type", tokenType);
form.add("token", token);
form.add("client_id", clientId);
- if (clientSecret!=null){
+ if (clientSecret != null) {
form.add("client_secret", clientSecret);
}
-
- ClientResponse response = resource().path(API_VERSION).path("oauth2").path("revoke")
+
+ ClientResponse response =
+ resource().path(API_VERSION).path("oauth2").path("revoke")
+ .header(HttpHeaders.CONTENT_TYPE,
+ ContentType.APPLICATION_FORM_URLENCODED)
+ .entity(form).post(ClientResponse.class);
+
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ assertEquals("SUCCESS", response.getEntity(String.class));
+ }
+
+ private JsonNode requestTokenList (String userAuthHeader, String tokenType,
+ String clientId) throws KustvaktException {
+ MultivaluedMap<String, String> form = new MultivaluedMapImpl();
+ form.add("super_client_id", superClientId);
+ form.add("super_client_secret", clientSecret);
+ form.add("token_type", tokenType);
+
+ if (clientId != null && !clientId.isEmpty()){
+ form.add("client_id", clientId);
+ }
+
+ ClientResponse response = resource().path(API_VERSION).path("oauth2")
+ .path("token").path("list")
+ .header(Attributes.AUTHORIZATION, userAuthHeader)
.header(HttpHeaders.CONTENT_TYPE,
ContentType.APPLICATION_FORM_URLENCODED)
.entity(form).post(ClientResponse.class);
assertEquals(Status.OK.getStatusCode(), response.getStatus());
- assertEquals("SUCCESS", response.getEntity(String.class));
+
+ String entity = response.getEntity(String.class);
+ return JsonUtils.readTree(entity);
+ }
+
+ private JsonNode requestTokenList (String userAuthHeader, String tokenType)
+ throws KustvaktException {
+ return requestTokenList(userAuthHeader, tokenType, null);
}
@Test
- public void testListRefreshToken () throws KustvaktException {
+ public void testListRefreshTokenConfidentialClient () throws KustvaktException {
String username = "gurgle";
String password = "pwd";
userAuthHeader = HttpAuthorizationHandler
@@ -682,8 +723,8 @@
String refreshToken1 = node.at("/refresh_token").asText();
// client 1
- String code = requestAuthorizationCode(confidentialClientId, clientSecret,
- null, userAuthHeader);
+ String code = requestAuthorizationCode(confidentialClientId,
+ clientSecret, null, userAuthHeader);
response = requestTokenWithAuthorizationCodeAndForm(
confidentialClientId, clientSecret, code);
assertEquals(Status.OK.getStatusCode(), response.getStatus());
@@ -696,11 +737,11 @@
assertEquals(Status.OK.getStatusCode(), response.getStatus());
// list
- node = requestRefreshTokenList(userAuthHeader);
+ node = requestTokenList(userAuthHeader, REFRESH_TOKEN_TYPE);
assertEquals(2, node.size());
assertEquals(confidentialClientId, node.at("/0/clientId").asText());
assertEquals(confidentialClientId2, node.at("/1/clientId").asText());
-
+
// client 1
code = requestAuthorizationCode(confidentialClientId, clientSecret,
null, userAuthHeader);
@@ -711,61 +752,95 @@
// another user
String darlaAuthHeader = HttpAuthorizationHandler
.createBasicAuthorizationHeaderValue("darla", "pwd");
+
+ // test listing clients
+ node = requestTokenList(darlaAuthHeader, REFRESH_TOKEN_TYPE);
+ assertEquals(0, node.size());
+
// client 1
code = requestAuthorizationCode(confidentialClientId, clientSecret,
null, darlaAuthHeader);
assertEquals(Status.OK.getStatusCode(), response.getStatus());
response = requestTokenWithAuthorizationCodeAndForm(
confidentialClientId, clientSecret, code);
-
+
node = JsonUtils.readTree(response.getEntity(String.class));
String refreshToken5 = node.at("/refresh_token").asText();
-
- // list
- node = requestRefreshTokenList(userAuthHeader);
+
+ // list all refresh tokens
+ node = requestTokenList(userAuthHeader, REFRESH_TOKEN_TYPE);
assertEquals(3, node.size());
+
+ // list refresh tokens from client 1
+ node = requestTokenList(userAuthHeader, REFRESH_TOKEN_TYPE, confidentialClientId);
+ assertEquals(2, node.size());
testRevokeToken(refreshToken1, superClientId, clientSecret,
REFRESH_TOKEN_TYPE);
- testRevokeToken(node.at("/0/token").asText(), confidentialClientId,
+ testRevokeToken(node.at("/0/token").asText(), confidentialClientId,
clientSecret, REFRESH_TOKEN_TYPE);
testRevokeToken(node.at("/1/token").asText(), confidentialClientId2,
clientSecret, REFRESH_TOKEN_TYPE);
-
- node = requestRefreshTokenList(userAuthHeader);
+
+ node = requestTokenList(userAuthHeader, REFRESH_TOKEN_TYPE);
assertEquals(1, node.size());
-
- testRevokeTokenViaSuperClient(node.at("/0/token").asText(), userAuthHeader);
- node = requestRefreshTokenList(userAuthHeader);
+
+ testRevokeTokenViaSuperClient(node.at("/0/token").asText(),
+ userAuthHeader);
+ node = requestTokenList(userAuthHeader, REFRESH_TOKEN_TYPE);
assertEquals(0, node.size());
-
+
// try revoking a token belonging to another user
// should not return any errors
testRevokeTokenViaSuperClient(refreshToken5, userAuthHeader);
- node = requestRefreshTokenList(darlaAuthHeader);
+ node = requestTokenList(darlaAuthHeader, REFRESH_TOKEN_TYPE);
assertEquals(1, node.size());
-
+
testRevokeTokenViaSuperClient(refreshToken5, darlaAuthHeader);
- node = requestRefreshTokenList(darlaAuthHeader);
+ node = requestTokenList(darlaAuthHeader, REFRESH_TOKEN_TYPE);
assertEquals(0, node.size());
}
-
- private JsonNode requestRefreshTokenList (String userAuthHeader)
- throws KustvaktException {
- MultivaluedMap<String, String> form = new MultivaluedMapImpl();
- form.add("client_id", superClientId);
- form.add("client_secret", clientSecret);
- ClientResponse response = resource().path(API_VERSION).path("oauth2")
- .path("token").path("list")
- .header(Attributes.AUTHORIZATION, userAuthHeader)
- .header(HttpHeaders.CONTENT_TYPE,
- ContentType.APPLICATION_FORM_URLENCODED)
- .entity(form).post(ClientResponse.class);
+ @Test
+ public void testListTokenPublicClient () throws KustvaktException {
+ String username = "nemo";
+ String password = "pwd";
+ userAuthHeader = HttpAuthorizationHandler
+ .createBasicAuthorizationHeaderValue(username, password);
+
+ // access token 1
+ String code = requestAuthorizationCode(publicClientId, clientSecret,
+ null, userAuthHeader);
+ ClientResponse response = requestTokenWithAuthorizationCodeAndForm(publicClientId, "",
+ code);
assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
+ String accessToken1 = node.at("/access_token").asText();
- String entity = response.getEntity(String.class);
- return JsonUtils.readTree(entity);
+ // access token 2
+ code = requestAuthorizationCode(publicClientId, clientSecret, null,
+ userAuthHeader);
+ response = requestTokenWithAuthorizationCodeAndForm(publicClientId, "",
+ code);
+ assertEquals(Status.OK.getStatusCode(), response.getStatus());
+ node = JsonUtils.readTree(response.getEntity(String.class));
+ String accessToken2 = node.at("/access_token").asText();
+
+ // list access tokens
+ node = requestTokenList(userAuthHeader, ACCESS_TOKEN_TYPE);
+ assertEquals(2, node.size());
+
+ // list refresh tokens
+ node = requestTokenList(userAuthHeader, REFRESH_TOKEN_TYPE);
+ assertEquals(0, node.size());
+
+ testRevokeTokenViaSuperClient(accessToken1, userAuthHeader);
+ node = requestTokenList(userAuthHeader, ACCESS_TOKEN_TYPE);
+ assertEquals(1, node.size());
+
+ testRevokeTokenViaSuperClient(accessToken2, userAuthHeader);
+ node = requestTokenList(userAuthHeader, ACCESS_TOKEN_TYPE);
+ assertEquals(0, node.size());
}
}
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 3d47f65..b334b65 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
@@ -42,7 +42,7 @@
protected String publicClientId = "8bIDtZnH6NvRkW2Fq";
protected String confidentialClientId = "9aHsGW6QflV13ixNpez";
- protected String confidentialClientId2 = "9aHsGW6QflV13ixNpez";
+ protected String confidentialClientId2 = "52atrL0ajex_3_5imd9Mgw";
protected String superClientId = "fCBbQkAyYzI4NzUxMg";
protected String clientSecret = "secret";