Skip to content

Commit

Permalink
Merge pull request #179 from UUDigitalHumanitieslab/feature/safe-csrf
Browse files Browse the repository at this point in the history
Safe csrf
  • Loading branch information
tijmenbaarda authored Jul 19, 2024
2 parents 971c5a4 + cb31509 commit b385423
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 72 deletions.
82 changes: 70 additions & 12 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"sinon": "^14.0.1"
},
"dependencies": {
"@uu-cdh/backbone-util": "^0.1.0",
"backbone": "^1.3.3",
"backbone-fractal": "^1.1.1",
"backbone.radio": "^2.0.0",
Expand Down
4 changes: 2 additions & 2 deletions frontend/vre/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ <h2>Welcome to the EDPOP Virtual Research Environment!</h2>
</div>
</div>
<script
src="https://code.jquery.com/jquery-3.6.1.min.js"
src="https://code.jquery.com/jquery-3.7.1.min.js"
crossorigin="anonymous"></script>

<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
Expand All @@ -59,7 +59,7 @@ <h2>Welcome to the EDPOP Virtual Research Environment!</h2>
crossorigin="anonymous"
></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.13/js/select2.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/backbone@1.4.1/backbone-min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/backbone@1.6.0/backbone-min.js"></script>
<script src="/static/bundle.js"></script>
</body>
</html>
7 changes: 2 additions & 5 deletions frontend/vre/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import _ from 'lodash';
import $ from 'jquery';
import Backbone from 'backbone';
import Cookies from 'jscookie';
import { wrapWithCSRF } from '@uu-cdh/backbone-util';

import './record/record.opening.aspect';
import { vreChannel } from './radio';
Expand All @@ -17,7 +18,6 @@ import { SearchResults } from './search/search.model';
import { SearchView } from './search/search.view';
import { AdvancedSearchView } from './search/advanced.search.view';
import { SelectCollectionView } from './collection/select-collection.view';
import { addCSRFToken } from './utils/generic-functions';
import { GlobalVariables } from './globals/variables';
import './globals/user';
import { accountMenu } from './globals/accountMenu';
Expand All @@ -33,10 +33,7 @@ GlobalVariables.searchView = new SearchView({model: GlobalVariables.results});
GlobalVariables.blankRecordButton = new BlankRecordButtonView();

// Override Backbone.sync so it always includes the CSRF token in requests.
(function() {
var id = _.identity;
Backbone.sync = _.overArgs(Backbone.sync, [id, id, addCSRFToken]);
}());
Backbone.sync = wrapWithCSRF(Backbone.sync, 'X-CSRFToken', 'csrftoken');

var VRERouter = Backbone.Router.extend({
routes: {
Expand Down
9 changes: 1 addition & 8 deletions frontend/vre/utils/generic-functions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import _ from 'lodash';
import Cookies from 'jscookie';

/**
* Perform the following transformation:
Expand All @@ -10,12 +9,6 @@ export function objectAsUrlParams(object) {
return _(object).entries().invokeMap('join', '=').join('&');
}

export function addCSRFToken(ajaxOptions) {
return _.defaultsDeep({
headers: {'X-CSRFToken': Cookies.get('csrftoken')},
}, ajaxOptions);
}

export function canonicalSort(key) {
var index = (canonicalOrder[key] || 100);
return index;
Expand All @@ -37,4 +30,4 @@ var canonicalOrder = {
'Note': 44,
'With Note': 48,
'Subject Headings': 52,
};
};
45 changes: 0 additions & 45 deletions frontend/vre/utils/generic-functions.test.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import assert from 'assert';
import sinon from 'sinon';

import Cookies from 'jscookie';

import {
objectAsUrlParams,
addCSRFToken,
canonicalSort,
} from './generic-functions';

Expand All @@ -30,48 +27,6 @@ describe('generic functions', function() {
});
});

describe('addCSRFToken', function() {
before(function() {
this.cookieJar = {csrftoken: 'abc123'};
sinon.replace(Cookies, 'get', sinon.fake(key =>
this.cookieJar[key]
));
});

after(function() {
sinon.restore();
delete this.cookieJar;
});

it('inserts the X-CSRFToken header', function() {
var input = {url: 'https://testing.test'};
var result = addCSRFToken(input);
assert(result !== input);
assert(result.url === input.url);
assert(result.headers);
assert(result.headers['X-CSRFToken'] === 'abc123');
});

it('overrides a preset csrftoken', function() {
var input = {headers: {'X-CSRFToken': 'def456'}};
var result = addCSRFToken(input);
assert(result.headers['X-CSRFToken'] === 'abc123');
});

it('does not modify the input', function() {
var input = {headers: {'X-CSRFToken': 'def456'}};
var result = addCSRFToken(input);
assert(input.headers['X-CSRFToken'] === 'def456');
});

it('retains other headers', function() {
var input = {url: 'https://testing.test', headers: {hi: 'there'}};
var result = addCSRFToken(input);
assert(result.headers.hi === input.headers.hi);
assert(result.headers['X-CSRFToken'] === 'abc123');
});
});

describe('canonicalSort', function() {
it('sorts Title before Author', function() {
assert(canonicalSort('Title') < canonicalSort('Author'));
Expand Down

0 comments on commit b385423

Please sign in to comment.