Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Commit

Permalink
feat($http): allow overriding the XSRF header and cookie name
Browse files Browse the repository at this point in the history
Add 'xsrfCookieName' and 'xsrfHeaderName' property to $httpProvider.defaults and
http config object, which give the name of the cookie the XSRF token is found
in, and the name of the header it is sent in, respectively.
This allows interop with servers with built-in XSRF support that use different
names.
The defaults match the current hard-coded values of 'XSRF-TOKEN' and
'X-XSRF-TOKEN'.
  • Loading branch information
sam-mccall authored and IgorMinar committed Feb 7, 2013
1 parent b001c8e commit 8155c3a
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 9 deletions.
28 changes: 21 additions & 7 deletions src/ng/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,10 @@ function $HttpProvider() {
},
post: {'Content-Type': 'application/json;charset=utf-8'},
put: {'Content-Type': 'application/json;charset=utf-8'}
}
},

xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN'
};

var providerResponseInterceptors = this.responseInterceptors = [];
Expand Down Expand Up @@ -383,9 +386,10 @@ function $HttpProvider() {
* {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which
* an unauthorized site can gain your user's private data. Angular provides following mechanism
* to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
* called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that
* runs on your domain could read the cookie, your server can be assured that the XHR came from
* JavaScript running on your domain. The header will not be set for cross-domain requests.
* (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only
* JavaScript that runs on your domain could read the cookie, your server can be assured that
* the XHR came from JavaScript running on your domain. The header will not be set for
* cross-domain requests.
*
* To take advantage of this, your server needs to set a token in a JavaScript readable session
* cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the
Expand All @@ -395,6 +399,9 @@ function $HttpProvider() {
* up its own tokens). We recommend that the token is a digest of your site's authentication
* cookie with {@link http://en.wikipedia.org/wiki/Rainbow_table salt for added security}.
*
* The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
* properties of either $httpProvider.defaults, or the per-request config object.
*
*
* @param {object} config Object describing the request to be made and how it should be
* processed. The object has following properties:
Expand All @@ -405,6 +412,8 @@ function $HttpProvider() {
* `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified.
* - **data** – `{string|Object}` – Data to be sent as the request message data.
* - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server.
* - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token.
* - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token.
* - **transformRequest** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
* transform function or an array of such functions. The transform function takes the http
* request body and headers and returns its transformed (typically serialized) version.
Expand Down Expand Up @@ -513,12 +522,17 @@ function $HttpProvider() {
function $http(config) {
config.method = uppercase(config.method);

var xsrfHeader = {},
xsrfCookieName = config.xsrfCookieName || defaults.xsrfCookieName,
xsrfHeaderName = config.xsrfHeaderName || defaults.xsrfHeaderName,
xsrfToken = isSameDomain(config.url, $browser.url()) ?
$browser.cookies()[xsrfCookieName] : undefined;
xsrfHeader[xsrfHeaderName] = xsrfToken;

var reqTransformFn = config.transformRequest || defaults.transformRequest,
respTransformFn = config.transformResponse || defaults.transformResponse,
defHeaders = defaults.headers,
xsrfToken = isSameDomain(config.url, $browser.url()) ?
$browser.cookies()['XSRF-TOKEN'] : undefined,
reqHeaders = extend({'X-XSRF-TOKEN': xsrfToken},
reqHeaders = extend(xsrfHeader,
defHeaders.common, defHeaders[lowercase(config.method)], config.headers),
reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),
promise;
Expand Down
9 changes: 7 additions & 2 deletions test/ng/httpSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -453,22 +453,27 @@ describe('$http', function() {


it('should set the XSRF cookie into a XSRF header', inject(function($browser) {
function checkXSRF(secret) {
function checkXSRF(secret, header) {
return function(headers) {
return headers['X-XSRF-TOKEN'] == secret;
return headers[header || 'X-XSRF-TOKEN'] == secret;
};
}

$browser.cookies('XSRF-TOKEN', 'secret');
$browser.cookies('aCookie', 'secret2');
$httpBackend.expect('GET', '/url', undefined, checkXSRF('secret')).respond('');
$httpBackend.expect('POST', '/url', undefined, checkXSRF('secret')).respond('');
$httpBackend.expect('PUT', '/url', undefined, checkXSRF('secret')).respond('');
$httpBackend.expect('DELETE', '/url', undefined, checkXSRF('secret')).respond('');
$httpBackend.expect('GET', '/url', undefined, checkXSRF('secret', 'aHeader')).respond('');
$httpBackend.expect('GET', '/url', undefined, checkXSRF('secret2')).respond('');

$http({url: '/url', method: 'GET'});
$http({url: '/url', method: 'POST', headers: {'S-ome': 'Header'}});
$http({url: '/url', method: 'PUT', headers: {'Another': 'Header'}});
$http({url: '/url', method: 'DELETE', headers: {}});
$http({url: '/url', method: 'GET', xsrfHeaderName: 'aHeader'})
$http({url: '/url', method: 'GET', xsrfCookieName: 'aCookie'})

$httpBackend.flush();
}));
Expand Down

0 comments on commit 8155c3a

Please sign in to comment.