Wandering Thoughts archives

2022-01-27

Django and Apache HTTP Basic Authentication (and REMOTE_USER)

We have a Django application, and part of it exists behind Apache HTTP Basic Authentication. For reasons beyond the scope of this entry, I was recently rediscovering some things about how Django interacts with Apache HTTP Basic Authentication, and so I want to write them down for myself before I forget them again.

First, the starting point in the Django documentation for this is not to search for 'HTTP Basic Authentication' or anything like that, but for the howto on authenticating with REMOTE_USER, which is the environment variable that Apache injects when it's already authenticated something. I believe that if you search for 'Django' with 'Basic Authentication' on search engines, you tend to get information about making Django or Django-related things actually perform the server side of HTTP Basic authentication itself. This is fair enough but can be confusing.

Second, you only need to configure Django itself to authenticate with REMOTE_USER if you want to use Django's own authentication for something, such as access and authorization in its admin site. It's perfectly valid (although potentially annoying) to authenticate and limit access to your Django site (or parts of it) in your Apache configuration with Apache's HTTP Basic Authentication but have a separate Django login step to access the Django admin site or even parts of your application (which will then be tracked with cookies and so on). If you want to do this, you don't want to add Django's RemoteUserMiddleware and so on into your Django settings.

(You'll have to manage Apache users and Django users separately, passwords included, and they won't be the same thing. This might wind up being confusing.)

If you do have Django authenticating with REMOTE_USER, you need your Django database superuser to be something you can authenticate with through Apache. If you cleverly set your database superuser to 'admin' but you have no 'admin' in your Basic Auth database, you will be sad. It's possible to get yourself out of this in a couple of ways, but it's better to avoid it in the first place.

(When you do have Django authenticating this way, ever person who uses your Django app through HTTP Basic Authentication will wind up with an entry in the Django 'User' table. Purging old logins that no longer exist is up to you, if you care. For people who you want to be able to use the Django admin site, you need to set them as at least 'Staff' in the Django User table. You can set them as database superusers too.)

It's not necessary to use Django's REMOTE_USER support in order to make use of the authentication information yourself, as long as Apache has HTTP Basic Authentication active. You can retrieve the login name from the $REMOTE_USER environment variable and look it up in your own 'User' table by hand, as we do. You may or may not want to automatically create new entries for new users, the way Django does by default. We don't because new people require some additional configuration on our side.

The corollary to this is that you can use and test your entire site under Apache HTTP Basic Authentication without having Django properly wired up to use REMOTE_USER, without noticing. I believe that this potentially actually matters, because I believe that Django does some things with sessions differently when you have the RemoteUser* things enabled, and this interacts with Django's CSRF protections. Which we've had mysterious problems with (also).

DjangoApacheBasicAuth written at 00:40:55;


Page tools: See As Normal.
Search:
Login: Password:

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.