Skip to content

Commit 0dd0dcf

Browse files
authored
Merge pull request #3 from eadwinCode/docs
Docs
2 parents 1535729 + aff56cf commit 0dd0dcf

22 files changed

+702
-61
lines changed

LICENSE.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright 2017 David Sanders
1+
Copyright 2021 Ezeudoh Tochukwu
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy of
44
this software and associated documentation files (the "Software"), to deal in

docs/docs/auth_integration.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
2+
Ninja JWT uses Django Ninja `HttpBearer` as a way to authenticate users reaching your api endpoint.
3+
Authenticated user can be found in `request.user` or `request.auth`
4+
5+
### Route Authentication - Class Based
6+
7+
``` {.sourceCode .python}
8+
from ninja_extra import APIController, router, route
9+
from ninja_jwt.authentication import JWTAuth
10+
11+
@router('')
12+
class MyController(APIController):
13+
@route.get('/some-endpoint', auth=JWTAuth())
14+
def some_endpoint(self):
15+
...
16+
```
17+
18+
### Route Authentication - Function Based
19+
20+
``` {.sourceCode .python}
21+
from ninja import router
22+
from ninja_jwt import JWTAuth
23+
24+
router = router('')
25+
26+
@router.get('/some-endpoint', auth=JWTAuth())
27+
def some_endpoint(self):
28+
...
29+
```
30+
31+
Custom Auth Implement
32+
-------
33+
If you wish to use a different implementation of `JWTAuth`, then you need to inherit from `JWTBaseAuthentication`.
34+
Please read more on [Django Ninja - Authentication](https://django-ninja.rest-framework.com/tutorial/authentication/), if you want to use a different approach that is not `bearer`.
35+
36+
example:
37+
``` {.sourceCode .python}
38+
from ninja.security import APIKeyHeader
39+
from ninja_jwt.authentication import JWTBaseAuthentication
40+
from ninja import router
41+
42+
class ApiKey(APIKeyHeader):
43+
param_name = "X-API-Key"
44+
45+
def authenticate(self, request, key):
46+
if key == "supersecret":
47+
return self.jwt_authenticate(request, token=key)
48+
49+
50+
header_key = ApiKey()
51+
router = router('')
52+
53+
@api.get("/headerkey", auth=header_key)
54+
def apikey(request):
55+
return f"Token = {request.auth}"
56+
57+
```

docs/docs/blacklist_app.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
Ninja JWT includes an app that provides token blacklist functionality.
3+
To use this app, include it in your list of installed apps in
4+
`settings.py`:
5+
6+
``` {.sourceCode .python}
7+
# Django project settings.py
8+
9+
...
10+
11+
INSTALLED_APPS = (
12+
...
13+
'ninja_jwt.token_blacklist',
14+
...
15+
)
16+
```
17+
18+
Also, make sure to run `python manage.py migrate` to run the app\'s
19+
migrations.
20+
21+
If the blacklist app is detected in `INSTALLED_APPS`, Ninja JWT will
22+
add any generated refresh or sliding tokens to a list of outstanding
23+
tokens. It will also check that any refresh or sliding token does not
24+
appear in a blacklist of tokens before it considers it as valid.
25+
26+
The Ninja JWT blacklist app implements its outstanding and blacklisted
27+
token lists using two models: `OutstandingToken` and `BlacklistedToken`.
28+
Model admins are defined for both of these models. To add a token to the
29+
blacklist, find its corresponding `OutstandingToken` record in the admin
30+
and use the admin again to create a `BlacklistedToken` record that
31+
points to the `OutstandingToken` record.
32+
33+
Alternatively, you can blacklist a token by creating a `BlacklistMixin`
34+
subclass instance and calling the instance's `blacklist` method:
35+
36+
``` {.sourceCode .python}
37+
from ninja_jwt.tokens import RefreshToken
38+
39+
token = RefreshToken(base64_encoded_token_string)
40+
token.blacklist()
41+
```
42+
43+
This will create unique outstanding token and blacklist records for the
44+
token's `jti` claim or whichever claim is specified by the
45+
`JTI_CLAIM` setting.
46+
47+
The blacklist app also provides a management command,
48+
`flushexpiredtokens`, which will delete any tokens from the outstanding
49+
list and blacklist that have expired. You should set up a cron job on
50+
your server or hosting platform which runs this command daily.

docs/docs/blacklist_app.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Blacklist app
44
=============
55

6-
Simple JWT includes an app that provides token blacklist functionality. To use
6+
Ninja JWT includes an app that provides token blacklist functionality. To use
77
this app, include it in your list of installed apps in ``settings.py``:
88

99
.. code-block:: python
@@ -21,12 +21,12 @@ this app, include it in your list of installed apps in ``settings.py``:
2121
Also, make sure to run ``python manage.py migrate`` to run the app's
2222
migrations.
2323

24-
If the blacklist app is detected in ``INSTALLED_APPS``, Simple JWT will add any
24+
If the blacklist app is detected in ``INSTALLED_APPS``, Ninja JWT will add any
2525
generated refresh or sliding tokens to a list of outstanding tokens. It will
2626
also check that any refresh or sliding token does not appear in a blacklist of
2727
tokens before it considers it as valid.
2828

29-
The Simple JWT blacklist app implements its outstanding and blacklisted token
29+
The Ninja JWT blacklist app implements its outstanding and blacklisted token
3030
lists using two models: ``OutstandingToken`` and ``BlacklistedToken``. Model
3131
admins are defined for both of these models. To add a token to the blacklist,
3232
find its corresponding ``OutstandingToken`` record in the admin and use the
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
Sometimes, you may wish to manually create a token for a user. This
3+
could be done as follows:
4+
5+
``` {.sourceCode .python}
6+
from ninja_jwt.tokens import RefreshToken
7+
8+
def get_tokens_for_user(user):
9+
refresh = RefreshToken.for_user(user)
10+
11+
return {
12+
'refresh': str(refresh),
13+
'access': str(refresh.access_token),
14+
}
15+
```
16+
17+
The above function `get_tokens_for_user` will return the serialized
18+
representations of new refresh and access tokens for the given user. In
19+
general, a token for any subclass of `ninja_jwt.tokens.Token` can be
20+
created in this way.
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
2+
If you wish to customize the claims contained in web tokens which are
3+
generated by the `SimpleJWTDefaultController` and `SimpleJWTSlidingController`
4+
views, create a subclass for the desired controller as well as a subclass for
5+
its corresponding serializer. Here\'s an example :
6+
7+
``` {.sourceCode .python}
8+
from ninja_jwt.schema import TokenObtainPairSerializer
9+
from ninja_jwt.controller import TokenObtainPairController, router, route
10+
from ninja_schema import Schema
11+
12+
13+
class UserSchema(Schema):
14+
first_name: str
15+
email: str
16+
17+
18+
class MyTokenObtainPairOutSchema(Schema):
19+
refresh: str
20+
access: str
21+
user: UserSchema
22+
23+
24+
class MyTokenObtainPairSchema(TokenObtainPairSerializer):
25+
def output_schema(self):
26+
out_dict = self.dict(exclude={"password"})
27+
out_dict.update(user=UserSchema.from_orm(self._user))
28+
return MyTokenObtainPairOutSchema(**out_dict)
29+
30+
@router('/token', tags=['Auth'])
31+
class MyTokenObtainPairController(TokenObtainPairController):
32+
@route.post(
33+
"/pair", response=schema.MyTokenObtainPairOutSchema, url_name="token_obtain_pair"
34+
)
35+
def obtain_token(self, user_token: MyTokenObtainPairSchema):
36+
return user_token.output_schema()
37+
38+
```
39+
40+
As with the standard controller, you\'ll also need to include register the controller as shown in `getting_started`
41+
42+
#### Use Django Ninja Router
43+
If you interested in using functions rather than classes, then you are also covered.
44+
Here is an example
45+
46+
``` {.sourceCode .python}
47+
from ninja import router
48+
from ninja_schema import Schema
49+
50+
router = router('/token')
51+
52+
@router.post(
53+
"/pair", response=schema.MyTokenObtainPairOutSchema, url_name="token_obtain_pair"
54+
)
55+
def obtain_token(self, user_token: MyTokenObtainPairSchema):
56+
return user_token.output_schema()
57+
```
58+
59+
Register the `router` to the django-ninja `api` like so:
60+
``` {.sourceCode .python}
61+
from ninja import NinjaAPI
62+
63+
api = NinjaAPI()
64+
api.add_router('', tags=['Auth'], router=router)
65+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
To do development work for Ninja JWT, make your own fork on Github,
3+
clone it locally, make and activate a virtualenv for it, then from
4+
within the project directory:
5+
6+
``` {.sourceCode .bash}
7+
make install
8+
```
9+
10+
To run the tests:
11+
12+
``` {.sourceCode .bash}
13+
make test
14+
```
15+
To run the tests with coverage:
16+
17+
``` {.sourceCode .bash}
18+
make test-cov
19+
```

docs/docs/development_and_contributing.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
Development and contributing
44
============================
55

6-
To do development work for Simple JWT, make your own fork on Github, clone it
6+
To do development work for Ninja JWT, make your own fork on Github, clone it
77
locally, make and activate a virtualenv for it, then from within the project
88
directory:
99

docs/docs/experimental_features.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
subtitle: JWTTokenUserAuthentication backend
2+
title: Experimental features
3+
---
4+
5+
The `JWTTokenUserAuthentication` backend\'s `authenticate` method does
6+
not perform a database lookup to obtain a user instance. Instead, it
7+
returns a `ninja_jwt.models.TokenUser` instance which acts as a
8+
stateless user object backed only by a validated token instead of a
9+
record in a database. This can facilitate developing single sign-on
10+
functionality between separately hosted Django apps which all share the
11+
same token secret key. To use this feature, add the
12+
`ninja_jwt.authentication.JWTTokenUserAuthentication` backend (instead
13+
of the default `JWTAuthentication` backend) to the Django REST
14+
Framework\'s `DEFAULT_AUTHENTICATION_CLASSES` config setting:
15+
16+
``` {.sourceCode .python}
17+
REST_FRAMEWORK = {
18+
...
19+
'DEFAULT_AUTHENTICATION_CLASSES': (
20+
...
21+
'ninja_jwt.authentication.JWTTokenUserAuthentication',
22+
)
23+
...
24+
}
25+
```

docs/docs/getting_started.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
2+
#### Requirements
3+
- Python >= 3.6
4+
- Django >= 2.1
5+
- Django-Ninja >= 0.16.1
6+
- Ninja-Schema >= 0.12.2
7+
- Django-Ninja-Extra >= 0.11.0
8+
9+
These are the officially supported python and package versions. Other
10+
versions will probably work. You\'re free to modify the tox config and
11+
see what is possible.
12+
13+
Installation
14+
============
15+
16+
Ninja JWT can be installed with pip:
17+
18+
pip install ninja-jwt
19+
20+
Also, you need to register `SimpleJWTDefaultController` controller to you Django-Ninja api.
21+
The `SimpleJWTDefaultController` comes with three routes `obtain_token`, `refresh_token` and `verify_token`
22+
23+
``` {.sourceCode .python}
24+
from ninja_jwt.controller import SimpleJWTDefaultController
25+
from ninja_extra import NinjaExtraAPI
26+
27+
api = NinjaExtraAPI()
28+
api.register_controller(SimpleJWTDefaultController)
29+
30+
```
31+
32+
The `SimpleJWTDefaultController` comes with three routes `obtain_token`, `refresh_token` and `verify_token`.
33+
It is a combination of two subclass `TokenVerificationController` and `TokenObtainPairController`.
34+
If you wish to customize these routes, you can inherit from these controllers and change its implementation
35+
36+
``` {.sourceCode .python}
37+
from ninja_jwt.controller import TokenObtainPairController, router
38+
39+
@router('token', tags=['Auth']
40+
class MyCustomController(TokenObtainPairController):
41+
"""obtain_token and refresh_token only"
42+
...
43+
api.register_controller(MyCustomController)
44+
```
45+
46+
If you wish to use localizations/translations, simply add `ninja_jwt` to
47+
`INSTALLED_APPS`.
48+
49+
``` {.sourceCode .python}
50+
INSTALLED_APPS = [
51+
...
52+
'ninja_jwt',
53+
...
54+
]
55+
```
56+
57+
Usage
58+
=====
59+
60+
To verify that Ninja JWT is working, you can use curl to issue a couple
61+
of test requests:
62+
63+
``` {.sourceCode .bash}
64+
curl \
65+
-X POST \
66+
-H "Content-Type: application/json" \
67+
-d '{"username": "davidattenborough", "password": "boatymcboatface"}' \
68+
http://localhost:8000/api/token/pair
69+
70+
...
71+
{
72+
"access":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNDU2LCJqdGkiOiJmZDJmOWQ1ZTFhN2M0MmU4OTQ5MzVlMzYyYmNhOGJjYSJ9.NHlztMGER7UADHZJlxNG0WSi22a2KaYSfd1S-AuT7lU",
73+
"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImNvbGRfc3R1ZmYiOiLimIMiLCJleHAiOjIzNDU2NywianRpIjoiZGUxMmY0ZTY3MDY4NDI3ODg5ZjE1YWMyNzcwZGEwNTEifQ.aEoAYkSJjoWH1boshQAaTkf8G3yn0kapko6HFRt7Rh4"
74+
}
75+
```
76+
77+
You can use the returned access token to prove authentication for a
78+
protected view:
79+
80+
``` {.sourceCode .bash}
81+
curl \
82+
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNDU2LCJqdGkiOiJmZDJmOWQ1ZTFhN2M0MmU4OTQ5MzVlMzYyYmNhOGJjYSJ9.NHlztMGER7UADHZJlxNG0WSi22a2KaYSfd1S-AuT7lU" \
83+
http://localhost:8000/api/some-protected-view/
84+
```
85+
86+
When this short-lived access token expires, you can use the longer-lived
87+
refresh token to obtain another access token:
88+
89+
``` {.sourceCode .bash}
90+
curl \
91+
-X POST \
92+
-H "Content-Type: application/json" \
93+
-d '{"refresh":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImNvbGRfc3R1ZmYiOiLimIMiLCJleHAiOjIzNDU2NywianRpIjoiZGUxMmY0ZTY3MDY4NDI3ODg5ZjE1YWMyNzcwZGEwNTEifQ.aEoAYkSJjoWH1boshQAaTkf8G3yn0kapko6HFRt7Rh4"}' \
94+
http://localhost:8000/api/token/refresh/
95+
96+
...
97+
{"access":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX3BrIjoxLCJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiY29sZF9zdHVmZiI6IuKYgyIsImV4cCI6MTIzNTY3LCJqdGkiOiJjNzE4ZTVkNjgzZWQ0NTQyYTU0NWJkM2VmMGI0ZGQ0ZSJ9.ekxRxgb9OKmHkfy-zs1Ro_xs1eMLXiR17dIDBVxeT-w"}
98+
```

0 commit comments

Comments
 (0)