-
Notifications
You must be signed in to change notification settings - Fork 378
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: endpoint for imapd to authenticate against (#5295)
* feat: endpoint for imapd to authenticate against * chore: remove unintended whitespace * fix: be stricter in matching User
- Loading branch information
Showing
4 changed files
with
154 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Copyright The IETF Trust 2023, All Rights Reserved | ||
|
||
# This is not utils.py because Tastypie implicitly consumes ietf.api.utils. | ||
# See ietf.api.__init__.py for details. | ||
|
||
from django.conf import settings | ||
|
||
def is_valid_token(endpoint, token): | ||
# This is where we would consider integration with vault | ||
# Settings implementation for now. | ||
if hasattr(settings, "APP_API_TOKENS"): | ||
token_store = settings.APP_API_TOKENS | ||
if endpoint in token_store and token in token_store[endpoint]: | ||
return True | ||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ | |
from django.apps import apps | ||
from django.conf import settings | ||
from django.test import Client | ||
from django.test.utils import override_settings | ||
from django.urls import reverse as urlreverse | ||
from django.utils import timezone | ||
|
||
|
@@ -530,6 +531,101 @@ def test_api_appauth(self): | |
jsondata = r.json() | ||
self.assertEqual(jsondata['success'], True) | ||
|
||
class DirectAuthApiTests(TestCase): | ||
|
||
def setUp(self): | ||
super().setUp() | ||
self.valid_token = "nSZJDerbau6WZwbEAYuQ" | ||
self.invalid_token = self.valid_token | ||
while self.invalid_token == self.valid_token: | ||
self.invalid_token = User.objects.make_random_password(20) | ||
self.url = urlreverse("ietf.api.views.directauth") | ||
self.valid_person = PersonFactory() | ||
self.valid_password = self.valid_person.user.username+"+password" | ||
self.invalid_password = self.valid_password | ||
while self.invalid_password == self.valid_password: | ||
self.invalid_password = User.objects.make_random_password(20) | ||
|
||
self.valid_body_with_good_password = self.post_dict(authtoken=self.valid_token, username=self.valid_person.user.username, password=self.valid_password) | ||
self.valid_body_with_bad_password = self.post_dict(authtoken=self.valid_token, username=self.valid_person.user.username, password=self.invalid_password) | ||
self.valid_body_with_unknown_user = self.post_dict(authtoken=self.valid_token, username="[email protected]", password=self.valid_password) | ||
|
||
def post_dict(self, authtoken, username, password): | ||
data = dict() | ||
if authtoken is not None: | ||
data["authtoken"] = authtoken | ||
if username is not None: | ||
data["username"] = username | ||
if password is not None: | ||
data["password"] = password | ||
return dict(data = json.dumps(data)) | ||
|
||
def response_data(self, response): | ||
try: | ||
data = json.loads(response.content) | ||
except json.decoder.JSONDecodeError: | ||
data = None | ||
self.assertIsNotNone(data) | ||
return data | ||
|
||
def test_bad_methods(self): | ||
for method in (self.client.get, self.client.put, self.client.head, self.client.delete, self.client.patch): | ||
r = method(self.url) | ||
self.assertEqual(r.status_code, 405) | ||
|
||
def test_bad_post(self): | ||
for bad in [ | ||
self.post_dict(authtoken=None, username=self.valid_person.user.username, password=self.valid_password), | ||
self.post_dict(authtoken=self.valid_token, username=None, password=self.valid_password), | ||
self.post_dict(authtoken=self.valid_token, username=self.valid_person.user.username, password=None), | ||
self.post_dict(authtoken=None, username=None, password=self.valid_password), | ||
self.post_dict(authtoken=self.valid_token, username=None, password=None), | ||
self.post_dict(authtoken=None, username=self.valid_person.user.username, password=None), | ||
self.post_dict(authtoken=None, username=None, password=None), | ||
]: | ||
r = self.client.post(self.url, bad) | ||
self.assertEqual(r.status_code, 200) | ||
data = self.response_data(r) | ||
self.assertEqual(data["result"], "failure") | ||
self.assertEqual(data["reason"], "invalid post") | ||
|
||
bad = dict(authtoken=self.valid_token, username=self.valid_person.user.username, password=self.valid_password) | ||
r = self.client.post(self.url, bad) | ||
self.assertEqual(r.status_code, 200) | ||
data = self.response_data(r) | ||
self.assertEqual(data["result"], "failure") | ||
self.assertEqual(data["reason"], "invalid post") | ||
|
||
def test_notokenstore(self): | ||
self.assertFalse(hasattr(settings, "APP_API_TOKENS")) | ||
r = self.client.post(self.url,self.valid_body_with_good_password) | ||
self.assertEqual(r.status_code, 200) | ||
data = self.response_data(r) | ||
self.assertEqual(data["result"], "failure") | ||
self.assertEqual(data["reason"], "invalid authtoken") | ||
|
||
@override_settings(APP_API_TOKENS={"ietf.api.views.directauth":"nSZJDerbau6WZwbEAYuQ"}) | ||
def test_bad_username(self): | ||
r = self.client.post(self.url, self.valid_body_with_unknown_user) | ||
self.assertEqual(r.status_code, 200) | ||
data = self.response_data(r) | ||
self.assertEqual(data["result"], "failure") | ||
self.assertEqual(data["reason"], "authentication failed") | ||
|
||
@override_settings(APP_API_TOKENS={"ietf.api.views.directauth":"nSZJDerbau6WZwbEAYuQ"}) | ||
def test_bad_password(self): | ||
r = self.client.post(self.url, self.valid_body_with_bad_password) | ||
self.assertEqual(r.status_code, 200) | ||
data = self.response_data(r) | ||
self.assertEqual(data["result"], "failure") | ||
self.assertEqual(data["reason"], "authentication failed") | ||
|
||
@override_settings(APP_API_TOKENS={"ietf.api.views.directauth":"nSZJDerbau6WZwbEAYuQ"}) | ||
def test_good_password(self): | ||
r = self.client.post(self.url, self.valid_body_with_good_password) | ||
self.assertEqual(r.status_code, 200) | ||
data = self.response_data(r) | ||
self.assertEqual(data["result"], "success") | ||
|
||
class TastypieApiTestCase(ResourceTestCaseMixin, TestCase): | ||
def __init__(self, *args, **kwargs): | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters