REST implementation of Django authentication system. Djoser library provides a set of Django Rest Framework views to handle basic actions such as registration, login, logout, password reset and account activation. It works with custom user model.
Instead of reusing Django code (e.g. PasswordResetForm
), we reimplemented
few things to fit better into Single Page App
architecture.
Developed by SUNSCRAPERS with passion & patience.
Here is a list of supported authentication backends:
Available endpoints:
/me/
/register/
/login/
(token based authentication)/logout/
(token based authentication)/activate/
/{{ User.USERNAME_FIELD }}/
/password/
/password/reset/
/password/reset/confirm/
Supported Python versions:
- Python 2.7
- Python 3.4
- Python 3.5
Supported Django versions:
- Django 1.7
- Django 1.8
- Django 1.9
- Django 1.10
Supported Django Rest Framework versions:
- Django Rest Framework 3.x
For Django Rest Framework 2.4 support check djoser 0.3.2.
Use pip
:
$ pip install djoser
Configure INSTALLED_APPS
:
INSTALLED_APPS = (
'django.contrib.auth',
(...),
'rest_framework',
'djoser',
(...),
)
Configure urls.py
:
urlpatterns = patterns('',
(...),
url(r'^auth/', include('djoser.urls')),
)
HTTP Basic Auth strategy is assumed by default as Django Rest Framework does it. However you may want to set it explicitly:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
),
}
Run migrations - this step will create tables for auth
app:
$ ./manage.py migrate
Add 'rest_framework.authtoken'
to INSTALLED_APPS
:
INSTALLED_APPS = (
'django.contrib.auth',
(...),
'rest_framework',
'rest_framework.authtoken',
'djoser',
(...),
)
Configure urls.py
. Pay attention to djoser.url.authtoken
module path.
urlpatterns = patterns('',
(...),
url(r'^auth/', include('djoser.urls.authtoken')),
)
Set TokenAuthentication
as default Django Rest Framework authentication strategy:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
}
Run migrations - this step will create tables for auth
and authtoken
apps:
$ ./manage.py migrate
djoser
does not provide support for JSON web token authentication out of the box but
can be enabled by using a library like djangorestframework-jwt.
You simply need to route correctly in your settings.ROOT_URLCONF
. An example would be:
import rest_framework_jwt.views
import djoser.views
urlpatterns = [
url(r'^auth/login', rest_framework_jwt.views.obtain_jwt_token), # using JSON web token
url(r'^auth/register', djoser.views.RegistrationView.as_view()),
url(r'^auth/password/reset', djoser.views.PasswordResetView.as_view()),
url(r'^auth/password/reset/confirm', djoser.views.PasswordResetConfirmView.as_view()),
...
]
Optionally add DJOSER
settings:
DJOSER = {
'DOMAIN': 'frontend.com',
'SITE_NAME': 'Frontend',
'PASSWORD_RESET_CONFIRM_URL': '#/password/reset/confirm/{uid}/{token}',
'ACTIVATION_URL': '#/activate/{uid}/{token}',
'SEND_ACTIVATION_EMAIL': True,
'PASSWORD_VALIDATORS': [],
'SERIALIZERS': {},
}
Check "Settings" section for more info.
Use this endpoint to retrieve/update user.
URL: /me/
Retrieve user.
-
response
-
status:
HTTP_200_OK
(success) -
data:
{{ User.USERNAME_FIELD }}
{{ User._meta.pk.name }}
{{ User.REQUIRED_FIELDS }}
-
URL: /me/
Update user.
-
request
-
data:
{{ User.REQUIRED_FIELDS }}
-
-
response
-
status:
HTTP_200_OK
(success) -
data:
{{ User.USERNAME_FIELD }}
{{ User._meta.pk.name }}
{{ User.REQUIRED_FIELDS }}
-
Use this endpoint to register new user. Your user model manager should implement create_user method and have USERNAME_FIELD and REQUIRED_FIELDS fields.
URL: /register/
-
request
-
data:
{{ User.USERNAME_FIELD }}
{{ User.REQUIRED_FIELDS }}
password
-
-
response
-
status:
HTTP_201_CREATED
(success) -
data:
{{ User.USERNAME_FIELD }}
{{ User._meta.pk.name }}
{{ User.REQUIRED_FIELDS }}
-
Use this endpoint to obtain user authentication token. This endpoint is available only if you are using token based authentication.
URL: /login/
-
request
-
data:
{{ User.USERNAME_FIELD }}
password
-
-
response
-
status:
HTTP_200_OK
(success) -
data:
auth_token
-
Use this endpoint to logout user (remove user authentication token). This endpoint is available only if you are using token based authentication.
URL: /logout/
-
response
- status:
HTTP_204_NO_CONTENT
(success)
- status:
Use this endpoint to activate user account. This endpoint is not a URL which
will be directly exposed to your users - you should provide site in your
frontend application (configured by ACTIVATION_URL
) which will send POST
request to activate endpoint.
URL: /activate/
-
request
-
data:
uid
token
-
-
response
- status:
HTTP_204_NO_CONTENT
(success)
- status:
Use this endpoint to change user username (USERNAME_FIELD
).
URL: /{{ User.USERNAME_FIELD }}/
-
request
-
data:
new_{{ User.USERNAME_FIELD }}
re_new_{{ User.USERNAME_FIELD }}
(ifSET_USERNAME_RETYPE
isTrue
)current_password
-
-
response
- status:
HTTP_204_NO_CONTENT
(success)
- status:
Use this endpoint to change user password.
URL: /password/
-
request
-
data:
new_password
re_new_password
(ifSET_PASSWORD_RETYPE
isTrue
)current_password
-
-
response
- status:
HTTP_204_NO_CONTENT
(success)
- status:
Use this endpoint to send email to user with password reset link. You have to
setup PASSWORD_RESET_CONFIRM_URL
.
URL: /password/reset/
-
request
-
data:
email
-
-
response
- status:
HTTP_204_NO_CONTENT
(success), ifPASSWORD_RESET_SHOW_EMAIL_NOT_FOUND
isFalse
(default); or - status:
HTTP_400_BAD_REQUEST
, ifPASSWORD_RESET_SHOW_EMAIL_NOT_FOUND
isTrue
andemail
does not exists in the database.
- status:
Use this endpoint to finish reset password process. This endpoint is not a URL
which will be directly exposed to your users - you should provide site in your
frontend application (configured by PASSWORD_RESET_CONFIRM_URL
) which
will send POST
request to reset password confirmation endpoint.
URL: /password/reset/confirm/
-
request
-
data:
uid
token
new_password
re_new_password
(ifPASSWORD_RESET_CONFIRM_RETYPE
isTrue
)
-
-
response
- status:
HTTP_204_NO_CONTENT
(success)
- status:
Domain of your frontend app. If not provided, domain of current site will be used.
Required: False
Name of your frontend app. If not provided, name of current site will be used.
Required: False
URL to your frontend password reset page. It should contain {uid}
and
{token}
placeholders, e.g. #/password-reset/{uid}/{token}
. You should pass
uid
and token
to reset password confirmation endpoint.
Required: True
If True
, register endpoint will send activation email to user.
Default: False
If True
, register or activation endpoint will send confirmation email to user.
Default: False
URL to your frontend activation page. It should contain {uid}
and {token}
placeholders, e.g. #/activate/{uid}/{token}
. You should pass uid
and
token
to activation endpoint.
Required: True
If True
, you need to pass re_new_{{ User.USERNAME_FIELD }}
to
/{{ User.USERNAME_FIELD }}/
endpoint, to validate username equality.
Default: False
If True
, you need to pass re_new_password
to /password/
endpoint, to
validate password equality.
Default: False
If True
, you need to pass re_new_password
to /password/reset/confirm/
endpoint in order to validate password equality.
Default: False
If True
, setting new password will logout the user.
Default: False
If True
, posting a non-existent email
to /password/reset/
will return
a HTTP_400_BAD_REQUEST
response with an EMAIL_NOT_FOUND
error message
('User with given email does not exist.').
If False
(default), the /password/reset/
endpoint will always return
a HTTP_204_NO_CONTENT
response.
Please note that setting this to True
will expose information whether
an email is registered in the system.
Default: False
List containing REST Framework Validator functions.
These validators are run on /register/
and /password/reset/confirm/
.
Default: []
Example: [my_validator1, my_validator2]
This dictionary is used to update the defaults, so by providing, let's say, one key, all the others will still be used.
Examples
{
'user': 'myapp.serializers.SpecialUserSerializer',
}
Default:
{
'activation': 'djoser.serializers.ActivationSerializer',
'login': 'djoser.serializers.LoginSerializer',
'password_reset': 'djoser.serializers.PasswordResetSerializer',
'password_reset_confirm': 'djoser.serializers.PasswordResetConfirmSerializer',
'password_reset_confirm_retype': 'djoser.serializers.PasswordResetConfirmRetypeSerializer',
'set_password': 'djoser.serializers.SetPasswordSerializer',
'set_password_retype': 'djoser.serializers.SetPasswordRetypeSerializer',
'set_username': 'djoser.serializers.SetUsernameSerializer',
'set_username_retype': 'djoser.serializers.SetUsernameRetypeSerializer',
'user_registration': 'djoser.serializers.UserRegistrationSerializer',
'user': 'djoser.serializers.UserSerializer',
'token': 'djoser.serializers.TokenSerializer',
}
There are few email templates which you may want to override:
activation_email_body.txt
activation_email_subject.txt
password_reset_email_body.txt
password_reset_email_subject.txt
All of them have following context:
user
domain
site_name
url
uid
token
protocol
We provide a standalone test app for you to start easily, see how everything works with basic settings. It might be useful before integrating djoser into your backend application.
In this extremely short tutorial we are going to mimic the simplest flow: register user, log in and log out. We will also check resource access on each consecutive step. Let's go!
-
Clone repository and install djoser to your virtualenv:
$ git clone [email protected]:sunscrapers/djoser.git
$ cd djoser
$ pip install -e .
-
Go to the
testproject
directory, migrate the database and start the development server:$ cd testproject
$ ./manage.py migrate
$ ./manage.py runserver 8088
-
Register a new user:
$ curl -X POST http://127.0.0.1:8088/auth/register/ --data 'username=djoser&password=djoser'
{"email": "", "username": "djoser", "id":1}
So far, so good. We have just created a new user using REST API.
-
Let's access user's details:
$ curl -X GET http://127.0.0.1:8088/auth/me/
{"detail": "Authentication credentials were not provided."}
As we can see, we cannot access user profile without logging in. Pretty obvious.
-
Let's log in:
curl -X POST http://127.0.0.1:8088/auth/login/ --data 'username=djoser&password=djoser'
{"auth_token": "b704c9fc3655635646356ac2950269f352ea1139"}
We have just obtained an authorization token that we may use later in order to retrieve specific resources.
-
Let's access user's details again:
$ curl -X GET http://127.0.0.1:8088/auth/me/
{"detail": "Authentication credentials were not provided."}
Access is still forbidden but let's offer the token we obtained:
$ curl -X GET http://127.0.0.1:8088/auth/me/ -H 'Authorization: Token b704c9fc3655635646356ac2950269f352ea1139'
{"email": "", "username": "djoser", "id": 1}
Yay, it works!
-
Now let's log out:
curl -X POST http://127.0.0.1:8088/auth/logout/ -H 'Authorization: Token b704c9fc3655635646356ac2950269f352ea1139'
And try access user profile again:
$ curl -X GET http://127.0.0.1:8088/auth/me/ -H 'Authorization: Token b704c9fc3655635646356ac2950269f352ea1139'
{"detail": "Invalid token"}
As we can see, user has been logged out successfully and the proper token has been removed.
If you need to customize any serializer behaviour you can use the DJOSER['SERIALIZERS'] setting to use your own serializer classes in the built-in views. Or if you need to completely change the default djoser behaviour, you can always override djoser views with your own custom ones.
Define custom urls
instead of reusing djoser.urls
:
urlpatterns = patterns('',
(...),
url(r'^register/$', views.CustomRegistrationView.as_view()),
)
Define custom view/serializer (inherit from one of djoser
class) and override necessary method/field:
class CustomRegistrationView(djoser.views.RegistrationView):
def send_activation_email(self, *args, **kwargs):
your_custom_email_sender(*args, **kwargs)
You could check djoser
API in source code:
To start developing on djoser, clone the repository:
$ git clone [email protected]:sunscrapers/djoser.git
In order to run the tests create virtualenv, go to repo directory and then:
$ pip install django djangorestframework
$ pip install -r requirements.txt
If you are running djoser tests on Python 2.7 you also need to install mock
library.
$ pip install mock # only on Python 2.7
$ cd testproject
$ ./manage.py test
If you need to run tests against all supported Python and Django versions then invoke:
$ pip install tox
$ tox
You can also play with test project by running following commands:
$ ./manage.py migrate
$ ./manage.py runserver
List of projects related to Django, REST and authentication: