aboutsummaryrefslogtreecommitdiffstats
path: root/topics/ajax-csrf-cors.html
blob: 85fb3ba845173862b7a438e17ea2e12679be550f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
<!DOCTYPE html>
<html lang="en">
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <title>Working with AJAX, CSRF & CORS - Django REST framework</title>
    <link href="http://www.django-rest-framework.org/img/favicon.ico" rel="icon" type="image/x-icon">
    <link rel="canonical" href="http://www.django-rest-framework.org/topics/ajax-csrf-cors"/>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="Django, API, REST, Working with AJAX, CSRF & CORS">
    <meta name="author" content="Tom Christie">

    <!-- Le styles -->
    <link href="http://www.django-rest-framework.org/css/prettify.css" rel="stylesheet">
    <link href="http://www.django-rest-framework.org/css/bootstrap.css" rel="stylesheet">
    <link href="http://www.django-rest-framework.org/css/bootstrap-responsive.css" rel="stylesheet">
    <link href="http://www.django-rest-framework.org/css/default.css" rel="stylesheet">

    <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
    <!--[if lt IE 9]>
      <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->

    <script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-18852272-2']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

    </script>
    <style>
span.fusion-wrap a {
  display: block;
  margin-top: 10px;
  color: black;
}

a.fusion-poweredby {
  display: block;
  margin-top: 10px;
}
@media (max-width: 767px) {
  div.promo {display: none;}
}
</style>
  </head>
  <body onload="prettyPrint()" class="ajax-csrf-cors-page">

  <div class="wrapper">

    <div class="navbar navbar-inverse navbar-fixed-top">
      <div class="navbar-inner">
        <div class="container-fluid">
            <a class="repo-link btn btn-primary btn-small" href="https://github.com/tomchristie/django-rest-framework/tree/master">GitHub</a>
            <a class="repo-link btn btn-inverse btn-small " href="../topics/browser-enhancements">Next <i class="icon-arrow-right icon-white"></i></a>
            <a class="repo-link btn btn-inverse btn-small " href="../topics/documenting-your-api"><i class="icon-arrow-left icon-white"></i> Previous</a>
            <a class="repo-link btn btn-inverse btn-small" href="#searchModal" data-toggle="modal"><i class="icon-search icon-white"></i> Search</a>
          <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </a>
          <a class="brand" href="http://www.django-rest-framework.org">Django REST framework</a>
          <div class="nav-collapse collapse">
            <ul class="nav">
              <li><a href="http://www.django-rest-framework.org">Home</a></li>
              <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown">Tutorial <b class="caret"></b></a>
                <ul class="dropdown-menu">
                  <li><a href="http://www.django-rest-framework.org/tutorial/quickstart">Quickstart</a></li>
                  <li><a href="http://www.django-rest-framework.org/tutorial/1-serialization">1 - Serialization</a></li>
                  <li><a href="http://www.django-rest-framework.org/tutorial/2-requests-and-responses">2 - Requests and responses</a></li>
                  <li><a href="http://www.django-rest-framework.org/tutorial/3-class-based-views">3 - Class based views</a></li>
                  <li><a href="http://www.django-rest-framework.org/tutorial/4-authentication-and-permissions">4 - Authentication and permissions</a></li>
                  <li><a href="http://www.django-rest-framework.org/tutorial/5-relationships-and-hyperlinked-apis">5 - Relationships and hyperlinked APIs</a></li>
                  <li><a href="http://www.django-rest-framework.org/tutorial/6-viewsets-and-routers">6 - Viewsets and routers</a></li>
                </ul>
              </li>
              <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown">API Guide <b class="caret"></b></a>
                <ul class="dropdown-menu">
                  <li><a href="http://www.django-rest-framework.org/api-guide/requests">Requests</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/responses">Responses</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/views">Views</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/generic-views">Generic views</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/viewsets">Viewsets</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/routers">Routers</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/parsers">Parsers</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/renderers">Renderers</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/serializers">Serializers</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/fields">Serializer fields</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/relations">Serializer relations</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/authentication">Authentication</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/permissions">Permissions</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/throttling">Throttling</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/filtering">Filtering</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/pagination">Pagination</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/content-negotiation">Content negotiation</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/format-suffixes">Format suffixes</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/reverse">Returning URLs</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/exceptions">Exceptions</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/status-codes">Status codes</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/testing">Testing</a></li>
                  <li><a href="http://www.django-rest-framework.org/api-guide/settings">Settings</a></li>
                </ul>
              </li>
              <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown">Topics <b class="caret"></b></a>
                <ul class="dropdown-menu">
                  <li><a href="http://www.django-rest-framework.org/topics/documenting-your-api">Documenting your API</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/ajax-csrf-cors">AJAX, CSRF & CORS</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/browser-enhancements">Browser enhancements</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/browsable-api">The Browsable API</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas">REST, Hypermedia & HATEOAS</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/third-party-resources">Third Party Resources</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/contributing">Contributing to REST framework</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/rest-framework-2-announcement">2.0 Announcement</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/2.2-announcement">2.2 Announcement</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/2.3-announcement">2.3 Announcement</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/2.4-announcement">2.4 Announcement</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/kickstarter-announcement">Kickstarter Announcement</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/release-notes">Release Notes</a></li>
                  <li><a href="http://www.django-rest-framework.org/topics/credits">Credits</a></li>
                </ul>
              </li>
            </ul>
            <ul class="nav pull-right">
              <!-- TODO
              <li class="dropdown">
                <a href="#" class="dropdown-toggle" data-toggle="dropdown">Version: 2.0.0 <b class="caret"></b></a>
                <ul class="dropdown-menu">
                  <li><a href="#">Trunk</a></li>
                  <li><a href="#">2.0.0</a></li>
                </ul>
              </li>
            -->
            </ul>
          </div><!--/.nav-collapse -->
        </div>
      </div>
    </div>

    <div class="body-content">
      <div class="container-fluid">

<!-- Search Modal -->
<div id="searchModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
  <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
    <h3 id="myModalLabel">Documentation search</h3>
  </div>
  <div class="modal-body">
    <!-- Custom google search -->
    <script>
      (function() {
        var cx = '015016005043623903336:rxraeohqk6w';
        var gcse = document.createElement('script');
        gcse.type = 'text/javascript';
        gcse.async = true;
        gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
            '//www.google.com/cse/cse.js?cx=' + cx;
        var s = document.getElementsByTagName('script')[0];
        s.parentNode.insertBefore(gcse, s);
      })();
    </script>
    <gcse:search></gcse:search>
  </div>
  <div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
  </div>
</div>

        <div class="row-fluid">

          <div class="span3">
            <!-- TODO
            <p style="margin-top: -12px">
              <a class="btn btn-mini btn-primary" style="width: 60px">&laquo; previous</a>
              <a class="btn btn-mini btn-primary" style="float: right; margin-right: 8px; width: 60px;">next &raquo;</a>
            </p>
          -->
            <div id="table-of-contents">
              <ul class="nav nav-list side-nav well sidebar-nav-fixed">
                <li class="main"><a href="#working-with-ajax,-csrf-&-cors">Working with AJAX, CSRF & CORS</a></li>
<li><a href="#javascript-clients">Javascript clients</a></li>
<li><a href="#csrf-protection">CSRF protection</a></li>
<li><a href="#cors">CORS</a></li>

              <div class="promo">
              
              </div>
</ul>

            </div>
          </div>

          <div id="main-content" class="span9">
            <h1 id="working-with-ajax-csrf-cors">Working with AJAX, CSRF &amp; CORS</h1>
<blockquote>
<p>"Take a close look at possible CSRF / XSRF vulnerabilities on your own websites.  They're the worst kind of vulnerability &mdash; very easy to exploit by attackers, yet not so intuitively easy to understand for software developers, at least until you've been bitten by one."</p>
<p>&mdash; <a href="http://www.codinghorror.com/blog/2008/10/preventing-csrf-and-xsrf-attacks.html">Jeff Atwood</a></p>
</blockquote>
<h2 id="javascript-clients">Javascript clients</h2>
<p>If you’re building a JavaScript client to interface with your Web API, you'll need to consider if the client can use the same authentication policy that is used by the rest of the website, and also determine if you need to use CSRF tokens or CORS headers.</p>
<p>AJAX requests that are made within the same context as the API they are interacting with will typically use <code>SessionAuthentication</code>.  This ensures that once a user has logged in, any AJAX requests made can be authenticated using the same session-based authentication that is used for the rest of the website.</p>
<p>AJAX requests that are made on a different site from the API they are communicating with will typically need to use a non-session-based authentication scheme, such as <code>TokenAuthentication</code>. </p>
<h2 id="csrf-protection">CSRF protection</h2>
<p><a href="https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)">Cross Site Request Forgery</a> protection is a mechanism of guarding against a particular type of attack, which can occur when a user has not logged out of a web site, and continues to have a valid session.   In this circumstance a malicious site may be able to perform actions against the target site, within the context of the logged-in session.</p>
<p>To guard against these type of attacks, you need to do two things:</p>
<ol>
<li>Ensure that the 'safe' HTTP operations, such as <code>GET</code>, <code>HEAD</code> and <code>OPTIONS</code> cannot be used to alter any server-side state.</li>
<li>Ensure that any 'unsafe' HTTP operations, such as <code>POST</code>, <code>PUT</code>, <code>PATCH</code> and <code>DELETE</code>, always require a valid CSRF token. </li>
</ol>
<p>If you're using <code>SessionAuthentication</code> you'll need to include valid CSRF tokens for any <code>POST</code>, <code>PUT</code>, <code>PATCH</code> or <code>DELETE</code> operations.</p>
<p>In order to make AJAX requests, you need to include CSRF token in the HTTP header, as <a href="https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax">described in the Django documentation</a>.</p>
<h2 id="cors">CORS</h2>
<p><a href="http://www.w3.org/TR/cors/">Cross-Origin Resource Sharing</a> is a mechanism for allowing clients to interact with APIs that are hosted on a different domain.  CORS works by requiring the server to include a specific set of headers that allow a browser to determine if and when cross-domain requests should be allowed.</p>
<p>The best way to deal with CORS in REST framework is to add the required response headers in middleware.  This ensures that CORS is supported transparently, without having to change any behavior in your views.</p>
<p><a href="https://github.com/ottoyiu/">Otto Yiu</a> maintains the <a href="https://github.com/ottoyiu/django-cors-headers/">django-cors-headers</a> package, which is known to work correctly with REST framework APIs.</p>
          </div><!--/span-->
        </div><!--/row-->
      </div><!--/.fluid-container-->
    </div><!--/.body content-->

      <div id="push"></div>
  </div><!--/.wrapper -->

  <footer class="span12">
    <p>Sponsored by <a href="http://dabapps.com/">DabApps</a>.</a></p>
  </footer>

    <!-- Le javascript
    ================================================== -->
    <!-- Placed at the end of the document so the pages load faster -->
    <script src="http://www.django-rest-framework.org/js/jquery-1.8.1-min.js"></script>
    <script src="http://www.django-rest-framework.org/js/prettify-1.0.js"></script>
    <script src="http://www.django-rest-framework.org/js/bootstrap-2.1.1-min.js"></script>

    <script>
      //$('.side-nav').scrollspy()
      var shiftWindow = function() { scrollBy(0, -50) };
      if (location.hash) shiftWindow();
      window.addEventListener("hashchange", shiftWindow);

      $('.dropdown-menu').on('click touchstart', function(event) {
        event.stopPropagation();
      });

      // Dynamically force sidenav to no higher than browser window
      $('.side-nav').css('max-height', window.innerHeight - 130);

      $(function(){
        $(window).resize(function(){
          $('.side-nav').css('max-height', window.innerHeight - 130);
        });
      });
    </script>
</body></html>