@@ -38,7 +38,7 @@ function $HttpParamSerializerProvider() {
38
38
* * `{'foo': {'bar':'baz'}}` results in `foo=%7B%22bar%22%3A%22baz%22%7D"` (stringified and encoded representation of an object)
39
39
*
40
40
* Note that serializer will sort the request parameters alphabetically.
41
- * * /
41
+ */
42
42
43
43
this . $get = function ( ) {
44
44
return function ngParamSerializer ( params ) {
@@ -103,7 +103,7 @@ function $HttpParamSerializerJQLikeProvider() {
103
103
* });
104
104
* ```
105
105
*
106
- * * /
106
+ */
107
107
this . $get = function ( ) {
108
108
return function jQueryLikeParamSerializer ( params ) {
109
109
if ( ! params ) return '' ;
@@ -248,7 +248,7 @@ function isSuccess(status) {
248
248
* @name $httpProvider
249
249
* @description
250
250
* Use `$httpProvider` to change the default behavior of the {@link ng.$http $http} service.
251
- * * /
251
+ */
252
252
function $HttpProvider ( ) {
253
253
/**
254
254
* @ngdoc property
@@ -281,7 +281,7 @@ function $HttpProvider() {
281
281
* If specified as string, it is interpreted as a function registered with the {@link auto.$injector $injector}.
282
282
* Defaults to {@link ng.$httpParamSerializer $httpParamSerializer}.
283
283
*
284
- ** /
284
+ */
285
285
var defaults = this . defaults = {
286
286
// transform incoming response data
287
287
transformResponse : [ defaultHttpResponseTransform ] ,
@@ -326,7 +326,7 @@ function $HttpProvider() {
326
326
*
327
327
* @returns {boolean|Object } If a value is specified, returns the $httpProvider for chaining.
328
328
* otherwise, returns the current configured value.
329
- ** /
329
+ */
330
330
this . useApplyAsync = function ( value ) {
331
331
if ( isDefined ( value ) ) {
332
332
useApplyAsync = ! ! value ;
@@ -350,7 +350,7 @@ function $HttpProvider() {
350
350
*
351
351
* @returns {boolean|Object } If a value is specified, returns the $httpProvider for chaining.
352
352
* otherwise, returns the current configured value.
353
- ** /
353
+ */
354
354
this . useLegacyPromiseExtensions = function ( value ) {
355
355
if ( isDefined ( value ) ) {
356
356
useLegacyPromise = ! ! value ;
@@ -371,9 +371,49 @@ function $HttpProvider() {
371
371
* array, on request, but reverse order, on response.
372
372
*
373
373
* {@link ng.$http#interceptors Interceptors detailed info}
374
- ** /
374
+ */
375
375
var interceptorFactories = this . interceptors = [ ] ;
376
376
377
+ /**
378
+ * @ngdoc property
379
+ * @name $httpProvider#xsrfWhitelistedOrigins
380
+ * @description
381
+ *
382
+ * Array containing URLs whose origins are considered trusted enough to receive the XSRF token.
383
+ * See the {@link ng.$http#security-considerations Security Considerations} sections for more
384
+ * details on XSRF.
385
+ *
386
+ * **Note:** An "origin" consists of the [URI scheme](https://en.wikipedia.org/wiki/URI_scheme),
387
+ * the [hostname](https://en.wikipedia.org/wiki/Hostname) and the
388
+ * [port number](https://en.wikipedia.org/wiki/Port_(computer_networking).
389
+ *
390
+ * <div class="alert alert-warning">
391
+ * It is not possible to whitelist specific URLs/paths. The `path`, `query` and `fragment` parts
392
+ * of a URL will be ignored. For example, `https://foo.com/path/bar?query=baz#fragment` will be
393
+ * treated as `https://foo.com/`, meaning that **all** requests to URLs starting with
394
+ * `https://foo.com/` will include the XSRF token.
395
+ * </div>
396
+ *
397
+ * ## Example
398
+ *
399
+ * ```
400
+ * // App served from `https://example.com`
401
+ * angular.
402
+ * module('xsrfWhitelistedOriginsExample', []).
403
+ * config(['$httpProvider', function($httpProvider) {
404
+ * $httpProvider.xsrfWhitelistedOrigins.push('https://api.example.com/');
405
+ * }]).
406
+ * run(['$http', function($http) {
407
+ * // The XSRF token will be sent
408
+ * $http.get('https://api.example.com/preferences').then(...);
409
+ *
410
+ * // The XSRF token will NOT be sent
411
+ * $http.get('https://stats.example.com/activity').then(...);
412
+ * }]);
413
+ * ```
414
+ */
415
+ var xsrfWhitelistedOrigins = this . xsrfWhitelistedOrigins = [ ] ;
416
+
377
417
this . $get = [ '$httpBackend' , '$$cookieReader' , '$cacheFactory' , '$rootScope' , '$q' , '$injector' ,
378
418
function ( $httpBackend , $$cookieReader , $cacheFactory , $rootScope , $q , $injector ) {
379
419
@@ -397,6 +437,11 @@ function $HttpProvider() {
397
437
? $injector . get ( interceptorFactory ) : $injector . invoke ( interceptorFactory ) ) ;
398
438
} ) ;
399
439
440
+ /**
441
+ * A function to check request URLs against a list of allowed origins.
442
+ */
443
+ var urlIsAllowedOrigin = urlIsAllowedOriginChecker ( xsrfWhitelistedOrigins ) ;
444
+
400
445
/**
401
446
* @ngdoc service
402
447
* @kind function
@@ -773,25 +818,42 @@ function $HttpProvider() {
773
818
* which the attacker can trick an authenticated user into unknowingly executing actions on your
774
819
* website. Angular provides a mechanism to counter XSRF. When performing XHR requests, the
775
820
* $http service reads a token from a cookie (by default, `XSRF-TOKEN`) and sets it as an HTTP
776
- * header (`X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read the
777
- * cookie, your server can be assured that the XHR came from JavaScript running on your domain.
778
- * The header will not be set for cross- domain requests .
821
+ * header (by default `X-XSRF-TOKEN`). Since only JavaScript that runs on your domain could read
822
+ * the cookie, your server can be assured that the XHR came from JavaScript running on your
823
+ * domain.
779
824
*
780
825
* To take advantage of this, your server needs to set a token in a JavaScript readable session
781
826
* cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the
782
- * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure
783
- * that only JavaScript running on your domain could have sent the request. The token must be
784
- * unique for each user and must be verifiable by the server (to prevent the JavaScript from
827
+ * server can verify that the cookie matches the `X-XSRF-TOKEN` HTTP header, and therefore be
828
+ * sure that only JavaScript running on your domain could have sent the request. The token must
829
+ * be unique for each user and must be verifiable by the server (to prevent the JavaScript from
785
830
* making up its own tokens). We recommend that the token is a digest of your site's
786
831
* authentication cookie with a [salt](https://en.wikipedia.org/wiki/Salt_(cryptography))
787
832
* for added security.
788
833
*
789
- * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName
790
- * properties of either $httpProvider.defaults at config-time, $http.defaults at run-time,
791
- * or the per-request config object.
834
+ * The header will — by default — **not** be set for cross-domain requests. This
835
+ * prevents unauthorized servers (e.g. malicious or compromized 3rd-party APIs) from gaining
836
+ * access to your users' XSRF tokens and exposing them to Cross Site Request Forgery. If you
837
+ * want to, you can whitelist additional origins to also receive the XSRF token, by adding them
838
+ * to {@link ng.$httpProvider#xsrfWhitelistedOrigins xsrfWhitelistedOrigins}. This might be
839
+ * useful, for example, if your application, served from `example.com`, needs to access your API
840
+ * at `api.example.com`.
841
+ * See {@link ng.$httpProvider#xsrfWhitelistedOrigins $httpProvider.xsrfWhitelistedOrigins} for
842
+ * more details.
843
+ *
844
+ * <div class="alert alert-danger">
845
+ * **Warning**<br />
846
+ * Only whitelist origins that you have control over and make sure you understand the
847
+ * implications of doing so.
848
+ * </div>
849
+ *
850
+ * The name of the cookie and the header can be specified using the `xsrfCookieName` and
851
+ * `xsrHeaderName` properties of either `$httpProvider.defaults` at config-time,
852
+ * `$http.defaults` at run-time, or the per-request config object.
792
853
*
793
854
* In order to prevent collisions in environments where multiple Angular apps share the
794
- * same domain or subdomain, we recommend that each application uses unique cookie name.
855
+ * same domain or subdomain, we recommend that each application uses a unique cookie name.
856
+ *
795
857
*
796
858
* @param {object } config Object describing the request to be made and how it should be
797
859
* processed. The object has following properties:
@@ -1262,7 +1324,7 @@ function $HttpProvider() {
1262
1324
// if we won't have the response in cache, set the xsrf headers and
1263
1325
// send the request to the backend
1264
1326
if ( isUndefined ( cachedResp ) ) {
1265
- var xsrfValue = urlIsSameOrigin ( config . url )
1327
+ var xsrfValue = urlIsAllowedOrigin ( config . url )
1266
1328
? $$cookieReader ( ) [ config . xsrfCookieName || defaults . xsrfCookieName ]
1267
1329
: undefined ;
1268
1330
if ( xsrfValue ) {
0 commit comments