@@ -34,7 +34,7 @@ function $HttpParamSerializerProvider() {
34
34
* * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D` (stringified and encoded representation of an object)
35
35
*
36
36
* Note that serializer will sort the request parameters alphabetically.
37
- * * /
37
+ */
38
38
39
39
this . $get = function ( ) {
40
40
return function ngParamSerializer ( params ) {
@@ -101,7 +101,7 @@ function $HttpParamSerializerJQLikeProvider() {
101
101
* });
102
102
* ```
103
103
*
104
- * * /
104
+ */
105
105
this . $get = function ( ) {
106
106
return function jQueryLikeParamSerializer ( params ) {
107
107
if ( ! params ) return '' ;
@@ -261,7 +261,7 @@ function isSuccess(status) {
261
261
*
262
262
* @description
263
263
* Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
264
- * * /
264
+ */
265
265
function $HttpProvider ( ) {
266
266
/**
267
267
* @ngdoc property
@@ -315,7 +315,7 @@ function $HttpProvider() {
315
315
* - **`defaults.xsrfHeaderName`** - {string} - Name of HTTP header to populate with the
316
316
* XSRF token. Defaults value is `'X-XSRF-TOKEN'`.
317
317
*
318
- ** /
318
+ */
319
319
var defaults = this . defaults = {
320
320
// transform incoming response data
321
321
transformResponse : [ defaultHttpResponseTransform ] ,
@@ -362,7 +362,7 @@ function $HttpProvider() {
362
362
*
363
363
* @returns {boolean|Object } If a value is specified, returns the $httpProvider for chaining.
364
364
* otherwise, returns the current configured value.
365
- ** /
365
+ */
366
366
this . useApplyAsync = function ( value ) {
367
367
if ( isDefined ( value ) ) {
368
368
useApplyAsync = ! ! value ;
@@ -383,9 +383,49 @@ function $HttpProvider() {
383
383
* array, on request, but reverse order, on response.
384
384
*
385
385
* {@link ng.$http#interceptors Interceptors detailed info}
386
- ** /
386
+ */
387
387
var interceptorFactories = this . interceptors = [ ] ;
388
388
389
+ /**
390
+ * @ngdoc property
391
+ * @name $httpProvider#xsrfWhitelistedOrigins
392
+ * @description
393
+ *
394
+ * Array containing URLs whose origins are considered trusted enough to receive the XSRF token.
395
+ * See the {@link ng.$http#security-considerations Security Considerations} sections for more
396
+ * details on XSRF.
397
+ *
398
+ * **Note:** An "origin" consists of the [URI scheme](https://en.wikipedia.org/wiki/URI_scheme),
399
+ * the [hostname](https://en.wikipedia.org/wiki/Hostname) and the
400
+ * [port number](https://en.wikipedia.org/wiki/Port_(computer_networking).
401
+ *
402
+ * <div class="alert alert-warning">
403
+ * It is not possible to whitelist specific URLs/paths. The `path`, `query` and `fragment` parts
404
+ * of a URL will be ignored. For example, `https://foo.com/path/bar?query=baz#fragment` will be
405
+ * treated as `https://foo.com/`, meaning that **all** requests to URLs starting with
406
+ * `https://foo.com/` will include the XSRF token.
407
+ * </div>
408
+ *
409
+ * ## Example
410
+ *
411
+ * ```
412
+ * // App served from `https://example.com`
413
+ * angular.
414
+ * module('xsrfWhitelistedOriginsExample', []).
415
+ * config(['$httpProvider', function($httpProvider) {
416
+ * $httpProvider.xsrfWhitelistedOrigins.push('https://api.example.com/');
417
+ * }]).
418
+ * run(['$http', function($http) {
419
+ * // The XSRF token will be sent
420
+ * $http.get('https://api.example.com/preferences').then(...);
421
+ *
422
+ * // The XSRF token will NOT be sent
423
+ * $http.get('https://stats.example.com/activity').then(...);
424
+ * }]);
425
+ * ```
426
+ */
427
+ var xsrfWhitelistedOrigins = this . xsrfWhitelistedOrigins = [ ] ;
428
+
389
429
this . $get = [ '$browser' , '$httpBackend' , '$$cookieReader' , '$cacheFactory' , '$rootScope' , '$q' , '$injector' , '$sce' ,
390
430
function ( $browser , $httpBackend , $$cookieReader , $cacheFactory , $rootScope , $q , $injector , $sce ) {
391
431
@@ -409,6 +449,11 @@ function $HttpProvider() {
409
449
? $injector . get ( interceptorFactory ) : $injector . invoke ( interceptorFactory ) ) ;
410
450
} ) ;
411
451
452
+ /**
453
+ * A function to check request URLs against a list of allowed origins.
454
+ */
455
+ var urlIsAllowedOrigin = urlIsAllowedOriginChecker ( xsrfWhitelistedOrigins ) ;
456
+
412
457
/**
413
458
* @ngdoc service
414
459
* @kind function
@@ -765,25 +810,42 @@ function $HttpProvider() {
765
810
* which the attacker can trick an authenticated user into unknowingly executing actions on your
766
811
* website. AngularJS provides a mechanism to counter XSRF. When performing XHR requests, the
767
812
* $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP
768
- * header (`X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read the
769
- * cookie, your server can be assured that the XHR came from JavaScript running on your domain.
770
- * The header will not be set for cross- domain requests .
813
+ * header (by default `X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read
814
+ * the cookie, your server can be assured that the XHR came from JavaScript running on your
815
+ * domain.
771
816
*
772
817
* To take advantage of this, your server needs to set a token in a JavaScript readable session
773
818
* cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
774
- * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
775
- * that only JavaScript running on your domain could have sent the request. The token must be
776
- * unique for each user and must be verifiable by the server (to prevent the JavaScript from
819
+ * server can verify that the cookie matches the `X-XSRF-TOKEN` HTTP header, and therefore be
820
+ * sure that only JavaScript running on your domain could have sent the request. The token must
821
+ * be unique for each user and must be verifiable by the server (to prevent the JavaScript from
777
822
* making up its own tokens). We recommend that the token is a digest of your site's
778
823
* authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography))
779
824
* for added security.
780
825
*
781
- * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
782
- * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
783
- * or the per-request config object.
826
+ * The header will — by default — **not** be set for cross-domain requests. This
827
+ * prevents unauthorized servers (e.g. malicious or compromized 3rd-party APIs) from gaining
828
+ * access to your users' XSRF tokens and exposing them to Cross Site Request Forgery. If you
829
+ * want to, you can whitelist additional origins to also receive the XSRF token, by adding them
830
+ * to {@link ng.$httpProvider#xsrfWhitelistedOrigins xsrfWhitelistedOrigins}. This might be
831
+ * useful, for example, if your application, served from `example.com`, needs to access your API
832
+ * at `api.example.com`.
833
+ * See {@link ng.$httpProvider#xsrfWhitelistedOrigins $httpProvider.xsrfWhitelistedOrigins} for
834
+ * more details.
835
+ *
836
+ * <div class="alert alert-danger">
837
+ * **Warning**<br />
838
+ * Only whitelist origins that you have control over and make sure you understand the
839
+ * implications of doing so.
840
+ * </div>
841
+ *
842
+ * The name of the cookie and the header can be specified using the `xsrfCookieName` and
843
+ * `xsrHeaderName` properties of either `$httpProvider.defaults` at config-time,
844
+ * `$http.defaults` at run-time, or the per-request config object.
784
845
*
785
846
* In order to prevent collisions in environments where multiple AngularJS apps share the
786
- * same domain or subdomain, we recommend that each application uses unique cookie name.
847
+ * same domain or subdomain, we recommend that each application uses a unique cookie name.
848
+ *
787
849
*
788
850
* @param {object } config Object describing the request to be made and how it should be
789
851
* processed. The object has following properties:
@@ -1343,7 +1405,7 @@ function $HttpProvider() {
1343
1405
// if we won't have the response in cache, set the xsrf headers and
1344
1406
// send the request to the backend
1345
1407
if ( isUndefined ( cachedResp ) ) {
1346
- var xsrfValue = urlIsSameOrigin ( config . url )
1408
+ var xsrfValue = urlIsAllowedOrigin ( config . url )
1347
1409
? $$cookieReader ( ) [ config . xsrfCookieName || defaults . xsrfCookieName ]
1348
1410
: undefined ;
1349
1411
if ( xsrfValue ) {
0 commit comments