Using reCAPTCHA v3 with Django
reCAPTCHA is a system to prevent spam and abuse of web services. It's easy to integrate with Django. There are three steps to using v3 reCAPTCHA in your web app:
- Create the reCAPTCHA application
- Integrate with your frontend
- Validate the response from Google
Create the reCAPTCHA application
First, register a new reCAPTCHA application at https://www.google.com/recaptcha/admin:
Copy the value in the Secret Key box. Put this in your Django settings:
GOOGLE_RECAPTCHA_SECRET_KEY = <secret_key>
You probably don't want to hardcode the value in your settings.py
. You can
store it in a separate config file, and read it in via configparser
.
Integrate with your frontend
In the "Client side integration" section of the reCAPTCHA admin page, copy the first snippet:
<script src='https://www.google.com/recaptcha/api.js?render=<YOUR_SITE_KEY>'></script>
Copy the one from your admin page, not the snippet above. Or replace <YOUR_SITE_KEY>
with your actual site key.
Put that tag in your template's <head>
tag.
Copy the second snippet from the reCAPTCHA admin page:
<script>
grecaptcha.ready(function() {
grecaptcha.execute('<YOUR_SITE_KEY>', {action: '<ACTION_NAME>'})
.then(function(token) {
<RESPONSE_ACTION>
});
});
</script>
Put that in the <body>
tag of the page you want to use reCAPTCHA on. You'll
need to replace <YOUR_SITE_KEY>
with your actual site key. The version on
your reCAPTCHA admin page should already have it. You also need to replace
<ACTION_NAME>
with an appropriate value - if you are using it to validate
user signups, you could use signup
for example.
The next step is to replace <RESPONSE_ACTION>
with some javascript. If you
are using reCAPTCHA to protect form submissions, you might have this form on the
same page:
<form method="post" id="form">
<input type="email" name="email">
<button type="submit">Sign up</button>
</div>
</form>
Google will return a token
to the client. That token needs to be passed to
your server for validation. You can do that like this:
<script>
grecaptcha.ready(function() {
grecaptcha.execute('<YOUR_SITE_KEY>', {action: '<ACTION_NAME>'})
.then(function(token) {
document.getElementById("form").appendChild(document.CreateElement(`<input type="hidden" name="g-recaptcha-response" value=${token}`);
});
});
</script>
The form will now contain an extra item named g-recaptcha-response
on submission.
Validate the response from Google
In the view that processes your form, you need to separately verify the submitted token is valid. If you are using a class-based view:
def form_valid(self, form):
# get the token submitted in the form
recaptcha_response = self.request.POST.get('g-recaptcha-response')
url = 'https://www.google.com/recaptcha/api/siteverify'
payload = {
'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY,
'response': recaptcha_response
}
data = urllib.parse.urlencode(payload).encode()
req = urllib.request.Request(url, data=data)
# verify the token submitted with the form is valid
response = urllib.request.urlopen(req)
result = json.loads(response.read().decode())
# result will be a dict containing 'success' and 'action'.
# it is important to verify both
if (not result['success']) or (not result['action'] == 'signup'): # make sure action matches the one from your template
messages.error(self.request, 'Invalid reCAPTCHA. Please try again.')
return super().form_invalid(form)
<finish your form processing...>
That's it! Now you have integrated reCAPTCHA with your Django app.
This post was written using Python 3.7.0 and Django 2.1.4.