@@ -117,7 +117,15 @@ body.
117
117
### JavaScript Applications
118
118
119
119
This approach is useful if you're using a front-end JavaScript framework like
120
- React, Ember or Angular, or are providing a JSON API.
120
+ React, Ember or Angular, and are providing a JSON API. Specifically, we need
121
+ to provide a way for our front-end fetch/AJAX calls to pass the token on each
122
+ fetch (AJAX/XMLHttpRequest) request. We achieve this by:
123
+
124
+ - Parsing the token from the ` <input> ` field generated by the
125
+ ` csrf.TemplateField(r) ` helper, or passing it back in a response header.
126
+ - Sending this token back on every request
127
+ - Ensuring our cookie is attached to the request so that the form/header
128
+ value can be compared to the cookie value.
121
129
122
130
We'll also look at applying selective CSRF protection using
123
131
[ gorilla/mux's] ( https://www.gorillatoolkit.org/pkg/mux ) sub-routers,
@@ -133,12 +141,13 @@ import (
133
141
134
142
func main () {
135
143
r := mux.NewRouter ()
144
+ csrfMiddleware := csrf.Protect ([]byte (" 32-byte-long-auth-key" ))
136
145
137
146
api := r.PathPrefix (" /api" ).Subrouter ()
147
+ api.Use (csrfMiddleware)
138
148
api.HandleFunc (" /user/{id}" , GetUser).Methods (" GET" )
139
149
140
- http.ListenAndServe (" :8000" ,
141
- csrf.Protect ([]byte (" 32-byte-long-auth-key" ))(r))
150
+ http.ListenAndServe (" :8000" , r)
142
151
}
143
152
144
153
func GetUser (w http .ResponseWriter , r *http .Request ) {
@@ -159,11 +168,39 @@ func GetUser(w http.ResponseWriter, r *http.Request) {
159
168
}
160
169
```
161
170
171
+ In our JavaScript application, we should read the token from the response
172
+ headers and pass it in a request header for all requests. Here's what that
173
+ looks like when using [ Axios] ( https://github.com/axios/axios ) , a popular
174
+ JavaScript HTTP client library:
175
+
176
+ ``` js
177
+ // You can alternatively parse the response header for the X-CSRF-Token, and
178
+ // store that instead, if you followed the steps above to write the token to a
179
+ // response header.
180
+ let csrfToken = document .getElementsByName (" gorilla.csrf.Token" )[0 ].value
181
+
182
+ // via https://github.com/axios/axios#creating-an-instance
183
+ const instance = axios .create ({
184
+ baseURL: " https://example.com/api/" ,
185
+ timeout: 1000 ,
186
+ headers: { " X-CSRF-Token" : csrfToken }
187
+ })
188
+
189
+ // Now, any HTTP request you make will include the csrfToken from the page,
190
+ // provided you update the csrfToken variable for each render.
191
+ try {
192
+ let resp = await instance .post (endpoint, formData)
193
+ // Do something with resp
194
+ } catch (err) {
195
+ // Handle the exception
196
+ }
197
+ ```
198
+
162
199
### Google App Engine
163
200
164
201
If you're using [ Google App
165
202
Engine] ( https://cloud.google.com/appengine/docs/go/how-requests-are-handled#Go_Requests_and_HTTP ) ,
166
- which doesn't allow you to hook into the default ` http.ServeMux ` directly,
203
+ (first-generation) which doesn't allow you to hook into the default ` http.ServeMux ` directly,
167
204
you can still use gorilla/csrf (and gorilla/mux):
168
205
169
206
``` go
@@ -180,6 +217,10 @@ func init() {
180
217
}
181
218
```
182
219
220
+ Note: You can ignore this if you're using the
221
+ [ second-generation] ( https://cloud.google.com/appengine/docs/go/ ) Go runtime
222
+ on App Engine (Go 1.11 and above).
223
+
183
224
### Setting Options
184
225
185
226
What about providing your own error handler and changing the HTTP header the
0 commit comments