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