blob: 6895c26dacdabeb03811b8fe8b13d5a6ae36acaf [file] [log] [blame]
margarethaf0085122018-08-16 16:19:53 +02001package de.ids_mannheim.korap.web.controller;
2
margarethad4841562022-06-01 12:24:47 +02003import java.io.IOException;
margarethaf0085122018-08-16 16:19:53 +02004import java.net.URI;
margarethaca5472a2023-09-22 18:00:03 +02005import java.time.ZoneId;
6import java.time.ZonedDateTime;
7import java.util.HashSet;
8import java.util.Set;
margarethaf0085122018-08-16 16:19:53 +02009
margarethaf0085122018-08-16 16:19:53 +020010import org.apache.http.entity.ContentType;
margarethacc929592023-01-31 11:07:35 +010011import org.glassfish.jersey.client.ClientConfig;
12import org.glassfish.jersey.client.ClientProperties;
margarethab22a5852023-01-27 14:43:36 +010013import org.glassfish.jersey.uri.UriComponent;
margaretha93e602e2019-08-07 15:19:56 +020014import org.springframework.beans.factory.annotation.Autowired;
margarethaf0085122018-08-16 16:19:53 +020015import org.springframework.util.MultiValueMap;
16import org.springframework.web.util.UriComponentsBuilder;
17
18import com.fasterxml.jackson.databind.JsonNode;
19import com.google.common.net.HttpHeaders;
margarethab38e6302023-10-26 12:33:26 +020020import com.nimbusds.oauth2.sdk.GrantType;
margaretha5f5d3ed2023-08-30 23:48:52 +020021import com.nimbusds.oauth2.sdk.OAuth2Error;
margarethaf0085122018-08-16 16:19:53 +020022
23import de.ids_mannheim.korap.authentication.http.HttpAuthorizationHandler;
24import de.ids_mannheim.korap.config.Attributes;
25import de.ids_mannheim.korap.config.SpringJerseyTest;
margarethaca5472a2023-09-22 18:00:03 +020026import de.ids_mannheim.korap.constant.OAuth2Scope;
27import de.ids_mannheim.korap.encryption.RandomCodeGenerator;
margarethaf0085122018-08-16 16:19:53 +020028import de.ids_mannheim.korap.exceptions.KustvaktException;
margarethad4841562022-06-01 12:24:47 +020029import de.ids_mannheim.korap.exceptions.StatusCodes;
margarethae28cdd92022-03-29 09:42:08 +020030import de.ids_mannheim.korap.oauth2.constant.OAuth2ClientType;
margarethaca5472a2023-09-22 18:00:03 +020031import de.ids_mannheim.korap.oauth2.dao.AccessTokenDao;
32import de.ids_mannheim.korap.oauth2.dao.OAuth2ClientDao;
margaretha93e602e2019-08-07 15:19:56 +020033import de.ids_mannheim.korap.oauth2.dao.RefreshTokenDao;
margarethaca5472a2023-09-22 18:00:03 +020034import de.ids_mannheim.korap.oauth2.entity.AccessScope;
35import de.ids_mannheim.korap.oauth2.entity.AccessToken;
36import de.ids_mannheim.korap.oauth2.entity.OAuth2Client;
margarethaf0085122018-08-16 16:19:53 +020037import de.ids_mannheim.korap.utils.JsonUtils;
margaretha977fabe2022-04-28 09:23:47 +020038import de.ids_mannheim.korap.utils.TimeUtils;
margarethae28cdd92022-03-29 09:42:08 +020039import de.ids_mannheim.korap.web.input.OAuth2ClientJson;
margaretha96c309d2023-08-16 12:24:12 +020040import jakarta.ws.rs.ProcessingException;
41import jakarta.ws.rs.client.Client;
42import jakarta.ws.rs.client.ClientBuilder;
43import jakarta.ws.rs.client.Entity;
margaretha5f5d3ed2023-08-30 23:48:52 +020044import jakarta.ws.rs.client.Invocation.Builder;
margaretha96c309d2023-08-16 12:24:12 +020045import jakarta.ws.rs.client.WebTarget;
46import jakarta.ws.rs.core.Form;
47import jakarta.ws.rs.core.MultivaluedMap;
48import jakarta.ws.rs.core.Response;
49import jakarta.ws.rs.core.Response.Status;
margarethaf0085122018-08-16 16:19:53 +020050
Marc Kupietzd43a98d2023-09-22 17:11:46 +020051import static org.junit.jupiter.api.Assertions.*;
52
margaretha230effb2018-11-29 17:28:18 +010053/**
54 * Provides common methods and variables for OAuth2 tests,
55 * and does not run any test.
margarethaf0085122018-08-16 16:19:53 +020056 *
57 * @author margaretha
58 *
59 */
margarethaf370f542018-08-23 18:51:49 +020060public abstract class OAuth2TestBase extends SpringJerseyTest {
margarethaf0085122018-08-16 16:19:53 +020061
margaretha93e602e2019-08-07 15:19:56 +020062 @Autowired
margarethaca5472a2023-09-22 18:00:03 +020063 private AccessTokenDao tokenDao;
64 @Autowired
65 private OAuth2ClientDao clientDao;
66 @Autowired
67 private RandomCodeGenerator codeGenerator;
68 @Autowired
margaretha93e602e2019-08-07 15:19:56 +020069 protected RefreshTokenDao refreshTokenDao;
margarethae20a2802022-04-21 12:37:38 +020070
margarethaf0085122018-08-16 16:19:53 +020071 protected String publicClientId = "8bIDtZnH6NvRkW2Fq";
margarethaffb89502022-04-20 12:03:16 +020072 // without registered redirect URI
73 protected String publicClientId2 = "nW5qM63Rb2a7KdT9L";
margarethaf0085122018-08-16 16:19:53 +020074 protected String confidentialClientId = "9aHsGW6QflV13ixNpez";
margaretha35074692021-03-26 18:11:59 +010075 protected String confidentialClientId2 = "52atrL0ajex_3_5imd9Mgw";
margarethaf0085122018-08-16 16:19:53 +020076 protected String superClientId = "fCBbQkAyYzI4NzUxMg";
77 protected String clientSecret = "secret";
margarethad67b4272022-04-11 17:34:19 +020078 protected String state = "thisIsMyState";
margarethaf0085122018-08-16 16:19:53 +020079
margaretha74110b72022-03-28 12:16:51 +020080 public static String ACCESS_TOKEN_TYPE = "access_token";
81 public static String REFRESH_TOKEN_TYPE = "refresh_token";
margarethae20a2802022-04-21 12:37:38 +020082
margaretha977fabe2022-04-28 09:23:47 +020083 protected int defaultRefreshTokenExpiry = TimeUtils.convertTimeToSeconds("365D");
84
margarethad67b4272022-04-11 17:34:19 +020085 protected String clientURL = "http://example.client.com";
86 protected String clientRedirectUri = "https://example.client.com/redirect";
margarethae20a2802022-04-21 12:37:38 +020087
margarethaffb89502022-04-20 12:03:16 +020088 protected MultivaluedMap<String, String> getQueryParamsFromURI (URI uri) {
89 return UriComponent.decodeQuery(uri, true);
90 };
margaretha74110b72022-03-28 12:16:51 +020091
abcpro173fe8f22022-11-08 19:56:52 +000092 protected Form getSuperClientForm () {
93 Form form = new Form();
94 form.param("super_client_id", superClientId);
95 form.param("super_client_secret", clientSecret);
margarethae20a2802022-04-21 12:37:38 +020096 return form;
97 }
98
margaretha3cd2d5f2023-05-02 14:51:11 +020099 protected String parseAuthorizationCode (Response response) {
100
101 assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
102 response.getStatus());
103
104 URI redirectUri = response.getLocation();
105 MultiValueMap<String, String> params = UriComponentsBuilder
106 .fromUri(redirectUri).build().getQueryParams();
107 return params.getFirst("code");
108 }
109
abcpro173fe8f22022-11-08 19:56:52 +0000110 protected Response requestAuthorizationCode (String responseType,
margarethad67b4272022-04-11 17:34:19 +0200111 String clientId, String redirectUri, String scope, String state,
112 String authHeader) throws KustvaktException {
margarethaf0085122018-08-16 16:19:53 +0200113
margarethacc929592023-01-31 11:07:35 +0100114 ClientConfig clientConfig = new ClientConfig();
115 clientConfig.property(ClientProperties.FOLLOW_REDIRECTS, false);
116 Client client = ClientBuilder.newClient(clientConfig);
margaretha0034a0c2022-05-17 10:37:41 +0200117
margarethacc929592023-01-31 11:07:35 +0100118 WebTarget request = client.target(getBaseUri()).path(API_VERSION)
119 .path("oauth2").path("authorize");
120
margaretha0034a0c2022-05-17 10:37:41 +0200121 if (!responseType.isEmpty()) {
122 request = request.queryParam("response_type", responseType);
123 }
124 if (!clientId.isEmpty()) {
125 request = request.queryParam("client_id", clientId);
126 }
127 if (!redirectUri.isEmpty()) {
128 request = request.queryParam("redirect_uri", redirectUri);
129 }
130 if (!scope.isEmpty()) {
131 request = request.queryParam("scope", scope);
132 }
133 if (!state.isEmpty()) {
134 request = request.queryParam("state", state);
135 }
136
margaretha5f5d3ed2023-08-30 23:48:52 +0200137 Builder builder = request.request().header(Attributes.AUTHORIZATION, authHeader);
138
139 return builder.get();
margarethaf0085122018-08-16 16:19:53 +0200140 }
141
margarethae20a2802022-04-21 12:37:38 +0200142 protected String requestAuthorizationCode (String clientId,
margarethad67b4272022-04-11 17:34:19 +0200143 String authHeader) throws KustvaktException {
margarethaf0085122018-08-16 16:19:53 +0200144
abcpro173fe8f22022-11-08 19:56:52 +0000145 Response response = requestAuthorizationCode("code", clientId, "",
margaretha64ea6452023-01-30 12:39:19 +0100146 "search match_info", "", authHeader);
margarethaf0085122018-08-16 16:19:53 +0200147 assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
148 response.getStatus());
149 URI redirectUri = response.getLocation();
150
151 MultiValueMap<String, String> params = UriComponentsBuilder
152 .fromUri(redirectUri).build().getQueryParams();
153 return params.getFirst("code");
154 }
margarethae20a2802022-04-21 12:37:38 +0200155
156 protected String requestAuthorizationCode (String clientId,
157 String redirect_uri, String authHeader) throws KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000158 Response response = requestAuthorizationCode("code", clientId,
margaretha64ea6452023-01-30 12:39:19 +0100159 redirect_uri, "search", "", authHeader);
Akrondc6d73d2020-04-15 16:40:04 +0200160 assertEquals(Status.TEMPORARY_REDIRECT.getStatusCode(),
161 response.getStatus());
162 URI redirectUri = response.getLocation();
163
164 MultiValueMap<String, String> params = UriComponentsBuilder
165 .fromUri(redirectUri).build().getQueryParams();
166 return params.getFirst("code");
167 }
margarethae20a2802022-04-21 12:37:38 +0200168
abcpro173fe8f22022-11-08 19:56:52 +0000169 protected Response requestToken (Form form)
margarethaf0085122018-08-16 16:19:53 +0200170 throws KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000171 return target().path(API_VERSION).path("oauth2").path("token")
abcpro1241bc4f2022-11-07 20:13:57 +0000172 .request()
margarethaf0085122018-08-16 16:19:53 +0200173 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
174 .header(HttpHeaders.CONTENT_TYPE,
175 ContentType.APPLICATION_FORM_URLENCODED)
abcpro173fe8f22022-11-08 19:56:52 +0000176 .post(Entity.form(form));
margarethaf0085122018-08-16 16:19:53 +0200177 }
178
179 // client credentials as form params
abcpro173fe8f22022-11-08 19:56:52 +0000180 protected Response requestTokenWithAuthorizationCodeAndForm (
margarethaf0085122018-08-16 16:19:53 +0200181 String clientId, String clientSecret, String code)
182 throws KustvaktException {
183
abcpro173fe8f22022-11-08 19:56:52 +0000184 Form form = new Form();
185 form.param("grant_type", "authorization_code");
186 form.param("client_id", clientId);
187 form.param("client_secret", clientSecret);
188 form.param("code", code);
margarethaf0085122018-08-16 16:19:53 +0200189
abcpro173fe8f22022-11-08 19:56:52 +0000190 return target().path(API_VERSION).path("oauth2").path("token")
abcpro1241bc4f2022-11-07 20:13:57 +0000191 .request()
margarethaf0085122018-08-16 16:19:53 +0200192 .header(HttpHeaders.CONTENT_TYPE,
193 ContentType.APPLICATION_FORM_URLENCODED)
abcpro173fe8f22022-11-08 19:56:52 +0000194 .post(Entity.form(form));
margarethaf0085122018-08-16 16:19:53 +0200195 }
margarethae20a2802022-04-21 12:37:38 +0200196
abcpro173fe8f22022-11-08 19:56:52 +0000197 protected Response requestTokenWithAuthorizationCodeAndForm (
Akrondc6d73d2020-04-15 16:40:04 +0200198 String clientId, String clientSecret, String code,
199 String redirectUri) throws KustvaktException {
200
abcpro173fe8f22022-11-08 19:56:52 +0000201 Form form = new Form();
202 form.param("grant_type", "authorization_code");
203 form.param("client_id", clientId);
204 form.param("client_secret", clientSecret);
205 form.param("code", code);
margarethae20a2802022-04-21 12:37:38 +0200206 if (redirectUri != null) {
abcpro173fe8f22022-11-08 19:56:52 +0000207 form.param("redirect_uri", redirectUri);
Akrondc6d73d2020-04-15 16:40:04 +0200208 }
209
abcpro173fe8f22022-11-08 19:56:52 +0000210 return target().path(API_VERSION).path("oauth2").path("token")
abcpro1241bc4f2022-11-07 20:13:57 +0000211 .request()
Akrondc6d73d2020-04-15 16:40:04 +0200212 .header(HttpHeaders.CONTENT_TYPE,
213 ContentType.APPLICATION_FORM_URLENCODED)
abcpro173fe8f22022-11-08 19:56:52 +0000214 .post(Entity.form(form));
Akrondc6d73d2020-04-15 16:40:04 +0200215 }
margarethaf0085122018-08-16 16:19:53 +0200216
217 // client credentials in authorization header
margarethae20a2802022-04-21 12:37:38 +0200218 protected JsonNode requestTokenWithAuthorizationCodeAndHeader (
219 String clientId, String code, String authHeader)
220 throws KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000221 Form form = new Form();
222 form.param("grant_type", "authorization_code");
223 form.param("client_id", clientId);
224 form.param("code", code);
margarethaf0085122018-08-16 16:19:53 +0200225
abcpro173fe8f22022-11-08 19:56:52 +0000226 Response response = target().path(API_VERSION).path("oauth2")
abcpro1241bc4f2022-11-07 20:13:57 +0000227 .path("token")
228 .request()
229 .header(Attributes.AUTHORIZATION, authHeader)
margarethaf0085122018-08-16 16:19:53 +0200230 .header(HttpHeaders.CONTENT_TYPE,
231 ContentType.APPLICATION_FORM_URLENCODED)
abcpro173fe8f22022-11-08 19:56:52 +0000232 .post(Entity.form(form));
margarethaf0085122018-08-16 16:19:53 +0200233
margaretha3cd2d5f2023-05-02 14:51:11 +0200234 assertEquals(Status.OK.getStatusCode(), response.getStatus());
235
abcpro173fe8f22022-11-08 19:56:52 +0000236 String entity = response.readEntity(String.class);
margarethaf0085122018-08-16 16:19:53 +0200237 return JsonUtils.readTree(entity);
238 }
239
abcpro173fe8f22022-11-08 19:56:52 +0000240 protected Response requestTokenWithDoryPassword (String clientId,
margarethaf0085122018-08-16 16:19:53 +0200241 String clientSecret) throws KustvaktException {
margaretha230effb2018-11-29 17:28:18 +0100242 return requestTokenWithPassword(clientId, clientSecret, "dory",
243 "password");
244 }
245
abcpro173fe8f22022-11-08 19:56:52 +0000246 protected Response requestTokenWithPassword (String clientId,
margaretha230effb2018-11-29 17:28:18 +0100247 String clientSecret, String username, String password)
248 throws KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000249 Form form = new Form();
250 form.param("grant_type", "password");
251 form.param("client_id", clientId);
margaretha7ac20b12023-09-27 09:40:16 +0200252 if (clientSecret !=null && !clientSecret.isEmpty()) {
253 form.param("client_secret", clientSecret);
254 }
abcpro173fe8f22022-11-08 19:56:52 +0000255 form.param("username", username);
256 form.param("password", password);
margarethaf0085122018-08-16 16:19:53 +0200257
258 return requestToken(form);
259 }
margarethae20a2802022-04-21 12:37:38 +0200260
margarethac750cbb2018-12-11 12:47:02 +0100261 protected void testRequestTokenWithRevokedRefreshToken (String clientId,
262 String clientSecret, String refreshToken) throws KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000263 Form form = new Form();
264 form.param("grant_type", GrantType.REFRESH_TOKEN.toString());
265 form.param("client_id", clientId);
266 form.param("client_secret", clientSecret);
267 form.param("refresh_token", refreshToken);
margarethac750cbb2018-12-11 12:47:02 +0100268 if (clientSecret != null) {
abcpro173fe8f22022-11-08 19:56:52 +0000269 form.param("client_secret", clientSecret);
margarethac750cbb2018-12-11 12:47:02 +0100270 }
margarethaf0085122018-08-16 16:19:53 +0200271
abcpro173fe8f22022-11-08 19:56:52 +0000272 Response response =
273 target().path(API_VERSION).path("oauth2").path("token")
abcpro1241bc4f2022-11-07 20:13:57 +0000274 .request()
margarethac750cbb2018-12-11 12:47:02 +0100275 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
276 .header(HttpHeaders.CONTENT_TYPE,
277 ContentType.APPLICATION_FORM_URLENCODED)
abcpro173fe8f22022-11-08 19:56:52 +0000278 .post(Entity.form(form));
margarethac750cbb2018-12-11 12:47:02 +0100279
abcpro173fe8f22022-11-08 19:56:52 +0000280 String entity = response.readEntity(String.class);
margarethac750cbb2018-12-11 12:47:02 +0100281 JsonNode node = JsonUtils.readTree(entity);
margaretha7ac20b12023-09-27 09:40:16 +0200282 assertEquals(OAuth2Error.INVALID_GRANT.getCode(), node.at("/error").asText());
margarethac750cbb2018-12-11 12:47:02 +0100283 assertEquals("Refresh token has been revoked",
284 node.at("/error_description").asText());
285 }
margarethae20a2802022-04-21 12:37:38 +0200286
abcpro173fe8f22022-11-08 19:56:52 +0000287 protected Response registerClient (String username,
abcpro163418f42022-11-09 20:35:09 +0000288 OAuth2ClientJson json) throws
289 ProcessingException, KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000290 return target().path(API_VERSION).path("oauth2").path("client")
margarethae28cdd92022-03-29 09:42:08 +0200291 .path("register")
abcpro1241bc4f2022-11-07 20:13:57 +0000292 .request()
margarethae28cdd92022-03-29 09:42:08 +0200293 .header(Attributes.AUTHORIZATION,
294 HttpAuthorizationHandler
295 .createBasicAuthorizationHeaderValue(username,
296 "password"))
297 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
298 .header(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON)
abcpro173fe8f22022-11-08 19:56:52 +0000299 .post(Entity.json(json));
margarethae28cdd92022-03-29 09:42:08 +0200300 }
margarethae20a2802022-04-21 12:37:38 +0200301
abcpro173fe8f22022-11-08 19:56:52 +0000302 protected Response registerConfidentialClient (String username)
margarethae28cdd92022-03-29 09:42:08 +0200303 throws KustvaktException {
margarethac750cbb2018-12-11 12:47:02 +0100304
margarethae28cdd92022-03-29 09:42:08 +0200305 OAuth2ClientJson json = new OAuth2ClientJson();
306 json.setName("OAuth2ClientTest");
307 json.setType(OAuth2ClientType.CONFIDENTIAL);
margaretha3ef1b812022-04-06 11:32:54 +0200308 json.setUrl(clientURL);
309 json.setRedirectURI(clientRedirectUri);
margarethae28cdd92022-03-29 09:42:08 +0200310 json.setDescription("This is a confidential test client.");
311
312 return registerClient(username, json);
313 }
margarethae20a2802022-04-21 12:37:38 +0200314
margaretha3ef1b812022-04-06 11:32:54 +0200315 protected void testConfidentialClientInfo (String clientId, String username)
abcpro163418f42022-11-09 20:35:09 +0000316 throws ProcessingException,
margaretha3ef1b812022-04-06 11:32:54 +0200317 KustvaktException {
318 JsonNode clientInfo = retrieveClientInfo(clientId, username);
margaretha79f01442022-05-04 12:03:47 +0200319 assertEquals(clientId, clientInfo.at("/client_id").asText());
320 assertEquals("OAuth2ClientTest", clientInfo.at("/client_name").asText());
margaretha3ef1b812022-04-06 11:32:54 +0200321 assertEquals(OAuth2ClientType.CONFIDENTIAL.name(),
margaretha79f01442022-05-04 12:03:47 +0200322 clientInfo.at("/client_type").asText());
margaretha3ef1b812022-04-06 11:32:54 +0200323 assertEquals(username, clientInfo.at("/registered_by").asText());
margaretha79f01442022-05-04 12:03:47 +0200324 assertEquals(clientURL, clientInfo.at("/client_url").asText());
margarethae20a2802022-04-21 12:37:38 +0200325 assertEquals(clientRedirectUri,
margaretha79f01442022-05-04 12:03:47 +0200326 clientInfo.at("/client_redirect_uri").asText());
margaretha977fabe2022-04-28 09:23:47 +0200327 // 31536000 seconds
margaretha79f01442022-05-04 12:03:47 +0200328 assertEquals(defaultRefreshTokenExpiry,
margaretha977fabe2022-04-28 09:23:47 +0200329 clientInfo.at("/refresh_token_expiry").asInt());
margaretha3ef1b812022-04-06 11:32:54 +0200330 assertNotNull(clientInfo.at("/description"));
margarethad7163122022-04-11 09:42:41 +0200331 assertNotNull(clientInfo.at("/registration_date"));
332 assertTrue(clientInfo.at("/permitted").asBoolean());
333 assertTrue(clientInfo.at("/source").isMissingNode());
margarethae20a2802022-04-21 12:37:38 +0200334
margaretha3ef1b812022-04-06 11:32:54 +0200335 }
margarethae20a2802022-04-21 12:37:38 +0200336
margarethad4841562022-06-01 12:24:47 +0200337 protected void deregisterClient (String username,
abcpro163418f42022-11-09 20:35:09 +0000338 String clientId) throws
339 ProcessingException, KustvaktException {
margarethae28cdd92022-03-29 09:42:08 +0200340
abcpro173fe8f22022-11-08 19:56:52 +0000341 Response response = target().path(API_VERSION).path("oauth2")
margarethae28cdd92022-03-29 09:42:08 +0200342 .path("client").path("deregister").path(clientId)
abcpro1241bc4f2022-11-07 20:13:57 +0000343 .request()
margarethae28cdd92022-03-29 09:42:08 +0200344 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
345 .createBasicAuthorizationHeaderValue(username, "pass"))
abcpro173fe8f22022-11-08 19:56:52 +0000346 .delete();
margarethae28cdd92022-03-29 09:42:08 +0200347
348 assertEquals(Status.OK.getStatusCode(), response.getStatus());
349 }
350
351 protected JsonNode retrieveClientInfo (String clientId, String username)
abcpro163418f42022-11-09 20:35:09 +0000352 throws ProcessingException,
margarethaf0085122018-08-16 16:19:53 +0200353 KustvaktException {
margarethab22a5852023-01-27 14:43:36 +0100354 Form form = new Form();
355 form.param("super_client_id", superClientId);
356 form.param("super_client_secret", clientSecret);
357
abcpro173fe8f22022-11-08 19:56:52 +0000358 Response response = target().path(API_VERSION).path("oauth2")
margarethae28cdd92022-03-29 09:42:08 +0200359 .path("client").path(clientId)
abcpro1241bc4f2022-11-07 20:13:57 +0000360 .request()
margarethab22a5852023-01-27 14:43:36 +0100361// .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
362// .createBasicAuthorizationHeaderValue(username, "pass"))
363 .header(HttpHeaders.CONTENT_TYPE,
364 ContentType.APPLICATION_FORM_URLENCODED)
365 .post(Entity.form(form));
margarethaf0085122018-08-16 16:19:53 +0200366
367 assertEquals(Status.OK.getStatusCode(), response.getStatus());
margarethae28cdd92022-03-29 09:42:08 +0200368
abcpro173fe8f22022-11-08 19:56:52 +0000369 String entity = response.readEntity(String.class);
margarethae28cdd92022-03-29 09:42:08 +0200370 return JsonUtils.readTree(entity);
margarethaf0085122018-08-16 16:19:53 +0200371 }
margaretha230effb2018-11-29 17:28:18 +0100372
abcpro173fe8f22022-11-08 19:56:52 +0000373 protected Response searchWithAccessToken (String accessToken) {
374 return target().path(API_VERSION).path("search")
margaretha230effb2018-11-29 17:28:18 +0100375 .queryParam("q", "Wasser").queryParam("ql", "poliqarp")
abcpro1241bc4f2022-11-07 20:13:57 +0000376 .request()
margarethaf0085122018-08-16 16:19:53 +0200377 .header(Attributes.AUTHORIZATION, "Bearer " + accessToken)
378 .header(HttpHeaders.X_FORWARDED_FOR, "149.27.0.32")
abcpro173fe8f22022-11-08 19:56:52 +0000379 .get();
margarethaf0085122018-08-16 16:19:53 +0200380 }
margarethad4841562022-06-01 12:24:47 +0200381
382 protected void testSearchWithOAuth2Token (String accessToken)
383 throws KustvaktException, IOException {
abcpro173fe8f22022-11-08 19:56:52 +0000384 Response response = searchWithAccessToken(accessToken);
385 String entity = response.readEntity(String.class);
386 assertEquals(Status.OK.getStatusCode(),
margarethad4841562022-06-01 12:24:47 +0200387 response.getStatus());
388 JsonNode node = JsonUtils.readTree(entity);
389 assertNotNull(node);
390 assertEquals(25, node.at("/matches").size());
391 }
392
393 protected void testSearchWithRevokedAccessToken (String accessToken)
394 throws KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000395 Response response = searchWithAccessToken(accessToken);
396 String entity = response.readEntity(String.class);
397 assertEquals(Status.UNAUTHORIZED.getStatusCode(),
margarethad4841562022-06-01 12:24:47 +0200398 response.getStatus());
399
400 JsonNode node = JsonUtils.readTree(entity);
401 assertEquals(StatusCodes.INVALID_ACCESS_TOKEN,
402 node.at("/errors/0/0").asInt());
403 assertEquals("Access token is invalid",
404 node.at("/errors/0/1").asText());
405 }
406
margarethae20a2802022-04-21 12:37:38 +0200407
408 protected void testRevokeTokenViaSuperClient (String token,
409 String userAuthHeader) {
abcpro173fe8f22022-11-08 19:56:52 +0000410 Form form = new Form();
411 form.param("token", token);
412 form.param("super_client_id", superClientId);
413 form.param("super_client_secret", clientSecret);
margaretha0afd44a2020-02-05 10:49:21 +0100414
abcpro173fe8f22022-11-08 19:56:52 +0000415 Response response = target().path(API_VERSION).path("oauth2")
margarethae20a2802022-04-21 12:37:38 +0200416 .path("revoke").path("super")
abcpro1241bc4f2022-11-07 20:13:57 +0000417 .request()
margaretha0afd44a2020-02-05 10:49:21 +0100418 .header(HttpHeaders.CONTENT_TYPE,
419 ContentType.APPLICATION_FORM_URLENCODED)
abcpro173fe8f22022-11-08 19:56:52 +0000420 .header(Attributes.AUTHORIZATION, userAuthHeader)
421 .post(Entity.form(form));
margaretha0afd44a2020-02-05 10:49:21 +0100422
423 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000424 assertEquals("SUCCESS", response.readEntity(String.class));
margaretha0afd44a2020-02-05 10:49:21 +0100425 }
margarethaf0085122018-08-16 16:19:53 +0200426
margaretha74110b72022-03-28 12:16:51 +0200427 protected void testRevokeToken (String token, String clientId,
428 String clientSecret, String tokenType) {
abcpro173fe8f22022-11-08 19:56:52 +0000429 Form form = new Form();
430 form.param("token_type", tokenType);
431 form.param("token", token);
432 form.param("client_id", clientId);
margaretha74110b72022-03-28 12:16:51 +0200433 if (clientSecret != null) {
abcpro173fe8f22022-11-08 19:56:52 +0000434 form.param("client_secret", clientSecret);
margaretha74110b72022-03-28 12:16:51 +0200435 }
436
abcpro173fe8f22022-11-08 19:56:52 +0000437 Response response =
438 target().path(API_VERSION).path("oauth2").path("revoke")
abcpro1241bc4f2022-11-07 20:13:57 +0000439 .request()
margaretha74110b72022-03-28 12:16:51 +0200440 .header(HttpHeaders.CONTENT_TYPE,
441 ContentType.APPLICATION_FORM_URLENCODED)
abcpro173fe8f22022-11-08 19:56:52 +0000442 .post(Entity.form(form));
margaretha74110b72022-03-28 12:16:51 +0200443
444 assertEquals(Status.OK.getStatusCode(), response.getStatus());
abcpro173fe8f22022-11-08 19:56:52 +0000445 assertEquals("SUCCESS", response.readEntity(String.class));
margaretha74110b72022-03-28 12:16:51 +0200446 }
margarethae20a2802022-04-21 12:37:38 +0200447
448 protected JsonNode listUserRegisteredClients (String username)
abcpro163418f42022-11-09 20:35:09 +0000449 throws ProcessingException,
margarethae20a2802022-04-21 12:37:38 +0200450 KustvaktException {
abcpro173fe8f22022-11-08 19:56:52 +0000451 Form form = getSuperClientForm();
452 Response response = target().path(API_VERSION).path("oauth2")
margarethae20a2802022-04-21 12:37:38 +0200453 .path("client").path("list")
abcpro1241bc4f2022-11-07 20:13:57 +0000454 .request()
margarethae20a2802022-04-21 12:37:38 +0200455 .header(Attributes.AUTHORIZATION, HttpAuthorizationHandler
456 .createBasicAuthorizationHeaderValue(username, "pwd"))
457 .header(HttpHeaders.CONTENT_TYPE,
458 ContentType.APPLICATION_FORM_URLENCODED)
abcpro173fe8f22022-11-08 19:56:52 +0000459 .post(Entity.form(form));
margarethae20a2802022-04-21 12:37:38 +0200460
461 assertEquals(Status.OK.getStatusCode(), response.getStatus());
462
abcpro173fe8f22022-11-08 19:56:52 +0000463 String entity = response.readEntity(String.class);
margarethae20a2802022-04-21 12:37:38 +0200464 return JsonUtils.readTree(entity);
465 }
margaretha9436ebe2022-04-22 11:48:37 +0200466
margaretha45ba7332023-01-31 11:39:52 +0100467 protected void testInvalidRedirectUri (String entity, String contentType,
468 boolean includeState, int status) throws KustvaktException {
margaretha9436ebe2022-04-22 11:48:37 +0200469 JsonNode node = JsonUtils.readTree(entity);
margarethab38e6302023-10-26 12:33:26 +0200470 System.out.println(node);
margaretha5f5d3ed2023-08-30 23:48:52 +0200471 assertEquals(OAuth2Error.INVALID_REQUEST.getCode(),
margaretha9436ebe2022-04-22 11:48:37 +0200472 node.at("/error").asText());
473 assertEquals("Invalid redirect URI",
474 node.at("/error_description").asText());
475 if (includeState) {
476 assertEquals(state, node.at("/state").asText());
477 }
478
margaretha45ba7332023-01-31 11:39:52 +0100479 assertEquals("application/json;charset=utf-8", contentType);
margaretha9436ebe2022-04-22 11:48:37 +0200480 assertEquals(Status.BAD_REQUEST.getStatusCode(), status);
481 }
margarethaca5472a2023-09-22 18:00:03 +0200482
483 protected String createExpiredAccessToken () throws KustvaktException {
484 String authToken = codeGenerator.createRandomCode();
485
486 // create new access token
487 OAuth2Client client = clientDao.retrieveClientById(publicClientId);
488
489 ZonedDateTime now =
490 ZonedDateTime.now(ZoneId.of(Attributes.DEFAULT_TIME_ZONE));
491 Set<AccessScope> scopes = new HashSet<>();
492 scopes.add(new AccessScope(OAuth2Scope.EDIT_VC));
493
494 AccessToken accessToken = new AccessToken();
495 accessToken.setCreatedDate(now.minusSeconds(5));
496 accessToken.setExpiryDate(now.minusSeconds(3));
497 accessToken.setToken(authToken);
498 accessToken.setScopes(scopes);
499 accessToken.setUserId("marlin");
500 accessToken.setClient(client);
501 accessToken.setUserAuthenticationTime(now.minusSeconds(5));
502 tokenDao.storeAccessToken(accessToken);
503 return authToken;
504 }
margarethaf0085122018-08-16 16:19:53 +0200505}