summaryrefslogtreecommitdiff
path: root/addons/web/static/src
diff options
context:
space:
mode:
authorRobot Odoo <xmo+roboto@odoo.com>2019-02-13 14:16:25 +0100
committerGitHub <noreply@github.com>2019-02-13 14:16:25 +0100
commit2d3dbff9653ed2b2a35e997f5c1faa99007085c5 (patch)
tree0ce58a74fde6024cd654ab04390775eaf93e9bf7 /addons/web/static/src
parent984bf2492a16f0ff357b3fc03712c68f1a011f96 (diff)
parent7abeaf56b3ae544dbe24c4a9fe4fa6d919582aba (diff)
[IMP] web, *: remove explicit references to `session_id`
Before this rev. the `session_id` was provided by the server to the webclient (in session_info, mostly) and was stored and accessible. This made XSS injection more dangerous than they should be as it was very easy to steal the `session_id`. As the browser automatically set the `session_id` on every request to the server, the webclient shouldn't need any explicit reference. Since rev. odoo/odoo@f4d541e the `session_id` cookie uses the `httponly` flag so it cannot be accessed through client side script. Task 1905359 closes odoo/odoo#30098
Diffstat (limited to 'addons/web/static/src')
-rw-r--r--addons/web/static/src/js/core/ajax.js82
-rw-r--r--addons/web/static/src/js/core/session.js90
-rw-r--r--addons/web/static/src/js/fields/basic_fields.js1
-rw-r--r--addons/web/static/src/xml/base.xml4
4 files changed, 14 insertions, 163 deletions
diff --git a/addons/web/static/src/js/core/ajax.js b/addons/web/static/src/js/core/ajax.js
index 1821d5a3be4..509126498bc 100644
--- a/addons/web/static/src/js/core/ajax.js
+++ b/addons/web/static/src/js/core/ajax.js
@@ -45,7 +45,6 @@ function genericJsonRpc (fct_name, params, settings, fct) {
var def = $.Deferred();
return def.reject.apply(def, ["communication"].concat(_.toArray(arguments)));
});
- // FIXME: jsonp?
deferred.abort = function () {
deferred.reject({message: "XmlHttpRequestError abort"}, $.Event('abort'));
if (xhr.abort) {
@@ -106,80 +105,6 @@ function jsonRpc(url, fct_name, params, settings) {
});
}
-function jsonpRpc(url, fct_name, params, settings) {
- settings = settings || {};
- return genericJsonRpc(fct_name, params, settings, function(data) {
- var payload_str = JSON.stringify(data, time.date_to_utc);
- var payload_url = $.param({r:payload_str});
- var force2step = settings.force2step || false;
- delete settings.force2step;
- var session_id = settings.session_id || null;
- delete settings.session_id;
- if (payload_url.length < 2000 && ! force2step) {
- return $.ajax(url, _.extend({}, settings, {
- url: url,
- dataType: 'jsonp',
- jsonp: 'jsonp',
- type: 'GET',
- cache: false,
- data: {r: payload_str, session_id: session_id}
- }));
- } else {
- var args = {session_id: session_id, id: data.id};
- var ifid = _.uniqueId('oe_rpc_iframe');
- var html = "<iframe src='javascript:false;' name='" + ifid + "' id='" + ifid + "' style='display:none'></iframe>";
- var $iframe = $(html);
- var nurl = 'jsonp=1&' + $.param(args);
- nurl = url.indexOf("?") !== -1 ? url + "&" + nurl : url + "?" + nurl;
- var $form = $('<form>')
- .attr('method', 'POST')
- .attr('target', ifid)
- .attr('enctype', "multipart/form-data")
- .attr('action', nurl)
- .append($('<input type="hidden" name="r" />').attr('value', payload_str))
- .hide()
- .appendTo($('body'));
- var cleanUp = function() {
- if ($iframe) {
- $iframe.unbind("load").remove();
- }
- $form.remove();
- };
- var deferred = $.Deferred();
- // the first bind is fired up when the iframe is added to the DOM
- $iframe.bind('load', function() {
- // the second bind is fired up when the result of the form submission is received
- $iframe.unbind('load').bind('load', function() {
- $.ajax({
- url: url,
- dataType: 'jsonp',
- jsonp: 'jsonp',
- type: 'GET',
- cache: false,
- data: {session_id: session_id, id: data.id}
- }).always(function() {
- cleanUp();
- }).done(function() {
- deferred.resolve.apply(deferred, arguments);
- }).fail(function() {
- deferred.reject.apply(deferred, arguments);
- });
- });
- // now that the iframe can receive data, we fill and submit the form
- $form.submit();
- });
- // append the iframe to the DOM (will trigger the first load)
- $form.after($iframe);
- if (settings.timeout) {
- realSetTimeout(function() {
- deferred.reject({});
- }, settings.timeout);
- }
- return deferred;
- }
- });
-}
-
// helper function to make a rpc with a function name hardcoded to 'call'
function rpc(url, params, settings) {
return jsonRpc(url, 'call', params, settings);
@@ -312,7 +237,7 @@ function get_file(options) {
xhr.open('POST', options.url);
data = new FormData();
_.each(options.data || {}, function (v, k) {
- data.append(k, v)
+ data.append(k, v);
});
}
data.append('token', 'dummy-because-api-expects-one');
@@ -360,7 +285,7 @@ function get_file(options) {
name: String(xhr.status),
title: nodes.length > 0 ? nodes[0].textContent : '',
}
- }
+ };
}
options.error(err);
};
@@ -375,7 +300,7 @@ function get_file(options) {
}
};
if (options.complete) {
- xhr.onloadend = function () { options.complete(); }
+ xhr.onloadend = function () { options.complete(); };
}
xhr.send(data);
@@ -596,7 +521,6 @@ function loadLibs (libs) {
var ajax = {
jsonRpc: jsonRpc,
- jsonpRpc: jsonpRpc,
rpc: rpc,
loadCSS: loadCSS,
loadJS: loadJS,
diff --git a/addons/web/static/src/js/core/session.js b/addons/web/static/src/js/core/session.js
index 694285cccdc..7212b8ad76e 100644
--- a/addons/web/static/src/js/core/session.js
+++ b/addons/web/static/src/js/core/session.js
@@ -22,11 +22,8 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
or `null` if the server to contact is the origin server.
@param {Dict} options A dictionary that can contain the following options:
- * "override_session": Default to false. If true, the current session object will
- not try to re-use a previously created session id stored in a cookie.
- * "session_id": Default to null. If specified, the specified session_id will be used
- by this session object. Specifying this option automatically implies that the option
- "override_session" is set to true.
+ * "modules"
+ * "use_cors"
*/
init: function (parent, origin, options) {
mixins.EventDispatcherMixin.init.call(this);
@@ -34,8 +31,6 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
options = options || {};
this.module_list = (options.modules && options.modules.slice()) || (window.odoo._modules && window.odoo._modules.slice()) || [];
this.server = null;
- this.session_id = options.session_id || null;
- this.override_session = options.override_session || !!options.session_id || false;
this.avoid_recursion = false;
this.use_cors = options.use_cors || false;
this.setup(origin);
@@ -61,7 +56,6 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
this.origin = origin;
this.prefix = this.origin;
this.server = this.origin; // keep chs happy
- this.origin_server = this.origin === window_origin;
options = options || {};
if ('use_cors' in options) {
this.use_cors = options.use_cors;
@@ -139,7 +133,6 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
if (!result.uid) {
return $.Deferred().reject();
}
- delete result.session_id;
_.extend(self, result);
});
},
@@ -276,9 +269,6 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
return this.currencies[currency_id];
},
get_file: function (options) {
- if (this.override_session){
- options.data.session_id = this.session_id;
- }
options.session = this;
return ajax.get_file(options);
},
@@ -290,29 +280,9 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
*/
session_reload: function () {
var result = _.extend({}, window.odoo.session_info);
- delete result.session_id;
_.extend(this, result);
return $.when();
},
- check_session_id: function () {
- var self = this;
- if (this.avoid_recursion)
- return $.when();
- if (this.session_id)
- return $.when(); // we already have the session id
- if (!this.use_cors && (this.override_session || ! this.origin_server)) {
- // If we don't use the origin server we consider we should always create a new session.
- // Even if some browsers could support cookies when using jsonp that behavior is
- // not consistent and the browser creators are tending to removing that feature.
- this.avoid_recursion = true;
- return this.rpc("/gen_session_id", {}).then(function (result) {
- self.session_id = result;
- }).always(function () {
- self.avoid_recursion = false;
- });
- }
- return $.when();
- },
/**
* Executes an RPC call, registering the provided callbacks.
*
@@ -333,57 +303,19 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, {
options.headers["X-Debug-Mode"] = $.deparam($.param.querystring()).debug;
}
- var deferred = self.check_session_id();
- var aborted = false;
- var xhrDef;
- deferred.abort = function () {
- if (xhrDef) {
- xhrDef.abort();
- } else {
- aborted = true;
- }
- };
-
- var promise = deferred.then(function () {
- if (aborted) {
- var def = $.Deferred().reject({message: "XmlHttpRequestError abort"}, $.Event('abort'));
- def.abort = function () {};
- return def;
- }
- // TODO: remove
- if (! _.isString(url)) {
- _.extend(options, url);
- url = url.url;
- }
- var fct;
- if (self.origin_server) {
- fct = ajax.jsonRpc;
- if (self.override_session) {
- options.headers["X-Openerp-Session-Id"] = self.session_id || '';
- }
- } else if (self.use_cors) {
- fct = ajax.jsonRpc;
- url = self.url(url, null);
- options.session_id = self.session_id || '';
- if (self.override_session) {
- options.headers["X-Openerp-Session-Id"] = self.session_id || '';
- }
- } else {
- fct = ajax.jsonpRpc;
- url = self.url(url, null);
- options.session_id = self.session_id || '';
- }
- xhrDef = fct(url, "call", params, options);
- return xhrDef;
- });
+ // TODO: remove
+ if (! _.isString(url)) {
+ _.extend(options, url);
+ url = url.url;
+ }
+ if (self.use_cors) {
+ url = self.url(url, null);
+ }
- promise.abort = deferred.abort;
- return promise;
+ return ajax.jsonRpc(url, "call", params, options);
},
url: function (path, params) {
params = _.extend(params || {});
- if (this.override_session || (! this.origin_server))
- params.session_id = this.session_id;
var qs = $.param(params);
if (qs.length > 0)
qs = "?" + qs;
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js
index b3cd17a38ee..ae080f45a11 100644
--- a/addons/web/static/src/js/fields/basic_fields.js
+++ b/addons/web/static/src/js/fields/basic_fields.js
@@ -1446,7 +1446,6 @@ var AbstractFieldBinary = AbstractField.extend({
self.on_file_uploaded(file.size, file.name, file.type, data);
};
} else {
- this.$('form.o_form_binary_form input[name=session_id]').val(this.getSession().session_id);
this.$('form.o_form_binary_form').submit();
}
this.$('.o_form_binary_progress').show();
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 5e2f27ccc66..dc40c962333 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -378,7 +378,6 @@
<t t-set="multi_upload" t-value="true"/>
<input type="hidden" name="model" t-att-value="widget.env and widget.env.model"/>
<input type="hidden" name="id" t-att-value="widget.env.activeIds[0]"/>
- <input type="hidden" name="session_id" t-att-value="widget.getSession().session_id" t-if="widget.getSession().override_session"/>
<span>Add...</span>
</t>
</div>
@@ -998,7 +997,6 @@
<form class="o_form_binary_form" t-att-target="fileupload_id"
method="post" enctype="multipart/form-data" t-att-action="fileupload_action || '/web/binary/upload'">
<input type="hidden" name="csrf_token" t-att-value="csrf_token"/>
- <input type="hidden" name="session_id" value="" t-if="widget.getSession().override_session"/>
<input type="hidden" name="callback" t-att-value="fileupload_id"/>
<input t-if="widget.image_only" type="file" class="o_input_file" name="ufile" accept="image/*"/>
<input t-if="!widget.image_only" type="file" class="o_input_file" name="ufile" t-att="{'multiple': multi_upload ? 'multiple' : null}"/>
@@ -1042,7 +1040,6 @@
<t t-set="multi_upload" t-value="true"/>
<input type="hidden" name="model" t-att-value="widget.model"/>
<input type="hidden" name="id" value="0"/>
- <input t-if="widget.getSession().override_session" type="hidden" name="session_id" t-att-value="widget.getSession().session_id"/>
</t>
</div>
</div>
@@ -1567,7 +1564,6 @@
<t t-set="multi_upload" t-value="true"/>
<input type="hidden" name="model" t-att-value="widget.res_model"/>
<input type="hidden" name="id" t-att-value="widget.res_id"/>
- <input type="hidden" name="session_id" t-att-value="widget.getSession().session_id"/>
</t>
</span>
</button>