blob: dfbcee82f90fb026a712f37646b2f57f07cbb029 [file] [log] [blame]
margaretha31a9f522018-04-03 20:40:45 +02001package de.ids_mannheim.korap.web.controller;
2
3import static org.junit.Assert.assertEquals;
margaretha0e8f4e72018-04-05 14:11:52 +02004import static org.junit.Assert.assertNotNull;
margaretha8d804f62018-04-10 12:39:56 +02005import static org.junit.Assert.assertTrue;
6
margaretha05122312018-04-16 15:01:34 +02007import java.util.List;
margaretha05122312018-04-16 15:01:34 +02008import java.util.Map.Entry;
margarethaf839dde2018-04-16 17:52:57 +02009import java.util.Set;
margaretha05122312018-04-16 15:01:34 +020010
margaretha8d804f62018-04-10 12:39:56 +020011import javax.ws.rs.core.MultivaluedMap;
margaretha31a9f522018-04-03 20:40:45 +020012
13import org.apache.http.entity.ContentType;
14import org.junit.Test;
15
margaretha0e8f4e72018-04-05 14:11:52 +020016import com.fasterxml.jackson.databind.JsonNode;
margaretha31a9f522018-04-03 20:40:45 +020017import com.google.common.net.HttpHeaders;
margaretha8d804f62018-04-10 12:39:56 +020018import com.sun.jersey.api.client.ClientHandlerException;
margaretha31a9f522018-04-03 20:40:45 +020019import com.sun.jersey.api.client.ClientResponse;
20import com.sun.jersey.api.client.ClientResponse.Status;
margaretha8d804f62018-04-10 12:39:56 +020021import com.sun.jersey.api.client.UniformInterfaceException;
22import com.sun.jersey.core.util.MultivaluedMapImpl;
margaretha05122312018-04-16 15:01:34 +020023import com.sun.jersey.spi.container.ContainerRequest;
margaretha31a9f522018-04-03 20:40:45 +020024
margaretha0e8f4e72018-04-05 14:11:52 +020025import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
26import de.ids_mannheim.korap.config.Attributes;
margaretha31a9f522018-04-03 20:40:45 +020027import de.ids_mannheim.korap.exceptions.KustvaktException;
margaretha80ea0dd2018-07-03 14:22:59 +020028import de.ids_mannheim.korap.exceptions.StatusCodes;
margarethaa452c5e2018-04-25 22:48:09 +020029import de.ids_mannheim.korap.oauth2.constant.OAuth2ClientType;
30import de.ids_mannheim.korap.oauth2.constant.OAuth2Error;
margaretha0e8f4e72018-04-05 14:11:52 +020031import de.ids_mannheim.korap.utils.JsonUtils;
margaretha31a9f522018-04-03 20:40:45 +020032import de.ids_mannheim.korap.web.input.OAuth2ClientJson;
33
margarethaa0486272018-04-12 19:59:31 +020034/**
35 * @author margaretha
36 *
37 */
margarethaf0085122018-08-16 16:19:53 +020038public class OAuth2ClientControllerTest extends OAuth2TestBase {
margaretha31a9f522018-04-03 20:40:45 +020039
margaretha0e8f4e72018-04-05 14:11:52 +020040 private String username = "OAuth2ClientControllerTest";
margarethaf0085122018-08-16 16:19:53 +020041 private String userAuthHeader;
42
43 public OAuth2ClientControllerTest () throws KustvaktException {
44 userAuthHeader = HttpAuthorizationHandler
45 .createBasicAuthorizationHeaderValue("dory", "password");
46 }
margaretha8d804f62018-04-10 12:39:56 +020047
margaretha05122312018-04-16 15:01:34 +020048 private void checkWWWAuthenticateHeader (ClientResponse response) {
49 Set<Entry<String, List<String>>> headers =
50 response.getHeaders().entrySet();
51
52 for (Entry<String, List<String>> header : headers) {
53 if (header.getKey().equals(ContainerRequest.WWW_AUTHENTICATE)) {
54 assertEquals("Basic realm=\"Kustvakt\"",
55 header.getValue().get(0));
56 }
57 }
58 }
margaretha7a09e482019-11-14 14:34:07 +010059
60 private ClientResponse registerClient (String username,
61 OAuth2ClientJson json) throws UniformInterfaceException,
62 ClientHandlerException, KustvaktException {
63 return resource().path(API_VERSION).path("oauth2").path("client")
64 .path("register")
65 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
66 .createBasicAuthorizationHeaderValue(username, "password"))
67 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
68 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
69 .entity(json).post(ClientResponse.class);
70 }
margaretha6374f722018-04-17 18:45:57 +020071
margaretha7f5071f2018-08-14 15:58:51 +020072 private ClientResponse registerConfidentialClient ()
margaretha8d804f62018-04-10 12:39:56 +020073 throws KustvaktException {
margaretha31a9f522018-04-03 20:40:45 +020074
75 OAuth2ClientJson json = new OAuth2ClientJson();
margaretha0e8f4e72018-04-05 14:11:52 +020076 json.setName("OAuth2ClientTest");
77 json.setType(OAuth2ClientType.CONFIDENTIAL);
margaretha31a9f522018-04-03 20:40:45 +020078 json.setUrl("http://example.client.com");
margarethaa0486272018-04-12 19:59:31 +020079 json.setRedirectURI("https://example.client.com/redirect");
margarethafb027f92018-04-23 20:00:13 +020080 json.setDescription("This is a confidential test client.");
margaretha31a9f522018-04-03 20:40:45 +020081
margaretha7a09e482019-11-14 14:34:07 +010082 return registerClient(username, json);
margaretha8d804f62018-04-10 12:39:56 +020083 }
84
margarethaf0085122018-08-16 16:19:53 +020085 private JsonNode retrieveClientInfo (String clientId, String username)
86 throws UniformInterfaceException, ClientHandlerException,
87 KustvaktException {
margaretha230effb2018-11-29 17:28:18 +010088 ClientResponse response = resource().path(API_VERSION).path("oauth2")
margarethac20cd342019-11-14 10:59:39 +010089 .path("client").path(clientId)
margarethaf0085122018-08-16 16:19:53 +020090 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
91 .createBasicAuthorizationHeaderValue(username, "pass"))
92 .get(ClientResponse.class);
93
94 assertEquals(Status.OK.getStatusCode(), response.getStatus());
95
96 String entity = response.getEntity(String.class);
97 return JsonUtils.readTree(entity);
98 }
99
margaretha8d804f62018-04-10 12:39:56 +0200100 @Test
margaretha2ea9a1e2019-01-11 16:37:21 +0100101 public void testRetrieveClientInfo () throws KustvaktException {
102 // public client
103 JsonNode clientInfo = retrieveClientInfo(publicClientId, "system");
104 assertEquals(publicClientId, clientInfo.at("/id").asText());
105 assertEquals("third party client", clientInfo.at("/name").asText());
106 assertNotNull(clientInfo.at("/description"));
margarethac20cd342019-11-14 10:59:39 +0100107 assertNotNull(clientInfo.at("/url"));
margaretha2ea9a1e2019-01-11 16:37:21 +0100108 assertEquals("PUBLIC", clientInfo.at("/type").asText());
109
110 // confidential client
111 clientInfo = retrieveClientInfo(confidentialClientId, "system");
112 assertEquals(confidentialClientId, clientInfo.at("/id").asText());
113 assertEquals("non super confidential client", clientInfo.at("/name").asText());
margarethac20cd342019-11-14 10:59:39 +0100114 assertNotNull(clientInfo.at("/url"));
margaretha2ea9a1e2019-01-11 16:37:21 +0100115 assertEquals(false,clientInfo.at("/isSuper").asBoolean());
116 assertEquals("CONFIDENTIAL", clientInfo.at("/type").asText());
117
118 // super client
119 clientInfo = retrieveClientInfo(superClientId, "system");
120 assertEquals(superClientId, clientInfo.at("/id").asText());
121 assertEquals("super confidential client", clientInfo.at("/name").asText());
margarethac20cd342019-11-14 10:59:39 +0100122 assertNotNull(clientInfo.at("/url"));
margaretha2ea9a1e2019-01-11 16:37:21 +0100123 assertEquals("CONFIDENTIAL", clientInfo.at("/type").asText());
124 assertTrue(clientInfo.at("/isSuper").asBoolean());
125 }
126
127 @Test
margaretha7f5071f2018-08-14 15:58:51 +0200128 public void testRegisterConfidentialClient () throws KustvaktException {
129 ClientResponse response = registerConfidentialClient();
margaretha8d804f62018-04-10 12:39:56 +0200130 String entity = response.getEntity(String.class);
131 assertEquals(Status.OK.getStatusCode(), response.getStatus());
132 JsonNode node = JsonUtils.readTree(entity);
margarethafb1e0992018-04-10 14:58:28 +0200133 String clientId = node.at("/client_id").asText();
134 String clientSecret = node.at("/client_secret").asText();
135 assertNotNull(clientId);
136 assertNotNull(clientSecret);
margaretha8d804f62018-04-10 12:39:56 +0200137
margaretha7f5071f2018-08-14 15:58:51 +0200138 testRegisterClientNonUniqueURL();
139
140 String newclientSecret =
141 testResetConfidentialClientSecret(clientId, clientSecret);
margarethafb1e0992018-04-10 14:58:28 +0200142
margaretha80ea0dd2018-07-03 14:22:59 +0200143 testDeregisterConfidentialClientMissingSecret(clientId);
margaretha7f5071f2018-08-14 15:58:51 +0200144 testDeregisterClientIncorrectCredentials(clientId, clientSecret);
145 testDeregisterConfidentialClient(clientId, newclientSecret);
146 }
147
margaretha7f5071f2018-08-14 15:58:51 +0200148 private void testRegisterClientNonUniqueURL () throws KustvaktException {
149 ClientResponse response = registerConfidentialClient();
150 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
151 JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
152 assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
margaretha8d804f62018-04-10 12:39:56 +0200153 }
154
155 @Test
156 public void testRegisterPublicClient () throws UniformInterfaceException,
157 ClientHandlerException, KustvaktException {
158 OAuth2ClientJson json = new OAuth2ClientJson();
159 json.setName("OAuth2PublicClient");
160 json.setType(OAuth2ClientType.PUBLIC);
margarethaf839dde2018-04-16 17:52:57 +0200161 json.setUrl("http://test.public.client.com");
162 json.setRedirectURI("https://test.public.client.com/redirect");
margarethafb027f92018-04-23 20:00:13 +0200163 json.setDescription("This is a public test client.");
margaretha8d804f62018-04-10 12:39:56 +0200164
margaretha7a09e482019-11-14 14:34:07 +0100165 ClientResponse response = registerClient(username, json);
margaretha31a9f522018-04-03 20:40:45 +0200166
margaretha0e8f4e72018-04-05 14:11:52 +0200167 String entity = response.getEntity(String.class);
margaretha31a9f522018-04-03 20:40:45 +0200168 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margaretha0e8f4e72018-04-05 14:11:52 +0200169 JsonNode node = JsonUtils.readTree(entity);
margaretha8d804f62018-04-10 12:39:56 +0200170 String clientId = node.at("/client_id").asText();
171 assertNotNull(clientId);
172 assertTrue(node.at("/client_secret").isMissingNode());
173
margaretha835178d2018-08-15 19:04:03 +0200174 testResetPublicClientSecret(clientId);
margarethaf0085122018-08-16 16:19:53 +0200175 testAccessTokenAfterDeregistration(clientId, null);
margaretha8d804f62018-04-10 12:39:56 +0200176 }
177
margaretha6374f722018-04-17 18:45:57 +0200178 @Test
margarethad7cab212018-07-02 19:01:43 +0200179 public void testRegisterDesktopApp () throws UniformInterfaceException,
180 ClientHandlerException, KustvaktException {
181 OAuth2ClientJson json = new OAuth2ClientJson();
182 json.setName("OAuth2DesktopClient");
183 json.setType(OAuth2ClientType.PUBLIC);
184 json.setDescription("This is a desktop test client.");
185
margaretha7a09e482019-11-14 14:34:07 +0100186 ClientResponse response = registerClient(username, json);
margarethad7cab212018-07-02 19:01:43 +0200187
188 String entity = response.getEntity(String.class);
189 assertEquals(Status.OK.getStatusCode(), response.getStatus());
190 JsonNode node = JsonUtils.readTree(entity);
191 String clientId = node.at("/client_id").asText();
192 assertNotNull(clientId);
193 assertTrue(node.at("/client_secret").isMissingNode());
margaretha7f5071f2018-08-14 15:58:51 +0200194
margaretha835178d2018-08-15 19:04:03 +0200195 testDeregisterPublicClientMissingUserAuthentication(clientId);
196 testDeregisterPublicClientMissingId();
margaretha7a09e482019-11-14 14:34:07 +0100197 testDeregisterPublicClient(clientId,username);
margaretha7f5071f2018-08-14 15:58:51 +0200198 }
199
margarethaf0085122018-08-16 16:19:53 +0200200 private void testAccessTokenAfterDeregistration (String clientId,
201 String clientSecret) throws KustvaktException {
202 String userAuthHeader = HttpAuthorizationHandler
203 .createBasicAuthorizationHeaderValue("dory", "password");
204
205 String code =
206 requestAuthorizationCode(clientId, "", null, userAuthHeader);
margaretha230effb2018-11-29 17:28:18 +0100207 ClientResponse response = requestTokenWithAuthorizationCodeAndForm(
208 clientId, clientSecret, code);
margaretha7f5071f2018-08-14 15:58:51 +0200209 JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
210 String accessToken = node.at("/access_token").asText();
211
212 response = searchWithAccessToken(accessToken);
213 assertEquals(Status.OK.getStatusCode(), response.getStatus());
214
margarethaf0085122018-08-16 16:19:53 +0200215 code = requestAuthorizationCode(clientId, "", null, userAuthHeader);
margaretha7a09e482019-11-14 14:34:07 +0100216 testDeregisterPublicClient(clientId, username);
margaretha7f5071f2018-08-14 15:58:51 +0200217
margarethaf0085122018-08-16 16:19:53 +0200218 response = requestTokenWithAuthorizationCodeAndForm(clientId,
219 clientSecret, code);
margaretha7f5071f2018-08-14 15:58:51 +0200220 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
221 node = JsonUtils.readTree(response.getEntity(String.class));
222 assertEquals(OAuth2Error.INVALID_CLIENT.toString(),
223 node.at("/error").asText());
224
225 response = searchWithAccessToken(accessToken);
226 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
227 node = JsonUtils.readTree(response.getEntity(String.class));
228 assertEquals(StatusCodes.INVALID_ACCESS_TOKEN,
229 node.at("/errors/0/0").asInt());
margaretha85273f12019-02-04 18:13:17 +0100230 assertEquals("Access token is invalid",
margaretha7f5071f2018-08-14 15:58:51 +0200231 node.at("/errors/0/1").asText());
margaretha6374f722018-04-17 18:45:57 +0200232 }
233
margaretha80ea0dd2018-07-03 14:22:59 +0200234 private void testDeregisterPublicClientMissingUserAuthentication (
235 String clientId) throws UniformInterfaceException,
236 ClientHandlerException, KustvaktException {
237
margaretha230effb2018-11-29 17:28:18 +0100238 ClientResponse response = resource().path(API_VERSION).path("oauth2")
239 .path("client").path("deregister").path(clientId)
240 .delete(ClientResponse.class);
margaretha80ea0dd2018-07-03 14:22:59 +0200241
242 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
243
244 String entity = response.getEntity(String.class);
245 JsonNode node = JsonUtils.readTree(entity);
246 assertEquals(StatusCodes.AUTHORIZATION_FAILED,
247 node.at("/errors/0/0").asInt());
248 }
249
250 private void testDeregisterPublicClientMissingId ()
251 throws UniformInterfaceException, ClientHandlerException,
252 KustvaktException {
253
margaretha230effb2018-11-29 17:28:18 +0100254 ClientResponse response = resource().path(API_VERSION).path("oauth2")
255 .path("client").path("deregister")
margaretha064eb6f2018-07-10 18:33:01 +0200256 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
margaretha80ea0dd2018-07-03 14:22:59 +0200257 .createBasicAuthorizationHeaderValue(username, "pass"))
258 .delete(ClientResponse.class);
259
margarethac20cd342019-11-14 10:59:39 +0100260 assertEquals(Status.METHOD_NOT_ALLOWED.getStatusCode(), response.getStatus());
margaretha80ea0dd2018-07-03 14:22:59 +0200261 }
262
margaretha7a09e482019-11-14 14:34:07 +0100263 private void testDeregisterPublicClient (String clientId, String username)
margaretha8d804f62018-04-10 12:39:56 +0200264 throws UniformInterfaceException, ClientHandlerException,
265 KustvaktException {
266
margaretha230effb2018-11-29 17:28:18 +0100267 ClientResponse response = resource().path(API_VERSION).path("oauth2")
268 .path("client").path("deregister").path(clientId)
margaretha064eb6f2018-07-10 18:33:01 +0200269 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
margaretha80ea0dd2018-07-03 14:22:59 +0200270 .createBasicAuthorizationHeaderValue(username, "pass"))
271 .delete(ClientResponse.class);
margaretha8d804f62018-04-10 12:39:56 +0200272
273 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margaretha31a9f522018-04-03 20:40:45 +0200274 }
margarethafb1e0992018-04-10 14:58:28 +0200275
276 private void testDeregisterConfidentialClient (String clientId,
277 String clientSecret) throws UniformInterfaceException,
278 ClientHandlerException, KustvaktException {
margarethafb1e0992018-04-10 14:58:28 +0200279
margaretha80ea0dd2018-07-03 14:22:59 +0200280 MultivaluedMap<String, String> form = new MultivaluedMapImpl();
281 form.add("client_secret", clientSecret);
282
margaretha230effb2018-11-29 17:28:18 +0100283 ClientResponse response = resource().path(API_VERSION).path("oauth2")
284 .path("client").path("deregister").path(clientId)
margaretha064eb6f2018-07-10 18:33:01 +0200285 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
286 .createBasicAuthorizationHeaderValue(username, "pass"))
margarethafb1e0992018-04-10 14:58:28 +0200287 .header(HttpHeaders.CONTENT_TYPE,
288 ContentType.APPLICATION_FORM_URLENCODED)
margaretha80ea0dd2018-07-03 14:22:59 +0200289 .entity(form).delete(ClientResponse.class);
margarethafb1e0992018-04-10 14:58:28 +0200290
291 assertEquals(Status.OK.getStatusCode(), response.getStatus());
292 }
293
margaretha80ea0dd2018-07-03 14:22:59 +0200294 private void testDeregisterConfidentialClientMissingSecret (String clientId)
margarethafb027f92018-04-23 20:00:13 +0200295 throws KustvaktException {
296
margaretha230effb2018-11-29 17:28:18 +0100297 ClientResponse response = resource().path(API_VERSION).path("oauth2")
298 .path("client").path("deregister").path(clientId)
margaretha064eb6f2018-07-10 18:33:01 +0200299 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
300 .createBasicAuthorizationHeaderValue(username, "pass"))
margarethafb027f92018-04-23 20:00:13 +0200301 .header(HttpHeaders.CONTENT_TYPE,
302 ContentType.APPLICATION_FORM_URLENCODED)
303 .delete(ClientResponse.class);
304
305 String entity = response.getEntity(String.class);
306 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
307
308 JsonNode node = JsonUtils.readTree(entity);
margarethad7cab212018-07-02 19:01:43 +0200309 assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
margaretha80ea0dd2018-07-03 14:22:59 +0200310 assertEquals("Missing parameters: client_secret",
margarethafb027f92018-04-23 20:00:13 +0200311 node.at("/error_description").asText());
312 }
313
margaretha7f5071f2018-08-14 15:58:51 +0200314 private void testDeregisterClientIncorrectCredentials (String clientId,
315 String clientSecret) throws UniformInterfaceException,
316 ClientHandlerException, KustvaktException {
margarethafb1e0992018-04-10 14:58:28 +0200317
margaretha80ea0dd2018-07-03 14:22:59 +0200318 MultivaluedMap<String, String> form = new MultivaluedMapImpl();
margaretha7f5071f2018-08-14 15:58:51 +0200319 form.add("client_secret", clientSecret);
margaretha80ea0dd2018-07-03 14:22:59 +0200320
margaretha230effb2018-11-29 17:28:18 +0100321 ClientResponse response = resource().path(API_VERSION).path("oauth2")
322 .path("client").path("deregister").path(clientId)
margaretha064eb6f2018-07-10 18:33:01 +0200323 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
324 .createBasicAuthorizationHeaderValue(username, "pass"))
margarethafb1e0992018-04-10 14:58:28 +0200325 .header(HttpHeaders.CONTENT_TYPE,
326 ContentType.APPLICATION_FORM_URLENCODED)
margaretha80ea0dd2018-07-03 14:22:59 +0200327 .entity(form).delete(ClientResponse.class);
margarethafb1e0992018-04-10 14:58:28 +0200328
margarethafb1e0992018-04-10 14:58:28 +0200329 String entity = response.getEntity(String.class);
margarethaa0486272018-04-12 19:59:31 +0200330 assertEquals(Status.UNAUTHORIZED.getStatusCode(), response.getStatus());
margaretha6374f722018-04-17 18:45:57 +0200331
margarethafb1e0992018-04-10 14:58:28 +0200332 JsonNode node = JsonUtils.readTree(entity);
margarethad7cab212018-07-02 19:01:43 +0200333 assertEquals(OAuth2Error.INVALID_CLIENT, node.at("/error").asText());
margarethafb027f92018-04-23 20:00:13 +0200334 assertEquals("Invalid client credentials",
margarethaa0486272018-04-12 19:59:31 +0200335 node.at("/error_description").asText());
margaretha6374f722018-04-17 18:45:57 +0200336
margaretha05122312018-04-16 15:01:34 +0200337 checkWWWAuthenticateHeader(response);
margarethafb1e0992018-04-10 14:58:28 +0200338 }
margaretha7f5071f2018-08-14 15:58:51 +0200339
340 private void testResetPublicClientSecret (String clientId)
341 throws UniformInterfaceException, ClientHandlerException,
342 KustvaktException {
343 MultivaluedMap<String, String> form = new MultivaluedMapImpl();
344 form.add("client_id", clientId);
345
margaretha230effb2018-11-29 17:28:18 +0100346 ClientResponse response = resource().path(API_VERSION).path("oauth2")
347 .path("client").path("reset")
margaretha7f5071f2018-08-14 15:58:51 +0200348 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
349 .createBasicAuthorizationHeaderValue(username, "pass"))
350 .header(HttpHeaders.CONTENT_TYPE,
351 ContentType.APPLICATION_FORM_URLENCODED)
352 .entity(form).post(ClientResponse.class);
353
354 String entity = response.getEntity(String.class);
355 assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
356 JsonNode node = JsonUtils.readTree(entity);
357 assertEquals(OAuth2Error.INVALID_REQUEST, node.at("/error").asText());
358 assertEquals("Operation is not allowed for public clients",
359 node.at("/error_description").asText());
360 }
361
362 private String testResetConfidentialClientSecret (String clientId,
363 String clientSecret) throws UniformInterfaceException,
364 ClientHandlerException, KustvaktException {
365 MultivaluedMap<String, String> form = new MultivaluedMapImpl();
366 form.add("client_id", clientId);
367 form.add("client_secret", clientSecret);
368
margaretha230effb2018-11-29 17:28:18 +0100369 ClientResponse response = resource().path(API_VERSION).path("oauth2")
370 .path("client").path("reset")
margaretha7f5071f2018-08-14 15:58:51 +0200371 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
372 .createBasicAuthorizationHeaderValue(username, "pass"))
373 .header(HttpHeaders.CONTENT_TYPE,
374 ContentType.APPLICATION_FORM_URLENCODED)
375 .entity(form).post(ClientResponse.class);
376
377 String entity = response.getEntity(String.class);
378 assertEquals(Status.OK.getStatusCode(), response.getStatus());
379
380 JsonNode node = JsonUtils.readTree(entity);
381 assertEquals(clientId, node.at("/client_id").asText());
382
383 String newClientSecret = node.at("/client_secret").asText();
384 assertTrue(!clientSecret.equals(newClientSecret));
385
386 return newClientSecret;
387 }
margaretha835178d2018-08-15 19:04:03 +0200388
389 @Test
390 public void testUpdateClientPrivilege () throws KustvaktException {
margarethaf0085122018-08-16 16:19:53 +0200391 // register a client
margaretha835178d2018-08-15 19:04:03 +0200392 ClientResponse response = registerConfidentialClient();
393 JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
394 String clientId = node.at("/client_id").asText();
margarethaf0085122018-08-16 16:19:53 +0200395 String clientSecret = node.at("/client_secret").asText();
margaretha835178d2018-08-15 19:04:03 +0200396
margarethaf0085122018-08-16 16:19:53 +0200397 // request an access token
398 String clientAuthHeader = HttpAuthorizationHandler
399 .createBasicAuthorizationHeaderValue(clientId, clientSecret);
400 String code = requestAuthorizationCode(clientId, clientSecret, null,
401 userAuthHeader);
402 node = requestTokenWithAuthorizationCodeAndHeader(clientId, code,
403 clientAuthHeader);
404 String accessToken = node.at("/access_token").asText();
405
406 testAccessTokenAfterUpgradingClient(clientId, accessToken);
407 testAccessTokenAfterDegradingSuperClient(clientId, accessToken);
margaretha230effb2018-11-29 17:28:18 +0100408
margaretha9e53bb22018-09-14 19:39:15 +0200409 testDeregisterConfidentialClient(clientId, clientSecret);
margarethaf0085122018-08-16 16:19:53 +0200410 }
411
412 // old access tokens retain their scopes
413 private void testAccessTokenAfterUpgradingClient (String clientId,
414 String accessToken) throws KustvaktException {
margaretha835178d2018-08-15 19:04:03 +0200415 MultivaluedMap<String, String> form = new MultivaluedMapImpl();
416 form.add("client_id", clientId);
417 form.add("super", "true");
418
419 updateClientPrivilege(form);
margarethaf0085122018-08-16 16:19:53 +0200420 JsonNode node = retrieveClientInfo(clientId, "admin");
margaretha835178d2018-08-15 19:04:03 +0200421 assertTrue(node.at("/isSuper").asBoolean());
422
margarethaf0085122018-08-16 16:19:53 +0200423 // list vc
margaretha03b195a2019-11-12 14:57:15 +0100424 ClientResponse response = resource().path(API_VERSION).path("vc")
425 .header(Attributes.AUTHORIZATION, "Bearer " + accessToken)
426 .get(ClientResponse.class);
margaretha835178d2018-08-15 19:04:03 +0200427
margarethaf0085122018-08-16 16:19:53 +0200428 assertEquals(ClientResponse.Status.UNAUTHORIZED.getStatusCode(),
429 response.getStatus());
margaretha835178d2018-08-15 19:04:03 +0200430 String entity = response.getEntity(String.class);
margarethaf0085122018-08-16 16:19:53 +0200431 node = JsonUtils.readTree(entity);
432 assertEquals(StatusCodes.AUTHORIZATION_FAILED,
433 node.at("/errors/0/0").asInt());
434 assertEquals("Scope vc_info is not authorized",
435 node.at("/errors/0/1").asText());
margaretha230effb2018-11-29 17:28:18 +0100436
margarethaf0085122018-08-16 16:19:53 +0200437 // search
438 response = searchWithAccessToken(accessToken);
439 assertEquals(Status.OK.getStatusCode(), response.getStatus());
440 }
441
442 private void testAccessTokenAfterDegradingSuperClient (String clientId,
443 String accessToken) throws KustvaktException {
444 MultivaluedMap<String, String> form = new MultivaluedMapImpl();
445 form.add("client_id", clientId);
446 form.add("super", "false");
margaretha230effb2018-11-29 17:28:18 +0100447
margarethaf0085122018-08-16 16:19:53 +0200448 updateClientPrivilege(form);
449 JsonNode node = retrieveClientInfo(clientId, username);
450 assertTrue(node.at("/isSuper").isMissingNode());
451
452 ClientResponse response = searchWithAccessToken(accessToken);
453 assertEquals(ClientResponse.Status.UNAUTHORIZED.getStatusCode(),
454 response.getStatus());
margaretha230effb2018-11-29 17:28:18 +0100455
margarethaf0085122018-08-16 16:19:53 +0200456 String entity = response.getEntity(String.class);
457 node = JsonUtils.readTree(entity);
458 assertEquals(StatusCodes.INVALID_ACCESS_TOKEN,
459 node.at("/errors/0/0").asInt());
margaretha85273f12019-02-04 18:13:17 +0100460 assertEquals("Access token is invalid",
margarethaf0085122018-08-16 16:19:53 +0200461 node.at("/errors/0/1").asText());
margaretha835178d2018-08-15 19:04:03 +0200462 }
margaretha230effb2018-11-29 17:28:18 +0100463
margaretha7a09e482019-11-14 14:34:07 +0100464 private void requestAuthorizedClientList (String userAuthHeader)
465 throws KustvaktException {
margaretha5a2c34e2018-11-29 19:35:13 +0100466 MultivaluedMap<String, String> form = new MultivaluedMapImpl();
467 form.add("client_id", superClientId);
468 form.add("client_secret", clientSecret);
469
470 ClientResponse response = resource().path(API_VERSION).path("oauth2")
471 .path("client").path("list")
472 .header(Attributes.AUTHORIZATION, userAuthHeader)
473 .header(HttpHeaders.CONTENT_TYPE,
474 ContentType.APPLICATION_FORM_URLENCODED)
475 .entity(form).post(ClientResponse.class);
476
477 assertEquals(Status.OK.getStatusCode(), response.getStatus());
478
479 String entity = response.getEntity(String.class);
480 JsonNode node = JsonUtils.readTree(entity);
481 assertEquals(2, node.size());
482 assertEquals(confidentialClientId, node.at("/0/clientId").asText());
483 assertEquals(publicClientId, node.at("/1/clientId").asText());
484 }
485
margaretha230effb2018-11-29 17:28:18 +0100486 @Test
487 public void testListUserClients () throws KustvaktException {
488 String username = "pearl";
489 String password = "pwd";
490 userAuthHeader = HttpAuthorizationHandler
491 .createBasicAuthorizationHeaderValue(username, password);
492
493 // super client
494 ClientResponse response = requestTokenWithPassword(superClientId,
495 clientSecret, username, password);
496 assertEquals(Status.OK.getStatusCode(), response.getStatus());
497
498 // client 1
499 String code = requestAuthorizationCode(publicClientId, clientSecret,
500 null, userAuthHeader);
501 response = requestTokenWithAuthorizationCodeAndForm(publicClientId, "",
502 code);
503 assertEquals(Status.OK.getStatusCode(), response.getStatus());
504
margarethac750cbb2018-12-11 12:47:02 +0100505 JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
506 String refreshToken = node.at("/refresh_token").asText();
507
margaretha230effb2018-11-29 17:28:18 +0100508 // client 2
509 code = requestAuthorizationCode(confidentialClientId, clientSecret,
510 null, userAuthHeader);
511 response = requestTokenWithAuthorizationCodeAndForm(
512 confidentialClientId, clientSecret, code);
513 assertEquals(Status.OK.getStatusCode(), response.getStatus());
514
margaretha7a09e482019-11-14 14:34:07 +0100515 requestAuthorizedClientList(userAuthHeader);
516 testListAuthorizedClientWithMultipleRefreshTokens(userAuthHeader);
517
518
margarethac750cbb2018-12-11 12:47:02 +0100519 testRequestTokenWithRevokedRefreshToken(publicClientId, clientSecret,
520 refreshToken);
521
522 node = JsonUtils.readTree(response.getEntity(String.class));
523 String accessToken = node.at("/access_token").asText();
524 refreshToken = node.at("/refresh_token").asText();
525
526 testRevokeTokenViaSuperClient(confidentialClientId, userAuthHeader,
527 accessToken, refreshToken);
margaretha5a2c34e2018-11-29 19:35:13 +0100528 }
margaretha230effb2018-11-29 17:28:18 +0100529
margaretha7a09e482019-11-14 14:34:07 +0100530 private void testListAuthorizedClientWithMultipleRefreshTokens (
531 String userAuthHeader) throws KustvaktException {
margaretha5a2c34e2018-11-29 19:35:13 +0100532 // client 1
533 String code = requestAuthorizationCode(publicClientId, clientSecret,
534 null, userAuthHeader);
535 ClientResponse response = requestTokenWithAuthorizationCodeAndForm(
536 publicClientId, "", code);
margaretha230effb2018-11-29 17:28:18 +0100537
538 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margaretha5a2c34e2018-11-29 19:35:13 +0100539
margaretha7a09e482019-11-14 14:34:07 +0100540 requestAuthorizedClientList(userAuthHeader);
margarethac750cbb2018-12-11 12:47:02 +0100541
542 JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
543 String accessToken = node.at("/access_token").asText();
544 String refreshToken = node.at("/refresh_token").asText();
545
546 testRevokeTokenViaSuperClient(publicClientId, userAuthHeader,
547 accessToken, refreshToken);
margaretha230effb2018-11-29 17:28:18 +0100548 }
549
margarethac750cbb2018-12-11 12:47:02 +0100550 private void testRevokeTokenViaSuperClient (String clientId,
551 String userAuthHeader, String accessToken, String refreshToken)
552 throws KustvaktException {
553 // check token before revoking
554 ClientResponse response = searchWithAccessToken(accessToken);
555 JsonNode node = JsonUtils.readTree(response.getEntity(String.class));
556 assertTrue(node.at("/matches").size() > 0);
557
558 MultivaluedMap<String, String> form = new MultivaluedMapImpl();
559 form.add("client_id", clientId);
560 form.add("super_client_id", superClientId);
561 form.add("super_client_secret", clientSecret);
562
563 response = resource().path(API_VERSION).path("oauth2").path("revoke")
564 .path("super").header(Attributes.AUTHORIZATION, userAuthHeader)
565 .header(HttpHeaders.CONTENT_TYPE,
566 ContentType.APPLICATION_FORM_URLENCODED)
567 .entity(form).post(ClientResponse.class);
568
569 assertEquals(Status.OK.getStatusCode(), response.getStatus());
570
571 response = searchWithAccessToken(accessToken);
572 node = JsonUtils.readTree(response.getEntity(String.class));
573 assertEquals(StatusCodes.INVALID_ACCESS_TOKEN,
574 node.at("/errors/0/0").asInt());
margaretha85273f12019-02-04 18:13:17 +0100575 assertEquals("Access token is invalid",
margarethac750cbb2018-12-11 12:47:02 +0100576 node.at("/errors/0/1").asText());
577
578 testRequestTokenWithRevokedRefreshToken(clientId, clientSecret,
579 refreshToken);
580 }
margaretha7a09e482019-11-14 14:34:07 +0100581
582 @Test
583 public void testListRegisteredClients ()
584 throws KustvaktException {
585
586 String clientName = "OAuth2DoryClient";
587 OAuth2ClientJson json = new OAuth2ClientJson();
588 json.setName(clientName);
589 json.setType(OAuth2ClientType.PUBLIC);
590 json.setDescription("This is dory client.");
591
592 registerClient("dory", json);
593
594 MultivaluedMap<String, String> form = new MultivaluedMapImpl();
595 form.add("client_id", superClientId);
596 form.add("client_secret", clientSecret);
597
598 ClientResponse response = resource().path(API_VERSION).path("oauth2")
599 .path("client").path("registered")
600 .header(Attributes.AUTHORIZATION, userAuthHeader)
601 .header(HttpHeaders.CONTENT_TYPE,
602 ContentType.APPLICATION_FORM_URLENCODED)
603 .entity(form).post(ClientResponse.class);
604
605 assertEquals(Status.OK.getStatusCode(), response.getStatus());
606
607 String entity = response.getEntity(String.class);
608 JsonNode node = JsonUtils.readTree(entity);
609
610 assertEquals(1, node.size());
611 assertEquals(clientName, node.at("/0/clientName").asText());
612 String clientId = node.at("/0/clientId").asText();
613 testDeregisterPublicClient(clientId, "dory");
614 }
margaretha31a9f522018-04-03 20:40:45 +0200615}