Skip to content

Commit

Permalink
Add tests to show CSRF behavior when client uses a made-up token
Browse files Browse the repository at this point in the history
  • Loading branch information
markpatton committed Jun 3, 2024
1 parent 17c6c89 commit 30bd16b
Showing 1 changed file with 107 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.fail;

import java.io.IOException;
import java.util.List;

import okhttp3.Cookie;
import okhttp3.Credentials;
Expand Down Expand Up @@ -119,7 +121,7 @@ public void testReadGrantsAsAnonymous() throws IOException {
String url = getBaseUrl() + "data/grant";

Request request = new Request.Builder().url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).get().build();
.header("Content-Type", JSON_API_CONTENT_TYPE).get().build();

Response response = client.newCall(request).execute();

Expand All @@ -131,7 +133,7 @@ public void testReadGrantsAsBackend() throws IOException {
String url = getBaseUrl() + "data/grant";

Request request = new Request.Builder().url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE)
.header("Content-Type", JSON_API_CONTENT_TYPE)
.header("Authorization", BACKEND_CREDENTIALS).get().build();

Response response = client.newCall(request).execute();
Expand All @@ -146,7 +148,7 @@ public void testReadPublicationsAsInvalidBackend() throws IOException {
String credentials = Credentials.basic("baduser", "badpassword");

Request request = new Request.Builder().url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).header("Authorization", credentials).get().build();
.header("Content-Type", JSON_API_CONTENT_TYPE).header("Authorization", credentials).get().build();

Response response = client.newCall(request).execute();

Expand All @@ -161,7 +163,7 @@ public void testReadGrantsAsShibUser() throws IOException {

Request.Builder builder = new Request.Builder();
Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).get().build();
.header("Content-Type", JSON_API_CONTENT_TYPE).get().build();

Response response = client.newCall(request).execute();

Expand All @@ -180,7 +182,7 @@ public void testCreateGrantAsShibUser() throws IOException, JSONException {
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).post(body).build();
.header("Content-Type", JSON_API_CONTENT_TYPE).post(body).build();

Response response = client.newCall(request).execute();

Expand All @@ -202,8 +204,8 @@ public void testCreateUpdateDeleteSubmissionAsShibUser() throws IOException, JSO
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("Content-Type", JSON_API_CONTENT_TYPE)
.header("X-XSRF-TOKEN", getCsrfToken())
.post(body).build();

Response response = client.newCall(request).execute();
Expand All @@ -219,8 +221,8 @@ public void testCreateUpdateDeleteSubmissionAsShibUser() throws IOException, JSO
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("Content-Type", JSON_API_CONTENT_TYPE)
.header("X-XSRF-TOKEN", getCsrfToken())
.patch(body).build();

Response response = client.newCall(request).execute();
Expand All @@ -233,7 +235,7 @@ public void testCreateUpdateDeleteSubmissionAsShibUser() throws IOException, JSO
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("X-XSRF-TOKEN", getCsrfToken())
.delete().build();

Response response = client.newCall(request).execute();
Expand All @@ -253,8 +255,8 @@ public void testCreateUpdateDeleteSubmissionAsShibUserWithBadCsrfToken() throws
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", "badtoken")
.header("Content-Type", JSON_API_CONTENT_TYPE)
.header("X-XSRF-TOKEN", "badtoken")
.post(body).build();

Response response = client.newCall(request).execute();
Expand All @@ -268,8 +270,8 @@ public void testCreateUpdateDeleteSubmissionAsShibUserWithBadCsrfToken() throws
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", "badtoken")
.header("Content-Type", JSON_API_CONTENT_TYPE)
.header("X-XSRF-TOKEN", "badtoken")
.patch(body).build();

Response response = client.newCall(request).execute();
Expand All @@ -282,7 +284,7 @@ public void testCreateUpdateDeleteSubmissionAsShibUserWithBadCsrfToken() throws
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", "")
.header("X-XSRF-TOKEN", "")
.delete().build();

Response response = client.newCall(request).execute();
Expand All @@ -305,8 +307,8 @@ public void testCreateUpdateDeletePublicationAsShibUser() throws IOException, JS
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("Content-Type", JSON_API_CONTENT_TYPE)
.header("X-XSRF-TOKEN", getCsrfToken())
.post(body).build();

Response response = client.newCall(request).execute();
Expand All @@ -322,8 +324,8 @@ public void testCreateUpdateDeletePublicationAsShibUser() throws IOException, JS
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("Content-Type", JSON_API_CONTENT_TYPE)
.header("X-XSRF-TOKEN", getCsrfToken())
.patch(body).build();

Response response = client.newCall(request).execute();
Expand All @@ -336,7 +338,7 @@ public void testCreateUpdateDeletePublicationAsShibUser() throws IOException, JS
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("X-XSRF-TOKEN", getCsrfToken())
.delete().build();

Response response = client.newCall(request).execute();
Expand Down Expand Up @@ -374,8 +376,8 @@ public void testCreateUpdateDeleteFileAsShibUserOwningSubmission() throws IOExce
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("Content-Type", JSON_API_CONTENT_TYPE)
.header("X-XSRF-TOKEN", getCsrfToken())
.post(body).build();

Response response = client.newCall(request).execute();
Expand All @@ -391,8 +393,8 @@ public void testCreateUpdateDeleteFileAsShibUserOwningSubmission() throws IOExce
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("Content-Type", JSON_API_CONTENT_TYPE)
.header("X-XSRF-TOKEN", getCsrfToken())
.patch(body).build();

Response response = client.newCall(request).execute();
Expand All @@ -405,7 +407,7 @@ public void testCreateUpdateDeleteFileAsShibUserOwningSubmission() throws IOExce
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("X-XSRF-TOKEN", getCsrfToken())
.delete().build();

Response response = client.newCall(request).execute();
Expand Down Expand Up @@ -442,7 +444,7 @@ public void testCreateUpdateDeleteEventAsShibUserOwningSubmission() throws IOExc
RequestBody body = RequestBody.create(event.toString(), JSON_API_MEDIA_TYPE);
Request.Builder builder = new Request.Builder();
Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("Content-Type", JSON_API_CONTENT_TYPE).header("X-XSRF-TOKEN", getCsrfToken())
.post(body).build();

Response response = client.newCall(request).execute();
Expand All @@ -457,7 +459,7 @@ public void testCreateUpdateDeleteEventAsShibUserOwningSubmission() throws IOExc
RequestBody body = RequestBody.create(event.toString(), JSON_API_MEDIA_TYPE);
Request.Builder builder = new Request.Builder();
Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).patch(body).build();
.header("Content-Type", JSON_API_CONTENT_TYPE).patch(body).build();

Response response = client.newCall(request).execute();

Expand Down Expand Up @@ -488,7 +490,7 @@ public void testCreateFileAsShibUserNotOwningSubmission() throws IOException, JS
RequestBody body = RequestBody.create(file.toString(), JSON_API_MEDIA_TYPE);
Request.Builder builder = new Request.Builder();
Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).post(body).build();
.header("Content-Type", JSON_API_CONTENT_TYPE).post(body).build();

Response response = client.newCall(request).execute();

Expand All @@ -509,7 +511,7 @@ public void testCreateEventAsShibUserNotOwningSubmission() throws IOException, J
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).post(body).build();
.header("Content-Type", JSON_API_CONTENT_TYPE).post(body).build();

Response response = client.newCall(request).execute();

Expand Down Expand Up @@ -538,7 +540,7 @@ public void testUpdateGrantAsShibUser() throws IOException, JSONException {
Request.Builder builder = new Request.Builder();

Request request = builder.url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).patch(body).build();
.header("Content-Type", JSON_API_CONTENT_TYPE).patch(body).build();

Response response = client.newCall(request).execute();

Expand Down Expand Up @@ -580,8 +582,8 @@ public void testCreateUpdateDeleteGrantAsBackend() throws IOException, JSONExcep

RequestBody body = RequestBody.create(grant.toString(), JSON_API_MEDIA_TYPE);
Request request = new Request.Builder().url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).header("Authorization", BACKEND_CREDENTIALS)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("Content-Type", JSON_API_CONTENT_TYPE).header("Authorization", BACKEND_CREDENTIALS)
.header("X-XSRF-TOKEN", getCsrfToken())
.post(body).build();

Response response = client.newCall(request).execute();
Expand All @@ -596,8 +598,8 @@ public void testCreateUpdateDeleteGrantAsBackend() throws IOException, JSONExcep
String url = getBaseUrl() + "data/grant/" + get_id(grant);
RequestBody body = RequestBody.create(grant.toString(), JSON_API_MEDIA_TYPE);
Request request = new Request.Builder().url(url).header("Accept", JSON_API_CONTENT_TYPE)
.addHeader("Content-Type", JSON_API_CONTENT_TYPE).header("Authorization", BACKEND_CREDENTIALS)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("Content-Type", JSON_API_CONTENT_TYPE).header("Authorization", BACKEND_CREDENTIALS)
.header("X-XSRF-TOKEN", getCsrfToken())
.patch(body)
.build();

Expand All @@ -611,7 +613,7 @@ public void testCreateUpdateDeleteGrantAsBackend() throws IOException, JSONExcep
String url = getBaseUrl() + "data/grant/" + get_id(grant);
Request request = new Request.Builder().url(url).header("Accept", JSON_API_CONTENT_TYPE)
.header("Authorization", BACKEND_CREDENTIALS)
.addHeader("X-XSRF-TOKEN", getCsrfToken())
.header("X-XSRF-TOKEN", getCsrfToken())
.delete().build();

Response response = client.newCall(request).execute();
Expand All @@ -620,6 +622,76 @@ public void testCreateUpdateDeleteGrantAsBackend() throws IOException, JSONExcep
}
}

@Test
public void testChooseCsrfTokenAsBackend() throws IOException, JSONException {
JSONObject grant = pass_object("grant");
set_attribute(grant, "projectName", "backend test");

HttpUrl base_url = HttpUrl.get(getBaseUrl());
String url = getBaseUrl() + "data/grant";

// Save our own CSRF token
assertNull(get_cookie("XSRF-TOKEN"));
client.cookieJar().saveFromResponse(base_url,
List.of(Cookie.parse(base_url, "XSRF-TOKEN=moo")));
assertNotNull(get_cookie("XSRF-TOKEN"));

// Create a grant with CSRF token
{
RequestBody body = RequestBody.create(grant.toString(), JSON_API_MEDIA_TYPE);
Request request = new Request.Builder().url(url).header("Accept", JSON_API_CONTENT_TYPE)
.header("Content-Type", JSON_API_CONTENT_TYPE).header("Authorization", BACKEND_CREDENTIALS)
.header("X-XSRF-TOKEN", "moo").post(body).build();

Response response = client.newCall(request).execute();

check(response, 201);
}

// Fails if header does not match token
{
RequestBody body = RequestBody.create(grant.toString(), JSON_API_MEDIA_TYPE);
Request request = new Request.Builder().url(url).header("Accept", JSON_API_CONTENT_TYPE)
.header("Content-Type", JSON_API_CONTENT_TYPE).header("Authorization", BACKEND_CREDENTIALS)
.header("X-XSRF-TOKEN", "badmoo").post(body).build();

Response response = client.newCall(request).execute();

check(response, 403);
}
}

@Test
public void testChooseCsrfTokenAsShibUser() throws IOException, JSONException {
HttpUrl base_url = HttpUrl.get(getBaseUrl());

doSamlLogin();

JSONObject grant = pass_object("grant");
set_attribute(grant, "projectName", "backend test");

// Save our own CSRF token
client.cookieJar().saveFromResponse(base_url,
List.of(Cookie.parse(base_url, "XSRF-TOKEN=moo")));

assertEquals("moo", getCsrfToken());

// Create a grant with a made up CSRF token
{
String url = getBaseUrl() + "data/grant";

RequestBody body = RequestBody.create(grant.toString(), JSON_API_MEDIA_TYPE);
Request request = new Request.Builder().url(url).header("Accept", JSON_API_CONTENT_TYPE)
.header("Content-Type", JSON_API_CONTENT_TYPE).header("X-XSRF-TOKEN", getCsrfToken())
.post(body).build();

Response response = client.newCall(request).execute();

// Fails because CSRF token tied to session
check(response, 403);
}
}

// Check handling of /app/ including CSP header.
@Test
public void testReadAppAuthorized() throws IOException {
Expand Down

0 comments on commit 30bd16b

Please sign in to comment.