{"id":730,"date":"2020-06-08T16:23:44","date_gmt":"2020-06-08T20:23:44","guid":{"rendered":"http:\/\/bhoey.com\/blog\/?p=730"},"modified":"2020-06-08T16:23:45","modified_gmt":"2020-06-08T20:23:45","slug":"integrating-recaptcha-with-django-allauth","status":"publish","type":"post","link":"https:\/\/bhoey.com\/blog\/integrating-recaptcha-with-django-allauth\/","title":{"rendered":"Integrating ReCaptcha With Django-AllAuth"},"content":{"rendered":"<h3>Background<\/h3>\n<p><a href=\"https:\/\/django-allauth.readthedocs.io\">Django-allauth<\/a> is a popular user authentication add-on for Django. Its rich set of features and functionality provides most of the common end-user initiated tasks such as registration and subsequent account management. However with the modern internet not being all rainbows and unicorns, additional layers of security are necessary to safeguard your systems from abuse.<\/p>\n<p>Automated bots creating fake accounts are a persistent problem targeting any user self-registration systems and django-allauth is no exception. The most common approach to discourage these bots is to incorporate a <a href=\"https:\/\/en.wikipedia.org\/wiki\/CAPTCHA\">captcha<\/a> on your signup page that adds a layer of validation, with <a href=\"https:\/\/developers.google.com\/recaptcha\/\">Google's ReCaptcha<\/a> being the industry-standard implementation. Integrating recaptcha into django-allauth can be tricky so in this post I'll cover the steps to add a captcha to the django-auth signup page.<\/p>\n<h3>Software Versions<\/h3>\n<p>Main software and versions used:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.python.org\/3.8\/\">Python<\/a>: 3.8<\/li>\n<li><a href=\"https:\/\/docs.djangoproject.com\/en\/2.2\/\">Django<\/a>: 2.2<\/li>\n<li><a href=\"https:\/\/django-allauth.readthedocs.io\/\">django-allauth<\/a>: 0.41.0<\/li>\n<li><a href=\"https:\/\/pypi.org\/project\/django-recaptcha\/\">django-recaptcha<\/a>: 2.0.6<\/li>\n<\/ul>\n<h3>Obtain Google ReCaptcha Keys<\/h3>\n<p>The first step is to register your site in <a href=\"https:\/\/www.google.com\/recaptcha\/admin\">Google's ReCaptcha service<\/a>. You'll have the option to register for either V2 or V3 of recaptcha. V2 is the familiar 'select all traffic signals' type of challenges that we've all seen before, V3 is Google's newer style that doesn't interact directly with the user and instead operates in the background and provides a confidence score that you can use to filter out likely bots. For this post we will be using V2 with the 'I am not a robot' option.<\/p>\n<h3><a href=\"http:\/\/bhoey.com\/blog\/wp-content\/uploads\/2020\/06\/google-recaptcha.png\"><img loading=\"lazy\" class=\"aligncenter wp-image-753 size-medium\" src=\"http:\/\/bhoey.com\/blog\/wp-content\/uploads\/2020\/06\/google-recaptcha-e1591585056621-300x193.png\" alt=\"Google ReCaptcha Add Site\" width=\"300\" height=\"193\" srcset=\"https:\/\/bhoey.com\/blog\/wp-content\/uploads\/2020\/06\/google-recaptcha-e1591585056621-300x193.png 300w, https:\/\/bhoey.com\/blog\/wp-content\/uploads\/2020\/06\/google-recaptcha-e1591585056621-768x495.png 768w, https:\/\/bhoey.com\/blog\/wp-content\/uploads\/2020\/06\/google-recaptcha-e1591585056621.png 773w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/h3>\n<h3>Install django-recaptcha<\/h3>\n<p>Assuming you already have django-allauth installed, you will need to install django-recaptcha using you're preferred method (pip or in your IDE).<\/p>\n<h3>Code Changes<\/h3>\n<p><b>settings.py<\/b><br \/>\nWe add the recaptcha keys provided when registering the site to the app's settings.py file. Additionally we redirect the signup form class to a custom one that will include an addition field of type ReCaptchaField.<\/p>\n<pre class=\"brush: python; notranslate\">ACCOUNT_SIGNUP_FORM_CLASS = 'yourapp.forms.MyCustomSignupForm'\nRECAPTCHA_PUBLIC_KEY = '&lt;your recaptcha site key&gt;'\nRECAPTCHA_PRIVATE_KEY =  '&lt;your recaptcha secret ke&gt;'\n<\/pre>\n<p><b>forms.py<\/b><br \/>\nAnd here is that custom form, the widget and related attrs parameter are the default values, but they've been added here in case you'd like to change them.<\/p>\n<pre class=\"brush: python; notranslate\">from captcha.fields import ReCaptchaField\nfrom captcha.widgets import ReCaptchaV2Checkbox\n\n...\n\nclass MyCustomSignupForm(forms.Form):\n\n    captcha = ReCaptchaField(\n            widget=ReCaptchaV2Checkbox(\n                attrs={\n                        'data-theme': 'light',  # default=light\n                        'data-size': 'normal',  # default=normal\n                },\n            ),\n    )\n\n    def signup(self, request, user):\n        \"\"\" This function is required otherwise you will get an ImproperlyConfigured exception \"\"\"\n        pass\n\n<\/pre>\n<h3>Optional: Cleaning Up Form Display<\/h3>\n<p>Using the above method as-is will result in the captcha field showing up in the middle of the form which doesn't look right. One way around this is to override the default django-allauth signup page and then list each field in the desired order. Below are the changes that need to be made to implement this.<\/p>\n<p><b>yourapp\/account_signup.html<\/b><br \/>\nThis is the form that will override the default allauth signup template. Note: I've only included the form section here, it is assumed this file would have your normal template structure.<\/p>\n<pre class=\"brush: html; notranslate\">...\n\n&lt;form class=\"signup\" id=\"signup_form\" method=\"post\" action=\"\/accounts\/signup\/\"&gt;\n\n    {% csrf_token %}\n\n    &lt;div class=\"form-group\"&gt;\n            {{ form.email.errors }}\n            {{ form.email }}\n    &lt;\/div&gt;\n    &lt;div class=\"form-group\"&gt;\n            {{ form.username.errors }}\n            {{ form.username }}\n    &lt;\/div&gt;\n    &lt;div class=\"form-group\"&gt;\n            {{ form.password1.errors }}\n            {{ form.password1 }}\n    &lt;\/div&gt;\n    &lt;div class=\"form-group\"&gt;\n            {{ form.password2.errors }}\n            {{ form.password2 }}\n    &lt;\/div&gt;\n    &lt;div class=\"form-group\"&gt;\n            {{ form.captcha.errors }}\n            {{ form.captcha }}\n    &lt;\/div&gt;\n\n    &lt;button type=\"submit\"&gt;Sign Up&lt;\/button&gt;\n\n&lt;\/form&gt;\n\n...\n\n<\/pre>\n<p><b>views.py<\/b><br \/>\nBelow is a small class-based view to repoint the template to use for signups. It should be noted that you can also override default django-allauth pages by putting them in a particular directory structure under your project. However I prefer to make this explicit so as to not trip up someone reading it down the road who is unaware or forgets this mechanism (myself included!)<\/p>\n<pre class=\"brush: python; notranslate\">from allauth.account.views import SignupView\n\n...\n\nclass MySignupView(SignupView):\n    template_name = 'yourapp\/account_signup.html'\n\n<\/pre>\n<p><b>urls.py<\/b><br \/>\nFinally point the \/accounts\/signup to our custom view and template. The key thing to remember here is that this needs to be added above where allauth urls are included.<\/p>\n<pre class=\"brush: python; notranslate\">url(r'^accounts\/signup\/', v.MySignupView.as_view(), name='account_signup'),\n<\/pre>\n<h3>Final Thoughts<\/h3>\n<p>This example covered adding a V2 recaptcha to the django-allauth signup page to hamper the ability of bots to create fake users in your system. Using it as a reference you should be able to add the captcha to other pages with relative ease as you see fit. Keep in mind changing to use a V3 recaptcha or using other V2 modes will require adjustments to the instructions above. Good luck and happy coding!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Automated bots creating fake accounts are a persistent problem targeting any user self-registration systems and django-allauth is no exception. The most common approach to discourage these bots is to incorporate a captcha on your signup page that adds a layer of validation, with Google's ReCaptcha being the industry-standard implementation. Integrating recaptcha into django-allauth can be tricky so in this post I'll cover the steps to add a captcha to the django-auth signup page.&nbsp;<a href=\"https:\/\/bhoey.com\/blog\/integrating-recaptcha-with-django-allauth\/\">[Continue&nbsp;reading...] <span class=\"screen-reader-text\">Integrating ReCaptcha With Django-AllAuth<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":761,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[79,23],"tags":[80,81,82,84],"_links":{"self":[{"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/posts\/730"}],"collection":[{"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/comments?post=730"}],"version-history":[{"count":30,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/posts\/730\/revisions"}],"predecessor-version":[{"id":762,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/posts\/730\/revisions\/762"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/media\/761"}],"wp:attachment":[{"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/media?parent=730"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/categories?post=730"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bhoey.com\/blog\/wp-json\/wp\/v2\/tags?post=730"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}