diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f061f9e8..43791050 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,3 +1,9 @@ +###### +2.2.2 +###### +- Bugfix: invalid token length does no longer trigger a server error +- Extending documentation + ###### 2.2.1 ###### diff --git a/docs/auth.md b/docs/auth.md index 55f64290..b404b453 100644 --- a/docs/auth.md +++ b/docs/auth.md @@ -39,3 +39,33 @@ Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b9836F45E23A345 ``` Tokens expire after a preset time. See settings. + + +### Global usage on all views + +You can activate TokenAuthentication on all your views by adding it to +`REST_FRAMEWORK["DEFAULT_AUTHENTICATION_CLASSES"]`. If it is your only +authentication class remember to overwrite the login view and url as at least +the token-obtaining view may not require a token: + +```python + +views.py: + +from knox.views import LoginView as KnoxLoginView +from rest_framework.authentication import BasicAuthentication + +class LoginView(KnoxLoginView): + authentication_classes = [BasicAuthentication] + +urls.py: + +from knox import views as knox_views +from yourapp.api.views import LoginView + +urlpatterns = [ + url(r'login/', LoginView.as_view(), name='knox_login'), + url(r'logout/', knox_views.LogoutView.as_view(), name='knox_logout'), + url(r'logoutall/', knox_views.LogoutAllView.as_view(), +] +``` diff --git a/docs/changes.md b/docs/changes.md index 5e97f6c2..2d34ea65 100644 --- a/docs/changes.md +++ b/docs/changes.md @@ -1,5 +1,17 @@ #Changelog +## 2.2.2 +- Bugfix: invalid token length does no longer trigger a server error +- Extending documentation + +## 2.2.1 +**Please be aware: updating to his version requires applying a database migration** + +- Introducing token_key to avoid loop over all tokens on login-requests +- Signals are sent on login/logout +- Test for invalid token length +- Cleanup in code and documentation + ## 2.0.0 - Hashing of tokens on the server introduced. - Updating to this version will clean the AuthToken table. In real terms, this diff --git a/docs/settings.md b/docs/settings.md index 944e19cf..ce1586e3 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -32,7 +32,7 @@ for production use. ### Tests SHA-512 and Whirlpool are secure, however, they are slow. This should not be a problem for your users, but when testing it may be noticable (as test cases tend -to use many more requests much more quickly than real users). In testing scenrios +to use many more requests much more quickly than real users). In testing scenarios it is acceptable to use `MD5` hashing.(`cryptography.hazmat.primitives.hashes.MD5`) MD5 is **not secure** and must *never* be used in production sites. diff --git a/knox/auth.py b/knox/auth.py index c6526234..301feb5e 100644 --- a/knox/auth.py +++ b/knox/auth.py @@ -56,16 +56,20 @@ def authenticate_credentials(self, token): Tokens that have expired will be deleted and skipped ''' + msg = _('Invalid token.') for auth_token in AuthToken.objects.all(): if auth_token.expires is not None: if auth_token.expires < timezone.now(): auth_token.delete() continue - digest = hash_token(token, auth_token.salt) + try: + digest = hash_token(token, auth_token.salt) + except TypeError: + raise exceptions.AuthenticationFailed(msg) if digest == auth_token.digest: return self.validate_user(auth_token) # Authentication with this token has failed - raise exceptions.AuthenticationFailed(_('Invalid token.')) + raise exceptions.AuthenticationFailed(msg) def validate_user(self, auth_token): if not auth_token.user.is_active: diff --git a/setup.py b/setup.py index a102da00..9c49bb6a 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ # Versions should comply with PEP440. For a discussion on single-sourcing # the version across setup.py and the project code, see # https://packaging.python.org/en/latest/single_source_version.html - version='2.2.1', + version='2.2.2', description='Authentication for django rest framework', long_description=long_description, diff --git a/tests/tests.py b/tests/tests.py index ea6f2dcd..68cc1d4f 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -94,11 +94,3 @@ def test_update_token_key(self): self.assertEqual( token[:CONSTANTS.TOKEN_KEY_LENGTH], auth_token.token_key) - - def test_invalid_token_length_returns_401_code(self): - invalid_token = "1" * (CONSTANTS.TOKEN_KEY_LENGTH - 1) - url = reverse('api-root') - self.client.credentials(HTTP_AUTHORIZATION=('Token %s' % invalid_token)) - response = self.client.post(url, {}, format='json') - self.assertEqual(response.status_code, 401) - self.assertEqual(response.data, {"detail": "Invalid token."})