Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django allauth not sending links with https

I want Django Allauth to send links like the confirm e-mail or reset password with https:

Something like this:

https://example.com/ca/accounts/confirm-email/picuwfpjpptjswi50x5zb4gtsqptmwkscea445kadnbsfwcyij3fdnblery4onuq/

According to the official documentation only changing the following setting in settings.py it should work:

ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https"

But I keep getting the links with http instead of https like this:

http://example.com/ca/accounts/confirm-email/picuwfpjpptjswi50x5zb4gtsqptmwkscea445kadnbsfwcyij3fdnblery4onuq/

Am I missing something? Thank you!

like image 279
ferrangb Avatar asked Sep 13 '14 15:09

ferrangb


2 Answers

Digging into the code a little bit, you can see that allauth sets the activate_url template context variable using Django's build in build_absolute_uri method:

https://github.com/pennersr/django-allauth/blob/master/allauth/account/models.py#L119

...
activate_url = reverse("account_confirm_email", args=[self.key])
activate_url = request.build_absolute_uri(activate_url)
ctx = {
"activate_url": activate_url,
...
}

Looking at the code for the build_absolute_uri you can see it requires a environment variable:

https://github.com/django/django/blob/master/django/http/request.py#L153

def _get_scheme(self):
    return 'https' if os.environ.get("HTTPS") == "on" else 'http'

to return https:// in URLs generated by this function, you need to set a HTTPS environment variable.

It depends on how you have set up your project, but you can set the environment variable in your settings.py or manage.py

The following is a good post on general Django security when it comes to SSL:

  • https://security.stackexchange.com/questions/8964/trying-to-make-a-django-based-site-use-https-only-not-sure-if-its-secure

EDIT

Strangely, the reset password template uses a different approach to constructing the URL:

https://github.com/pennersr/django-allauth/blob/master/allauth/account/forms.py#L428

url = '%s://%s%s' % (app_settings.DEFAULT_HTTP_PROTOCOL,
    current_site.domain,
    path)
context = {"site": current_site,
    "user": user,
    "password_reset_url": url}

using the DEFAULT_HTTP_PROTOCOL settings instead

like image 57
Timmy O'Mahony Avatar answered Oct 05 '22 23:10

Timmy O'Mahony


Besides setting the "HTTPS" environment variable and SECURE_PROXY_SSL_HEADER SECURE_SSL_REDIRECT, also seems that can be problem when rendering template and sending mail with EmailMultiAlternatives() when .txt body is used as is in adapter.py render_mail() [1]: https://github.com/pennersr/django-allauth/blob/master/allauth/account/adapter.py

for ext in ["html", "txt"]:
        try:
            template_name = "{0}_message.{1}".format(template_prefix, ext)
            bodies[ext] = render_to_string(
                template_name,
                context,
                self.request,
            ).strip()
        except TemplateDoesNotExist:
            if ext == "txt" and not bodies:
                # We need at least one body
                raise
    if "txt" in bodies:
        msg = EmailMultiAlternatives(subject, bodies["txt"], from_email, to)
        if "html" in bodies:
            msg.attach_alternative(bodies["html"], "text/html")
    else:
        msg = EmailMessage(subject, bodies["html"], from_email, to)
        msg.content_subtype = "html"  # Main content is now text/html
    return msg

For example print(bodies[ext]) gave:

  "To confirm this is correct, go to " https://127.0.0.1:8000/accounts/confirm-email/MjI:1kS0Mj:M5YfUf9-1Vg_TlgjVrK6vAtaLDE/ "

but on email is still http://

 http://url7514.sitename/ls/click?upn=HJL2SSWV...

With most devices also this worked since should be redirected still to https://, but on some didn't, so had to change in default templates/account/email/email_confirmation_message.txt to html extension, after result :

To confirm this is correct, go to https://sitename/accounts/confirm-email/M...

like image 43
zoran Avatar answered Oct 05 '22 23:10

zoran