Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enable https in Django-auth generated pages?

Using the Django-auth application (Django version 1.3), I want to have my login page go to https://mysite.com/login/. Currently, I'm using:

# urls.py
from django.contrib.auth.views import login
urlpatterns = patterns('', url(r'^login/$', login, name='login-view'),)

# navbar.html
<li id="nav-login"><a href="{% url login-view %}" ><b>Login</b></a></li>

which works nicely, but goes to http://mysite.com/login/.

Is there some way to tell Django-auth what prefix (https) to use, when it reverses the view name? I've read the entire manual page, and haven't found anything that covers it. Or maybe some way to tell the url tag to go to https?

Or is the only option to specify the entire URL manually? I hope not :) And given how powerful Django has been so far, I can't believe it wouldn't have that ability - I must be overlooking it. :)

like image 613
John C Avatar asked Nov 04 '11 21:11

John C


People also ask

Does Django use HTTPS?

Serving a HTTPS only Django Application is very important to secure your users data. If your application have user authentication it is already a good reason to start using HTTPS only. Otherwise usernames and passwords will be exposed traveling over HTTP in plain text.


2 Answers

Set OS environmental variable HTTPS to on

You need to enable the OS environmental variable HTTPS to 'on' so django will prepend https to fully generated links (e.g., like with HttpRedirectRequests). If you are using mod_wsgi, you can add the line:

os.environ['HTTPS'] = "on"

to your wsgi script. You can see the need for this by reading django/http/__init__.py:

def build_absolute_uri(self, location=None):
    """
    Builds an absolute URI from the location and the variables available in
    this request. If no location is specified, the absolute URI is built on
    ``request.get_full_path()``.
    """
    if not location:
        location = self.get_full_path()
    if not absolute_http_url_re.match(location):
        current_uri = '%s://%s%s' % (self.is_secure() and 'https' or 'http',
                                     self.get_host(), self.path)
        location = urljoin(current_uri, location)
    return iri_to_uri(location)

def is_secure(self):
    return os.environ.get("HTTPS") == "on"

Secure your cookies

In settings.py put the lines

SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

and cookies will only be sent via HTTPS connections. Additionally, you probably also want SESSION_EXPIRE_AT_BROWSER_CLOSE=True. Note if you are using older versions of django (less than 1.4), there isn't a setting for secure CSRF cookies. As a quick fix, you can just have CSRF cookie be secure when the session cookie is secure (SESSION_COOKIE_SECURE=True), by editing django/middleware/csrf.py:

class CsrfViewMiddleware(object):
   ...
   def process_response(self, request, response):
       ...
       response.set_cookie(settings.CSRF_COOKIE_NAME,
            request.META["CSRF_COOKIE"], max_age = 60 * 60 * 24 * 7 * 52,
            domain=settings.CSRF_COOKIE_DOMAIN,
            secure=settings.SESSION_COOKIE_SECURE or None)

Direct HTTP requests to HTTPS in the webserver

Next you want a rewrite rule that redirects http requests to https, e.g., in nginx

server {
   listen 80;
   rewrite ^(.*) https://$host$1 permanent;
}

Django's reverse function and url template tags only return relative links; so if you are on an https page your links will keep you on the https site.

like image 165
dr jimbob Avatar answered Sep 30 '22 20:09

dr jimbob


As seen in other StackOverflow questions, you could implement middleware that would automatically redirect the login page to a secure version.

If you are really serious about security, you should probably migrate the entire website to SSL. From the EFF's How to Deploy HTTPS Correctly:

You must serve the entire application domain over HTTPS. Redirect HTTP requests with HTTP 301 or 302 responses to the equivalent HTTPS resource.

Some site operators provide only the login page over HTTPS, on the theory that only the user’s password is sensitive. These sites’ users are vulnerable to passive and active attack.

like image 35
Martey Avatar answered Sep 30 '22 20:09

Martey