Skip to content

Commit

Permalink
Merge branch 'develop' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
johnraz authored May 2, 2024
2 parents 238b1ea + 3dc5ba3 commit 44a0296
Show file tree
Hide file tree
Showing 26 changed files with 351 additions and 141 deletions.
11 changes: 11 additions & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
coverage:
status:
project:
default: false
tests:
paths: tests
informational: true
knox:
paths: knox
informational: true
patch: off
5 changes: 5 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[run]
branch = True
source = knox
omit =
*/migrations/*
18 changes: 12 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ jobs:
fail-fast: false
max-parallel: 5
matrix:
python-version: ['3.6', '3.7', '3.8', '3.9', '3.10']
python-version: ['3.6', '3.7', '3.8', '3.9', '3.10', '3.11', '3.12']

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Get pip cache dir
id: pip-cache
run: |
echo "::set-output name=dir::$(pip cache dir)"
echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT
- name: Cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ${{ steps.pip-cache.outputs.dir }}
key:
Expand All @@ -36,8 +36,14 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --upgrade tox tox-gh-actions
python -m pip install --upgrade tox tox-gh-actions coverage
- name: Tox tests
run: |
tox -v
- name: Generate coverage XML report
run: coverage xml

- name: Codecov
uses: codecov/codecov-action@v3
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,6 @@ docs/_build/
target/
db.sqlite3
site/

# PyCharm Project
.idea
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
repos:
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/PyCQA/flake8
rev: 7.0.0
hooks:
- id: flake8
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## 4.2.0
- compatibility with Python up to 3.10 and Django up to 3.2
- compatibility with Python up to 3.10 and Django up to 4.0
- integration with github CI instead of travis
- Migration: "salt" field of model "AuthToken" is removed
- Migration: "salt" field of model "AuthToken" is removed, WARNING: invalidates old tokens!

## 4.1.0

Expand Down
3 changes: 3 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[![Jazzband](https://jazzband.co/static/img/jazzband.svg)](https://jazzband.co/)

This is a [Jazzband](https://jazzband.co/) project. By contributing you agree to abide by the [Contributor Code of Conduct](https://jazzband.co/about/conduct) and follow the [guidelines](https://jazzband.co/about/guidelines).
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
django-rest-knox
================

[![image](https://github.com/James1345/django-rest-knox/workflows/Test/badge.svg?branch=develop)](https://github.com/James1345/django-rest-knox/actions)
[![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/)
[![image](https://github.com/jazzband/django-rest-knox/workflows/Test/badge.svg?branch=develop)](https://github.com/jazzband/django-rest-knox/actions)

Authentication Module for django rest auth
Authentication module for Django rest auth.

Knox provides easy to use authentication for [Django REST
Knox provides easy-to-use authentication for [Django REST
Framework](https://www.django-rest-framework.org/) The aim is to allow
for common patterns in applications that are REST based, with little
for common patterns in applications that are REST-based, with little
extra effort; and to ensure that connections remain secure.

Knox authentication is token based, similar to the `TokenAuthentication`
built in to DRF. However, it overcomes some problems present in the
Knox authentication is token-based, similar to the `TokenAuthentication`
built into DRF. However, it overcomes some problems present in the
default implementation:

- DRF tokens are limited to one per user. This does not facilitate
Expand All @@ -23,13 +24,14 @@ default implementation:
client to have its own token which is deleted on the server side
when the client logs out.

Knox also provides an option for a logged in client to remove *all*
Knox also provides an option for a logged-in client to remove *all*
tokens that the server has - forcing all clients to re-authenticate.

- DRF tokens are stored unencrypted in the database. This would allow
an attacker unrestricted access to an account with a token if the
an attacker unrestricted access to an account with a token if the
database were compromised.


Knox tokens are only stored in a secure hash form (like a password). Even if the
database were somehow stolen, an attacker would not be able to log
in with the stolen credentials.
Expand All @@ -39,12 +41,11 @@ default implementation:
the app settings (default is 10 hours.)

More information can be found in the
[Documentation](https://james1345.github.io/django-rest-knox/)
[Documentation](https://jazzband.github.io/django-rest-knox/)

# Run the tests locally

If you need to debug a test locally and if you have [docker](https://www.docker.com/) installed:

If you need to debug a test locally and if you have [docker](https://www.docker.com/) installed,
simply run the ``./docker-run-tests.sh`` script and it will run the test suite in every Python /
Django versions.

Expand All @@ -55,7 +56,7 @@ Python / Django versions a bit more tricky.

Our documentation is generated by [Mkdocs](https://www.mkdocs.org).

You can refer to their documentation on how to install it locally.
You can refer to their [documentation](https://www.mkdocs.org/user-guide/installation/) on how to install it locally.

Another option is to use `mkdocs.sh` in this repository.
It will run mkdocs in a [docker](https://www.docker.com/) container.
Expand Down
18 changes: 8 additions & 10 deletions docs/auth.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,17 @@ If it is your only default authentication class, remember to overwrite knox's Lo

For instance, you can authenticate users using Basic Authentication by simply overwriting knox's LoginView and setting BasicAuthentication as one of the acceptable authentication classes, as follows:

**views.py:**
```python

views.py:

from knox.views import LoginView as KnoxLoginView
from rest_framework.authentication import BasicAuthentication

class LoginView(KnoxLoginView):
authentication_classes = [BasicAuthentication]
```

urls.py:

**urls.py:**
```python
from knox import views as knox_views
from yourapp.api.views import LoginView

Expand All @@ -75,10 +74,8 @@ You can use any number of authentication classes if you want to be able to authe

If you decide to use Token Authentication as your only authentication class, you can overwrite knox's login view as such:

**views.py:**
```python

views.py:

from django.contrib.auth import login

from rest_framework import permissions
Expand All @@ -94,9 +91,10 @@ class LoginView(KnoxLoginView):
user = serializer.validated_data['user']
login(request, user)
return super(LoginView, self).post(request, format=None)
```

urls.py:

**urls.py:**
```python
from knox import views as knox_views
from yourapp.api.views import LoginView

Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Django-Rest-Knox
Knox provides easy to use authentication for [Django REST Framework](https://www.django-rest-framework.org/)
Knox provides easy-to-use authentication for [Django REST Framework](https://www.django-rest-framework.org/)
The aim is to allow for common patterns in applications that are REST based,
with little extra effort; and to ensure that connections remain secure.

Knox authentication is token based, similar to the `TokenAuthentication` built
in to DRF. However, it overcomes some problems present in the default implementation:
into DRF. However, it overcomes some problems present in the default implementation:

- DRF tokens are limited to one per user. This does not facilitate securely
signing in from multiple devices, as the token is shared. It also requires
Expand Down
25 changes: 3 additions & 22 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,8 @@

## Requirements

Knox depends on `cryptography` to provide bindings to `OpenSSL` for token generation.
This requires the OpenSSL build libraries to be available.

### Windows
Cryptography is a statically linked build, no extra steps are needed.

### Linux
`cryptography` should build very easily on Linux provided you have a C compiler,
headers for Python (if you’re not using `pypy`), and headers for the OpenSSL and
`libffi` libraries available on your system.

Debian and Ubuntu:
```bash
sudo apt-get install build-essential libssl-dev libffi-dev python3-dev python-dev
```

Fedora and RHEL-derivatives:
```bash
sudo yum install gcc libffi-devel python-devel openssl-devel
```
For other systems or problems, see the [cryptography installation docs](https://cryptography.io/en/latest/installation/)
Knox depends on pythons internal library `hashlib` to provide bindings to `OpenSSL` or uses
an internal implementation of hashing algorithms for token generation.

## Installing Knox
Knox should be installed with pip
Expand Down Expand Up @@ -59,7 +40,7 @@ REST_FRAMEWORK = {

- If you set TokenAuthentication as the only default authentication class on the second step, [override knox's LoginView](auth.md#global-usage-on-all-views) to accept another authentication method and use it instead of knox's default login view.

- Apply the migrations for the models
- Apply the migrations for the models.

```bash
python manage.py migrate
Expand Down
33 changes: 27 additions & 6 deletions docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,27 @@ Example `settings.py`
# These are the default values if none are set
from datetime import timedelta
from rest_framework.settings import api_settings

KNOX_TOKEN_MODEL = 'knox.AuthToken'

REST_KNOX = {
'SECURE_HASH_ALGORITHM': 'cryptography.hazmat.primitives.hashes.SHA512',
'SECURE_HASH_ALGORITHM': 'hashlib.sha512',
'AUTH_TOKEN_CHARACTER_LENGTH': 64,
'TOKEN_TTL': timedelta(hours=10),
'USER_SERIALIZER': 'knox.serializers.UserSerializer',
'TOKEN_LIMIT_PER_USER': None,
'AUTO_REFRESH': False,
'MIN_REFRESH_INTERVAL': 60,
'AUTH_HEADER_PREFIX': 'Token',
'EXPIRY_DATETIME_FORMAT': api_settings.DATETIME_FORMAT,
'TOKEN_MODEL': 'knox.AuthToken',
}
#...snip...
```

## KNOX_TOKEN_MODEL
This is the variable used in the swappable dependency of the `AuthToken` model

## SECURE_HASH_ALGORITHM
This is a reference to the class used to provide the hashing algorithm for
token storage.
Expand All @@ -30,14 +39,13 @@ token storage.

By default, Knox uses SHA-512 to hash tokens in the database.

`cryptography.hazmat.primitives.hashes.Whirlpool` is an acceptable alternative setting
for production use.
`hashlib.sha3_512` is an acceptable alternative setting for production use.

### Tests
SHA-512 and Whirlpool are secure, however, they are slow. This should not be a
SHA-512 and SHA3-512 are secure, however, they are slow. This should not be a
problem for your users, but when testing it may be noticeable (as test cases tend
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`)
it is acceptable to use `MD5` hashing (`hashlib.md5`).

MD5 is **not secure** and must *never* be used in production sites.

Expand All @@ -58,7 +66,8 @@ Warning: setting a 0 or negative timedelta will create tokens that instantly exp
the system will not prevent you setting this.

## TOKEN_LIMIT_PER_USER
This allows you to control how many tokens can be issued per user.
This allows you to control how many valid tokens can be issued per user.
If the limit for valid tokens is reached, an error is returned at login.
By default this option is disabled and set to `None` -- thus no limit.

## USER_SERIALIZER
Expand All @@ -81,9 +90,18 @@ This is the expiry datetime format returned in the login view. The default is th
[DATETIME_FORMAT][DATETIME_FORMAT] of Django REST framework. May be any of `None`, `iso-8601`
or a Python [strftime format][strftime format] string.

## TOKEN_MODEL
This is the reference to the model used as `AuthToken`. We can define a custom `AuthToken`
model in our project that extends `knox.AbstractAuthToken` and add our business logic to it.
The default is `knox.AuthToken`

[DATETIME_FORMAT]: https://www.django-rest-framework.org/api-guide/settings/#date-and-time-formatting
[strftime format]: https://docs.python.org/3/library/time.html#time.strftime

## TOKEN_PREFIX
This is the prefix for the generated token that is used in the Authorization header. The default is just an empty string.
It can be up to `CONSTANTS.MAXIMUM_TOKEN_PREFIX_LENGTH` long.

# Constants `knox.settings`
Knox also provides some constants for information. These must not be changed in
external code; they are used in the model definitions in knox and an error will
Expand All @@ -97,3 +115,6 @@ print(CONSTANTS.DIGEST_LENGTH) #=> 128

## DIGEST_LENGTH
This is the length of the digest that will be stored in the database for each token.

## MAXIMUM_TOKEN_PREFIX_LENGTH
This is the maximum length of the token prefix.
19 changes: 16 additions & 3 deletions docs/views.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ helper methods:
- `get_user_serializer_class(self)`, to change the class used for serializing the user
- `get_expiry_datetime_format(self)`, to change the datetime format used for expiry
- `format_expiry_datetime(self, expiry)`, to format the expiry `datetime` object at your convenience
- `create_token(self)`, to create the `AuthToken` instance at your convenience

Finally, if none of these helper methods are sufficient, you can also override `get_post_response_data`
to return a fully customized payload.
Expand Down Expand Up @@ -66,12 +67,24 @@ It responds to Knox Token Authentication. On a successful request,
the token used to authenticate is deleted from the
system and can no longer be used to authenticate.

By default, this endpoint returns a HTTP 204 response on a successful request. To
customize this behavior, you can override the `get_post_response` method, for example
to include a body in the logout response and/or to modify the status code:

```python
...snip...
def get_post_response(self, request):
return Response({"bye-bye": request.user.username}, status=200)
...snip...
```

## LogoutAllView
This view accepts only a post request with an empty body. It responds to Knox Token
Authentication.
On a successful request, the token used to authenticate, and *all other tokens*
registered to the same `User` account, are deleted from the
system and can no longer be used to authenticate.
On a successful request, a HTTP 204 is returned and the token used to authenticate,
and *all other tokens* registered to the same `User` account, are deleted from the
system and can no longer be used to authenticate. The success response can be modified
like the `LogoutView` by overriding the `get_post_response` method.

**Note** It is not recommended to alter the Logout views. They are designed
specifically for token management, and to respond to Knox authentication.
Expand Down
Loading

0 comments on commit 44a0296

Please sign in to comment.