Using Basic HTTP access authentication in Django testing framework
Question:
For some of my Django views I’ve created a decorator that performs Basic HTTP access authentication. However, while writing test cases in Django, it took me a while to work out how to authenticate to the view. Here’s how I did it. I hope somebody finds this useful.
Answers:
Here’s how I did it:
from django.test import Client
import base64
auth_headers = {
'HTTP_AUTHORIZATION': 'Basic ' + base64.b64encode('username:password'),
}
c = Client()
response = c.get('/my-protected-url/', **auth_headers)
Note: You will also need to create a user.
Assuming I have a login form, I use the following technique to login through the test framework:
client = Client()
client.post('/login/', {'username': 'john.smith', 'password': 'secret'})
I then carry the client
around in my other tests since it’s already authenticated. What is your question to this post?
In your Django TestCase you can update the client defaults to contain your HTTP basic auth credentials.
import base64
from django.test import TestCase
class TestMyStuff(TestCase):
def setUp(self):
credentials = base64.b64encode('username:password')
self.client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + credentials
Another way to do it is to bypass the Django Client() and use Requests instead.
class MyTest(TestCase):
def setUp(self):
AUTH = requests.auth.HTTPBasicAuth("username", "password")
def some_test(self):
resp = requests.get(BASE_URL + 'endpoint/', auth=AUTH)
self.assertEqual(resp.status_code, 200)
For python3, you can base64-encode your username:password
string:
base64.b64encode(b'username:password')
This returns bytes, so you need to transfer it into an ASCII string with .decode('ascii')
:
Complete example:
import base64
from django.test import TestCase
class TestClass(TestCase):
def test_authorized(self):
headers = {
'HTTP_AUTHORIZATION': 'Basic ' +
base64.b64encode(b'username:password').decode("ascii")
}
response = self.client.get('/', **headers)
self.assertEqual(response.status_code, 200)
(python3) I’m using this in a test:
credentials_string = '%s:%s' % ('invalid', 'invalid')
credentials = base64.b64encode(credentials_string.encode())
self.client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + credentials.decode()
and the following in a view:
import base64
[...]
type, auth = request.META['HTTP_AUTHORIZATION'].split(' ', 1)
auth = base64.b64decode(auth.strip()).decode()
For some of my Django views I’ve created a decorator that performs Basic HTTP access authentication. However, while writing test cases in Django, it took me a while to work out how to authenticate to the view. Here’s how I did it. I hope somebody finds this useful.
Here’s how I did it:
from django.test import Client
import base64
auth_headers = {
'HTTP_AUTHORIZATION': 'Basic ' + base64.b64encode('username:password'),
}
c = Client()
response = c.get('/my-protected-url/', **auth_headers)
Note: You will also need to create a user.
Assuming I have a login form, I use the following technique to login through the test framework:
client = Client()
client.post('/login/', {'username': 'john.smith', 'password': 'secret'})
I then carry the client
around in my other tests since it’s already authenticated. What is your question to this post?
In your Django TestCase you can update the client defaults to contain your HTTP basic auth credentials.
import base64
from django.test import TestCase
class TestMyStuff(TestCase):
def setUp(self):
credentials = base64.b64encode('username:password')
self.client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + credentials
Another way to do it is to bypass the Django Client() and use Requests instead.
class MyTest(TestCase):
def setUp(self):
AUTH = requests.auth.HTTPBasicAuth("username", "password")
def some_test(self):
resp = requests.get(BASE_URL + 'endpoint/', auth=AUTH)
self.assertEqual(resp.status_code, 200)
For python3, you can base64-encode your username:password
string:
base64.b64encode(b'username:password')
This returns bytes, so you need to transfer it into an ASCII string with .decode('ascii')
:
Complete example:
import base64
from django.test import TestCase
class TestClass(TestCase):
def test_authorized(self):
headers = {
'HTTP_AUTHORIZATION': 'Basic ' +
base64.b64encode(b'username:password').decode("ascii")
}
response = self.client.get('/', **headers)
self.assertEqual(response.status_code, 200)
(python3) I’m using this in a test:
credentials_string = '%s:%s' % ('invalid', 'invalid')
credentials = base64.b64encode(credentials_string.encode())
self.client.defaults['HTTP_AUTHORIZATION'] = 'Basic ' + credentials.decode()
and the following in a view:
import base64
[...]
type, auth = request.META['HTTP_AUTHORIZATION'].split(' ', 1)
auth = base64.b64decode(auth.strip()).decode()