CSRF protection for Wikidata extension
This commit is contained in:
parent
24feda600a
commit
1ee5068f0d
@ -56,7 +56,7 @@ ManageAccountDialog.display = function(logged_in_username, saved_credentials, ca
|
||||
|
||||
elmts.loginButton.click(function() {
|
||||
frame.hide();
|
||||
$.post(
|
||||
Refine.postCSRF(
|
||||
"command/wikidata/login",
|
||||
elmts.loginForm.serialize(),
|
||||
function(data) {
|
||||
@ -71,7 +71,7 @@ ManageAccountDialog.display = function(logged_in_username, saved_credentials, ca
|
||||
});
|
||||
|
||||
elmts.logoutButton.click(function() {
|
||||
$.post(
|
||||
Refine.postCSRF(
|
||||
"command/wikidata/login",
|
||||
"logout=true",
|
||||
function(data) {
|
||||
|
@ -94,7 +94,7 @@ PerformEditsDialog.checkAndLaunch = function () {
|
||||
ManageAccountDialog.ensureLoggedIn(function(logged_in_username) {
|
||||
if (logged_in_username) {
|
||||
var discardWaiter = DialogSystem.showBusy($.i18n('perform-wikidata-edits/analyzing-edits'));
|
||||
$.post(
|
||||
Refine.postCSRF(
|
||||
"command/wikidata/preview-wikibase-schema?" + $.param({ project: theProject.id }),
|
||||
{ engine: JSON.stringify(ui.browsingEngine.getJSON()) },
|
||||
function(data) {
|
||||
|
@ -1283,7 +1283,7 @@ SchemaAlignmentDialog.preview = function() {
|
||||
$('.invalid-schema-warning').show();
|
||||
return;
|
||||
}
|
||||
$.post(
|
||||
Refine.postCSRF(
|
||||
"command/wikidata/preview-wikibase-schema?" + $.param({ project: theProject.id }),
|
||||
{ schema: JSON.stringify(schema), engine: JSON.stringify(ui.browsingEngine.getJSON()) },
|
||||
function(data) {
|
||||
|
@ -41,6 +41,11 @@ public class LoginCommand extends Command {
|
||||
@Override
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
if(!hasValidCSRFToken(request)) {
|
||||
respondCSRFError(response);
|
||||
return;
|
||||
}
|
||||
|
||||
String username = request.getParameter("wb-username");
|
||||
String password = request.getParameter("wb-password");
|
||||
String remember = request.getParameter("remember-credentials");
|
||||
|
@ -46,6 +46,13 @@ import com.google.refine.model.Project;
|
||||
|
||||
public class PreviewWikibaseSchemaCommand extends Command {
|
||||
|
||||
/**
|
||||
* This command uses POST but is left CSRF-unprotected since it does not
|
||||
* incur a side effect or state change in the backend.
|
||||
* The reason why it uses POST is to make sure large schemas and engines
|
||||
* can be passed as parameters.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
@ -46,6 +46,10 @@ public class SaveWikibaseSchemaCommand extends Command {
|
||||
@Override
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
if(!hasValidCSRFToken(request)) {
|
||||
respondCSRFError(response);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Project project = getProject(request);
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.openrefine.wikidata.commands;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -9,6 +10,9 @@ import javax.servlet.ServletException;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.refine.commands.Command;
|
||||
import com.google.refine.util.TestUtils;
|
||||
|
||||
public class LoginCommandTest extends CommandTest {
|
||||
|
||||
@BeforeMethod
|
||||
@ -18,8 +22,16 @@ public class LoginCommandTest extends CommandTest {
|
||||
|
||||
@Test
|
||||
public void testNoCredentials() throws ServletException, IOException {
|
||||
when(request.getParameter("csrf_token")).thenReturn(Command.csrfFactory.getFreshToken());
|
||||
|
||||
command.doPost(request, response);
|
||||
|
||||
assertEquals("{\"logged_in\":false,\"username\":null}", writer.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsrfProtection() throws ServletException, IOException {
|
||||
command.doPost(request, response);
|
||||
TestUtils.assertEqualAsJson("{\"code\":\"error\",\"message\":\"Missing or invalid csrf_token parameter\"}", writer.toString());
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,9 @@ import javax.servlet.ServletException;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.refine.commands.Command;
|
||||
import com.google.refine.util.TestUtils;
|
||||
|
||||
public class SaveWikibaseSchemaCommandTest extends SchemaCommandTest {
|
||||
|
||||
@BeforeMethod
|
||||
@ -44,6 +47,8 @@ public class SaveWikibaseSchemaCommandTest extends SchemaCommandTest {
|
||||
@Test
|
||||
public void testValidSchema()
|
||||
throws ServletException, IOException {
|
||||
when(request.getParameter("csrf_token")).thenReturn(Command.csrfFactory.getFreshToken());
|
||||
|
||||
String schemaJson = jsonFromFile("schema/inception.json").toString();
|
||||
when(request.getParameter("schema")).thenReturn(schemaJson);
|
||||
|
||||
@ -54,6 +59,8 @@ public class SaveWikibaseSchemaCommandTest extends SchemaCommandTest {
|
||||
|
||||
@Test
|
||||
public void testInvalidSchema() throws ServletException, IOException {
|
||||
when(request.getParameter("csrf_token")).thenReturn(Command.csrfFactory.getFreshToken());
|
||||
|
||||
String schemaJson = "{\"itemDocuments\":[{\"statementGroups\":[{\"statements\":[]}],"
|
||||
+"\"nameDescs\":[]}],\"wikibasePrefix\":\"http://www.wikidata.org/entity/\"}";
|
||||
|
||||
@ -62,4 +69,13 @@ public class SaveWikibaseSchemaCommandTest extends SchemaCommandTest {
|
||||
|
||||
assertTrue(writer.toString().contains("\"error\""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCsrfProtection() throws ServletException, IOException {
|
||||
String schemaJson = jsonFromFile("schema/inception.json").toString();
|
||||
when(request.getParameter("schema")).thenReturn(schemaJson);
|
||||
|
||||
command.doPost(request, response);
|
||||
TestUtils.assertEqualAsJson("{\"code\":\"error\",\"message\":\"Missing or invalid csrf_token parameter\"}", writer.toString());
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import javax.servlet.ServletException;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.refine.commands.Command;
|
||||
import com.google.refine.util.ParsingUtilities;
|
||||
|
||||
public abstract class SchemaCommandTest extends CommandTest {
|
||||
@ -39,9 +40,11 @@ public abstract class SchemaCommandTest extends CommandTest {
|
||||
@Test
|
||||
public void testNoSchema()
|
||||
throws ServletException, IOException {
|
||||
when(request.getParameter("csrf_token")).thenReturn(Command.csrfFactory.getFreshToken());
|
||||
|
||||
command.doPost(request, response);
|
||||
|
||||
assertEquals("{\"code\":\"error\",\"message\":\"No Wikibase schema provided.\"}", writer.toString());
|
||||
assertEquals(writer.toString(), "{\"code\":\"error\",\"message\":\"No Wikibase schema provided.\"}");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -56,7 +56,11 @@ Refine.wrapCSRF = function(onCSRF) {
|
||||
Refine.postCSRF = function(url, data, success, dataType, failCallback) {
|
||||
return Refine.wrapCSRF(function(token) {
|
||||
var fullData = data || {};
|
||||
if (typeof fulldata == 'string') {
|
||||
fullData = fullData + $.param({csrf_token: token});
|
||||
} else {
|
||||
fullData['csrf_token'] = token;
|
||||
}
|
||||
var req = $.post(url, fullData, success, dataType);
|
||||
if (failCallback !== undefined) {
|
||||
req.fail(failCallback);
|
||||
|
@ -55,7 +55,11 @@ Refine.wrapCSRF = function(onCSRF) {
|
||||
Refine.postCSRF = function(url, data, success, dataType, failCallback) {
|
||||
return Refine.wrapCSRF(function(token) {
|
||||
var fullData = data || {};
|
||||
if (typeof fulldata == 'string') {
|
||||
fullData = fullData + $.param({csrf_token: token});
|
||||
} else {
|
||||
fullData['csrf_token'] = token;
|
||||
}
|
||||
var req = $.post(url, fullData, success, dataType);
|
||||
if (failCallback !== undefined) {
|
||||
req.fail(failCallback);
|
||||
|
@ -420,7 +420,11 @@ Refine.wrapCSRF = function(onCSRF) {
|
||||
Refine.postCSRF = function(url, data, success, dataType) {
|
||||
Refine.wrapCSRF(function(token) {
|
||||
var fullData = data || {};
|
||||
if (typeof fulldata == 'string') {
|
||||
fullData = fullData + $.param({csrf_token: token});
|
||||
} else {
|
||||
fullData['csrf_token'] = token;
|
||||
}
|
||||
$.post(url, fullData, success, dataType);
|
||||
});
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user