The current csrftoken parser breaks on multiple crsftokens

For example: 

`Cookie: csrftoken=asdfasd; sessionid=asdfasdf; csrftoken=qwertyqwerty`

This can happen when multiple sessions, or multiple csrftokens for different paths.
This commit is contained in:
James 2019-09-23 20:17:32 -05:00 committed by GitHub
parent 5068ea05c3
commit 6c8d4a386b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,26 +1,33 @@
(function() { (function() {
// Parse the cookie value for a CSRF token // Parse the cookie value for a CSRF token
var csrftoken; var csrftoken;
var cookies = ('; ' + document.cookie).split('; csrftoken='); var cookies = document.cookie.split(';').reduce((p, c) => {
if (cookies.length == 2) let x = {};
csrftoken = cookies.pop().split(';').shift(); let key = c.split('=')[0].trim();
x[key] = p[key] ? p[key].concat([c.split('=')[1]]) : [c.split('=')[1]];
return Object.assign(p, x);
}, {});
// Collect the URL parameters // Collect the URL parameters
var parameters = {}; var parameters = {};
window.location.hash.substr(1).split('&').forEach(function (entry) { window.location.hash
var eq = entry.indexOf('='); .substr(1)
if (eq >= 0) { .split('&')
parameters[decodeURIComponent(entry.slice(0, eq))] = .forEach(function(entry) {
decodeURIComponent(entry.slice(eq + 1)); var eq = entry.indexOf('=');
} if (eq >= 0) {
}); parameters[decodeURIComponent(entry.slice(0, eq))] = decodeURIComponent(entry.slice(eq + 1));
}
});
// Produce a Location fragment string from a parameter object. // Produce a Location fragment string from a parameter object.
function locationQuery(params) { function locationQuery(params) {
return '#' + Object.keys(params).map(function (key) { return (
return encodeURIComponent(key) + '=' + '#' +
encodeURIComponent(params[key]); Object.keys(params)
}).join('&'); .map(function(key) {
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
})
.join('&')
);
} }
// Derive a fetch URL from the current URL, sans the GraphQL parameters. // Derive a fetch URL from the current URL, sans the GraphQL parameters.
var graphqlParamNames = { var graphqlParamNames = {
@ -40,26 +47,43 @@
// Defines a GraphQL fetcher using the fetch API. // Defines a GraphQL fetcher using the fetch API.
function graphQLFetcher(graphQLParams) { function graphQLFetcher(graphQLParams) {
var headers = { var headers = {
'Accept': 'application/json', Accept: 'application/json',
'Content-Type': 'application/json' 'Content-Type': 'application/json'
}; };
if (csrftoken) {
headers['X-CSRFToken'] = csrftoken; var cookies = document.cookie.split(';').reduce((p, c) => {
let x = {};
let key = c.split('=')[0].trim();
x[key] = p[key] ? p[key].concat([c.split('=')[1]]) : [c.split('=')[1]];
return Object.assign(p, x);
}, {});
if (cookies.csrftoken && cookies.csrftoken.length) {
headers['X-CSRFToken'] = cookies.csrftoken.pop();
} }
return fetch(fetchURL, { function getFetch(headers) {
method: 'post', return fetch(fetchURL, {
headers: headers, method: 'post',
body: JSON.stringify(graphQLParams), headers: headers,
credentials: 'include', body: JSON.stringify(graphQLParams),
}).then(function (response) { credentials: 'include'
return response.text(); });
}).then(function (responseBody) { }
try { return getFetch(headers)
return JSON.parse(responseBody); .then(function(response) {
} catch (error) { console.log(headers);
return responseBody; return response.text();
} })
}); .then(function(responseBody) {
try {
return JSON.parse(responseBody);
} catch (error) {
if (cookies.csrftoken.length) {
headers['X-CSRFToken'] = cookies.csrftoken.pop();
return getFetch(headers);
}
return responseBody;
}
});
} }
// When the query and variables string is edited, update the URL bar so // When the query and variables string is edited, update the URL bar so
// that it can be easily shared. // that it can be easily shared.
@ -80,11 +104,11 @@
} }
var options = { var options = {
fetcher: graphQLFetcher, fetcher: graphQLFetcher,
onEditQuery: onEditQuery, onEditQuery: onEditQuery,
onEditVariables: onEditVariables, onEditVariables: onEditVariables,
onEditOperationName: onEditOperationName, onEditOperationName: onEditOperationName,
query: parameters.query, query: parameters.query
} };
if (parameters.variables) { if (parameters.variables) {
options.variables = parameters.variables; options.variables = parameters.variables;
} }
@ -92,8 +116,5 @@
options.operationName = parameters.operation_name; options.operationName = parameters.operation_name;
} }
// Render <GraphiQL /> into the body. // Render <GraphiQL /> into the body.
ReactDOM.render( ReactDOM.render(React.createElement(GraphiQL, options), document.body);
React.createElement(GraphiQL, options),
document.body
);
})(); })();