I found a solution myself. Please feel free to post any alternative solutions. One that doesn't require two separate requests would be particularly great.
If you look at the password_reset method, you can see that it only tries to process the request as a reset request if the request method is POST. Otherwise it just returns a TemplateResponse
containing a form. This also contains the CSRF token as a cookie.
So first, I send a GET request to http://myaddress.com/user/password/reset/
and extract the CSRF cookie from the response. Then I send a POST request containing the cookie, the email address and 2 headers (see below).
This is the code I've implemented to achieve this from Android
(trimmed):
String url = "http://myaddress.com/user/password/reset/";
GET Request:
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
CookieStore cookieStore = new BasicCookieStore();
HttpContext localContext = new BasicHttpContext();
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
HttpResponse httpResponse = httpClient.execute(httpGet, localContext);
Cookie csrfCookie = null;
for (Cookie cookie : cookieStore.getCookies()) {
if (cookie.getName() == "csrftoken") {
csrfCookie = cookie;
break;
}
}
if (csrfCookie == null) {
throw new NullPointerException("CSRF cookie not found!");
}
return csrfCookie;
Note that you want the CookieStore
from org.apache.http.client
.
POST Request:
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
// Prepare the cookie store to receive cookies.
CookieStore cookieStore = new BasicCookieStore();
cookieStore.addCookie(csrfCookie);
httpPost.setHeader("Referer", url);
httpPost.setHeader("X-CSRFToken", csrfCookie.getValue());
localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addTextBody("email", emailAddressToReset);
httpPost.setEntity(builder.build());
HttpResponse httpResponse = httpClient.execute(httpPost, localContext);
if (httpResponse.getStatusLine().getStatusCode() != 200) {
throw new Exception("Could not reset password!");
}
Toast.makeText(context, "Password reset requested! Please check your email inbox!", Toast.LENGTH_LONG).show();