Authentication for Django Rest Framework

Overview

Dj-Rest-Auth

<iMerica> Coverage Status

Drop-in API endpoints for handling authentication securely in Django Rest Framework. Works especially well with SPAs (e.g React, Vue, Angular), and Mobile applications.

Requirements

  • Django 2 or 3
  • Python 3

Quick Setup

Install package

pip install dj-rest-auth

Add dj_rest_auth app to INSTALLED_APPS in your django settings.py:

INSTALLED_APPS = (
    ...,
    'rest_framework',
    'rest_framework.authtoken',
    ...,
    'dj_rest_auth'
)

Add URL patterns

urlpatterns = [
    path('dj-rest-auth/', include('dj_rest_auth.urls')),
]

(Optional) Use Http-Only cookies

REST_USE_JWT = True
JWT_AUTH_COOKIE = 'jwt-auth'

Testing

To run the tests within a virtualenv, run python runtests.py from the repository directory. The easiest way to run test coverage is with coverage, which runs the tests against all supported Django installs. To run the test coverage within a virtualenv, run coverage run ./runtests.py from the repository directory then run coverage report.

Tox

Testing may also be done using tox, which will run the tests against all supported combinations of python and django.

Install tox, either globally or within a virtualenv, and then simply run tox from the repository directory. As there are many combinations, you may run them in parallel using tox --parallel.

The tox.ini includes an environment for testing code coverage and you can run it and view this report with tox -e coverage.

Linting may also be performed via flake8 by running tox -e flake8.

Documentation

View the full documentation here: https://dj-rest-auth.readthedocs.io/en/latest/index.html

Acknowledgements

This project began as a fork of django-rest-auth. Big thanks to everyone who contributed to that repo!

Comments
  • Migrate to GitHub Actions.

    Migrate to GitHub Actions.

    Travis CI has a new pricing model which places limits on open source.

    • https://blog.travis-ci.com/2020-11-02-travis-ci-new-billing
    • https://www.jeffgeerling.com/blog/2020/travis-cis-new-pricing-plan-threw-wrench-my-open-source-works

    Many projects are moving to GitHub Actions instead, including Jazzband projects

    • https://github.com/orgs/jazzband/projects/1
    • https://github.com/jazzband-roadies/help/issues/206

    This is based on https://github.com/jazzband/contextlib2/pull/26.

    TODO:

    • [x] @jezdez to add JAZZBAND_RELEASE_KEY to the repo secrets.
    • [x] @jezdez to add @iMerica as project lead (refs #1).
    opened by jezdez 23
  • Password Reset Custom Email

    Password Reset Custom Email

    Hey everyone! Sorry if this seems repetitive but I really did try to get this to work the best I could using the solutions above. Nothing seems to work and I'm hitting a wall.

    I am trying to simply customize the email sent when the password-reset route is hit. I want it to direct to a route in my frontend (React).

    I tried @mohmyo solution to customize the email here https://github.com/iMerica/dj-rest-auth/issues/9#issuecomment-598963520.

    This doesn't seem to do a thing sadly.

    Here's some code from my project:

    project/users/serializers.py - This is my custom serializer:

    from dj_rest_auth.serializers import PasswordResetSerializer
    
    class CustomPasswordResetSerializer(PasswordResetSerializer):
        def get_email_options(self):
            return {
                'email_template_name': 'registration/password_reset_message.html'
            }
    

    project/users/urls.py - users is a app

    from dj_rest_auth.registration.views import (ConfirmEmailView, RegisterView,
                                                 VerifyEmailView)
    from dj_rest_auth.views import LoginView, LogoutView
    from django.urls import path, re_path
    
    urlpatterns = [
        path('register/', RegisterView.as_view()),
        path('account-confirm-email/<str:key>/', ConfirmEmailView.as_view()),
        path('login/', LoginView.as_view()),
        path('logout/', LogoutView.as_view()),
        path('verify-email/',
             VerifyEmailView.as_view(), name='rest_verify_email'),
        path('account-confirm-email/',
             VerifyEmailView.as_view(), name='account_email_verification_sent'),
        re_path(r'^account-confirm-email/(?P<key>[-:\w]+)/$',
                VerifyEmailView.as_view(), name='account_confirm_email'),
    ]
    
    

    project/mysite/urls.py - mysite is the directory where settings.py and the the main urls.py are:

    from dj_rest_auth.views import PasswordResetConfirmView, PasswordResetView
    from django.contrib import admin
    from django.urls import include, path
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('api/users/', include('users.urls')),
        path('api/users/password-reset/', PasswordResetView.as_view()),
        path('api/users/password-reset-confirm/<uidb64>/<token>/',
             PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
    ]
    
    

    project/mysite/settings.py

    TEMPLATES = [
        {
            ...
            'DIRS': [os.path.join(BASE_DIR, "templates")],
            ...
        }
    ]
    
    # Django All Auth config
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
    AUTHENTICATION_BACKENDS = (
        "django.contrib.auth.backends.ModelBackend",
        "allauth.account.auth_backends.AuthenticationBackend",
    )
    SITE_ID = 1
    ACCOUNT_EMAIL_REQUIRED = True
    ACCOUNT_USERNAME_REQUIRED = False
    ACCOUNT_SESSION_REMEMBER = True
    ACCOUNT_AUTHENTICATION_METHOD = 'email'
    ACCOUNT_UNIQUE_EMAIL = True
    ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
    ACCOUNT_CONFIRM_EMAIL_ON_GET = True
    LOGIN_URL = 'http://localhost:8000/api/v1/users/login/'
    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_USE_TLS = True
    EMAIL_HOST = local_settings.email_host
    EMAIL_HOST_USER = local_settings.email_host_user
    EMAIL_HOST_PASSWORD = local_settings.email_host_password
    EMAIL_PORT = local_settings.email_port
    
    REST_AUTH_SERIALIZERS = {
        'PASSWORD_RESET_SERIALIZER': 'users.serializers.CustomPasswordResetSerializer'
    }
    
    

    I have a template in project/templates/registration/password_reset_message.py.

    This is my file structure if it helps.

    ├── manage.py ├── templates │   └── registration │   └── password_reset_message.html ├── mysite │   ├── init.py │   ├── asgi.py │   ├── local_settings.py │   ├── settings.py │   ├── urls.py │   └── wsgi.py └── users ├── init.py ├── admin.py ├── apps.py ├── forms.py ├── migrations │   ├── 0001_initial.py │   └── init.py ├── models.py ├── serializers.py ├── tests.py ├── urls.py └── views.py

    The issue is the template I specify isn't being sent. Rather, the default one provide by Django is.

    I tried the other way in @mohmyo solution as well where you overwrite the entire save method of the serializer with no luck. Thanks to anyone who can help out here. This is my first GitHub issue!

    opened by tarricsookdeo 14
  • Password reset throws error with django 3.1

    Password reset throws error with django 3.1

    Hello,

    recently updated django to version 3.1 and the password reset view throws error: django.urls.exceptions.NoReverseMatch: Reverse for 'password_reset_confirm' with keyword arguments '{'uidb64': 'MTA', 'token': 'a88hdr-5fb0f72acbe1e9d2b81b7810dee31037'}' not found. 1 pattern(s) tried: ['usermanagement\/password-reset/confirm/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$']

    If i roll back to django 3.0 it works again.

    bug 
    opened by IIFelix 14
  • UID for password reset incorrectly uses base64

    UID for password reset incorrectly uses base64

    When a password reset link is request, the UID is encoded into the url as such, by django allauth

    /accounts/password/reset/key/7w-1x7-d1a11z1sa1s1a1s/
    

    Such that the uid is 7w and the token is 1x7-d1a11z1sa1s1a1s

    The UID is encoded here, as base36: https://github.com/pennersr/django-allauth/blob/330bf899dd77046fd0510221f3c12e69eb2bc64d/allauth/account/forms.py#L524

    However, when the UID decoded in django-rest-auth as base64 https://github.com/jazzband/dj-rest-auth/blob/02c9242e3d069164692ef44a0f15eaca31a41cac/dj_rest_auth/serializers.py#L214

    question 
    opened by gsheni 14
  • ImproperlyConfigured registration email verification

    ImproperlyConfigured registration email verification

    hi! when I try to access the following link in the email confirmation sent on user registration:

    http://localhost:8000/dj-rest-auth/registration/account-confirm-email/MQ:1jIgPr:Ayckd0pouL4B-foYgl2wjdSCYOY/

    I receive the following error:

    ImproperlyConfigured
    TemplateResponseMixin requires either a definition of 'template_name' or an implementation of 'get_template_names()'
    

    Where should I create such a template? how should I name the template? it would be great if you could point me to some documentation or shed some light on how to proceed further. cheers!

    opened by fessacchiotto 14
  • Authenticate on a backend server with Google account

    Authenticate on a backend server with Google account

    Hello, I already have dj-rest-auth in my app. How can I authenticate user on a backend server with Google account - https://developers.google.com/identity/sign-in/android/backend-auth

    I dont want to reinvent the wheel, maybe you could point me out how to do this with dj-rest-auth Thanks in advance!

    support-request 
    opened by bene25 11
  • Google Social Authentication with dj-rest-auth

    Google Social Authentication with dj-rest-auth

    I've spent a a lot of time on implementing Google oAuth with dj-rest-auth which should be easier, and I'll post my solution here, hoping it'll help somebody else. views.py

    class GoogleLogin(SocialLoginView):
        adapter_class = GoogleOAuth2Adapter
        client_class = OAuth2Client
        callback_url = "http://127.0.0.1:8000/api/auth/google/callback/"
    

    urls.py

    path(r'auth/google', GoogleLogin.as_view(), name='google_login')

    settings.py

       'allauth.socialaccount',
       'allauth.socialaccount.providers.google',
    

    The callback_url and client_class are only required if you're sending only code i.e. authorization_code to Google oAuth URL. The problem I had was that after making the request to https://accounts.google.com/o/oauth2/v2/auth?redirect_uri=<callback-url>&prompt=consent&response_type=code&client_id=<your_client_id>&scope=openid%20email&access_type=offline (change the callback_url and client_id with the ones from your app), as a response I got back the code. When sending the code to the /auth/google URL, i got this error Error retrieving access token: b'{\n “error”: “redirect_uri_mismatch”,\n “error_description”: “Bad Request”\n}'. This was because the code is URL safe, which means you'll need to first decode it and then send it to your API endpoint.

    opened by MatejMijoski 10
  • Sign In with Apple KeyError: 'id_token'

    Sign In with Apple KeyError: 'id_token'

    I want to start off by saying fantastic job on this package.

    An issue was raised on StackOverflow last week about Sign In with Apple and rest-auth here that is not seeing much traffic. This issue seems to be the same with dj-rest-framework.

    Following the example, this is what I got:

    from allauth.socialaccount.providers.apple.views import AppleOAuth2Adapter
    from allauth.socialaccount.providers.apple.client import AppleOAuth2Client
    from dj_rest_auth.registration.views import SocialLoginView
    
    class AppleLogin(SocialLoginView):
        """
        Class used for Sign In with Apple authentication.
        """
        adapter_class = AppleOAuth2Adapter
        client_class = AppleOAuth2Client
        callback_url = 'example.com'
    

    Submitting the access_token and code, you get the same KeyError: 'id_token' (targeting the same line) that is mentioned in the Stack Overflow question.

    When using Django allauth exclusively, Sign In with Apple works. It's only over the API requests that it does not.

    Thanks for the help.

    opened by gabe-lucas 10
  • Refresh token not blacklisted on logout

    Refresh token not blacklisted on logout

    #27

    Attempt to blacklist refresh token if no JWT_AUTH_COOKIE is found and using SimpleJWT Blacklist

    Status returned may be questionable in my try/except, but they make sense to me. I'm not sure how the cookies work, so I didn't test that. If there is a better way to implement this (should it be blacklisted even if using cookies?), please let me know!

    enhancement 
    opened by mjlabe 10
  • ImportError: djangorestframework_jwt needs to be installed

    ImportError: djangorestframework_jwt needs to be installed

    When using rest_framework_simplejwt, I am getting ImportError: djangorestframework_jwt needs to be installed when I hit login or registration.

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'rest_framework',
        'rest_framework_simplejwt.token_blacklist',
        'dj_rest_auth',
        'django.contrib.sites',
        'allauth',
        'allauth.account',
        'dj_rest_auth.registration',
        ...
    ]
    
    REST_FRAMEWORK = {
        # Use Django's standard `django.contrib.auth` permissions,
        # or allow read-only access for unauthenticated users.
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
        ],
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework_simplejwt.authentication.JWTAuthentication',
        )
    }
    
    REST_USE_JWT = True
    
    opened by mjlabe 10
  • Login/Logout API endpoints not sending/clearing django sessionid cookie

    Login/Logout API endpoints not sending/clearing django sessionid cookie

    EDITED TLDR: Part of the problem was that I was not including credentials on my frontend, and this got the login method working. However, I am still unable to get the logout function to work

    I have followed the installation instructions, and am trying to use dj-rest-auth with a react SPA. It appears to be partly working, as when I log in via the django admin console, and I make a GET request to /api/account/user/ (my user endpoint for dj-rest-auth), I get back the user info which corresponds to my user. This makes me think nothing is wrong with at least the basic configuration of dj-rest-auth. When I log out from the admin console and hit the same endpoint, I get a 403 response with a JSON response that tells me no user is logged in. Great.

    However, the login/logout endpoints don't appear to be working. When I log in via the django admin console, and then I hit the logout endpoint with my SPA, it does not log me out. The django server tells me the request was good:

    [21/Oct/2022 17:32:18] "POST /api/account/logout/ HTTP/1.0" 200 37
    

    But I am still logged in to the console, and no change was made to the Session model database.

    Similarly, when I hit the login endpoint with a POST request, using exactly the same username/password as I use in the admin console, it does not log me in. However, the login request gives me back a 200 response:

    [21/Oct/2022 17:39:58] "POST /api/account/login/ HTTP/1.0" 200 50
    

    which seems odd. dj-rest-auth seems to think that it's working, but for some reason it doesn't appear to be attaching / detaching users from sessions. Any ideas as to why this might be, or how to debug it further?

    opened by edmundsj 9
  • Update 2.2.6 broke Google login

    Update 2.2.6 broke Google login

    Trace : site-packages/dj_rest_auth/registration/serializers.py, line 150, in validate

    -> login = self.get_social_login(adapter, app, social_token, token)

    site-packages/dj_rest_auth/registration/serializers.py, line 60, in get_social_login

    -> social_login = adapter.complete_login(request, app, token, response=response)

    site-packages/allauth/socialaccount/providers/google/views.py, line 23, in complete_login

    try: identity_data = jwt.decode( -> response["id_token"], …

    Error : TypeError : string indices must be integers, not 'str'.

    The response is not a dict but instead it's a string of some id which then i tried and got : OAuth2Error("Invalid id_token")

    opened by Altroo 0
  • `SocialConnectView.process_login()` should not perform login

    `SocialConnectView.process_login()` should not perform login

    process_login() in SocialConnectView try to issue a new session tied to the specified social account (when REST_SESSION_LOGIN is True), but I think this behavior is not expected especially when the social account already exists in the DB:

    1. Signup and login as a User 1 tied to a SocialAccount 1
    2. Logout
    3. Signup and login as a User 2 tied to a SocialAccount 2
    4. Run a /connect API for User 2 with SocialAccount 1
    5. _add_social_account will reject the operation
    6. SocialConnectView runs django_login() and refreshes the user's session with a new one tied to User 1 even if the connection is failed

    Ref. #25.

    opened by okapies 0
  • allauth's openid connect

    allauth's openid connect

    Hello, django-allauth now support openid connect. This allows one provider class to support theoretically any OIDC compliant service. It could even perhaps replace every other provider.

    Is supporting this something the project would want? If so, may have time to help. The challenge is that this provider can be added multiple times using a SERVERS array and then generates a "dynamic instance for each configured server". This is very different as other providers can only be used once and have a static provider ID ("google"). Example:

    Provider class id: openid_connect Provider server id: google_oidc Provider server id: another_oidc

    Without changes, various places get the wrong ID. For example a callback url ends up having openid_connect when it really should have google_oidc. I got a terrible version working already by forcing in the dynamic provider name into various places. I would need to rework it for it to be of acceptable quality for this project.

    Let me know if you think this is worth my time to create a pull request for. IMO OIDC is nice because I can forget about every provider and use just 1 for everything. I no longer would need to make a custom provider class just to support yet another oauth2 service. I can also add multiple providers - for example I can add two Azure tenants to one site (impossible previously with allauth). That said, I would understand if supporting every allauth socialaccount feature isn't appetizing here.

    opened by bufke 2
  • httponly default incorrect in views.py

    httponly default incorrect in views.py

    The default for HTTPOnly is incorrect in the views.py on line #92:

    if getattr(settings, 'REST_USE_JWT', False):
        from .jwt_auth import set_jwt_cookies
        set_jwt_cookies(response, self.access_token, self.refresh_token)`
    

    Further, the HTTPOnly should be included in the serializer; no reason to remove it. This will simplify the code and also allow for easier testing. This can be seen on lines 99-103.

    opened by donaic 0
  • LogoutView return 500 status, when refresh token is invalid and output language is not English

    LogoutView return 500 status, when refresh token is invalid and output language is not English

    At BlacklistMixin you use gettext for raise TokenError with message "Token is blacklisted". But in LogoutView at checking error message at args array, you don`t use gettext, so if condition return False, when current language is not English

    image

    image

    opened by top1Dron 0
  • Login immediately on register when using JWT HTTP only

    Login immediately on register when using JWT HTTP only

    Hi there,

    Is there a way to have a user logged in immediately on register? I have set ACCOUNT_EMAIL_VERIFICATION = 'optional' and want the flow to have a user logged in once they register (then verify email at their convinience), but the register view doesn't set the JWT cookies so the user is still required to hit the Login view separately after registering...

    Is there a configuration or adjustment I can make to log in a user with JWT immediately after they register?

    Thanks :)

    opened by ainthateasy 0
Releases(2.2.6)
Owner
Michael
Lead Software Engineer, Founder - Platform & Product
Michael
A JSON Web Token authentication plugin for the Django REST Framework.

Simple JWT Abstract Simple JWT is a JSON Web Token authentication plugin for the Django REST Framework. For full documentation, visit django-rest-fram

Jazzband 3.3k Jan 4, 2023
Authentication Module for django rest auth

django-rest-knox Authentication Module for django rest auth Knox provides easy to use authentication for Django REST Framework The aim is to allow for

James McMahon 873 Dec 30, 2022
REST implementation of Django authentication system.

djoser REST implementation of Django authentication system. djoser library provides a set of Django Rest Framework views to handle basic actions such

Sunscrapers 2.2k Jan 1, 2023
Country-specific Django helpers, to use in Django Rest Framework

django-rest-localflavor Country-specific serializers fields, to Django Rest Framework Documentation (soon) The full documentation is at https://django

Gilson Filho 19 Aug 30, 2022
Automated generation of real Swagger/OpenAPI 2.0 schemas from Django REST Framework code.

drf-yasg - Yet another Swagger generator Generate real Swagger/OpenAPI 2.0 specifications from a Django Rest Framework API. Compatible with Django Res

Cristi Vîjdea 3k Jan 6, 2023
Introduction to Django Rest Framework

Introduction to Django Rest Framework This is the repository of the video series Introduction to Django Rest Framework published on YouTube. It is a s

Simple is Better Than Complex 20 Jul 14, 2022
JSON:API support for Django REST framework

JSON:API and Django REST framework Overview JSON:API support for Django REST framework Documentation: https://django-rest-framework-json-api.readthedo

null 1k Dec 27, 2022
DRF-extensions is a collection of custom extensions for Django REST Framework

Django REST Framework extensions DRF-extensions is a collection of custom extensions for Django REST Framework Full documentation for project is avail

Gennady Chibisov 1.3k Dec 28, 2022
Generate Views, Serializers, and Urls for your Django Rest Framework application

DRF Generators Writing APIs can be boring and repetitive work. Don't write another CRUDdy view in Django Rest Framework. With DRF Generators, one simp

Tobin Brown 332 Dec 17, 2022
Swagger Documentation Generator for Django REST Framework: deprecated

Django REST Swagger: deprecated (2019-06-04) This project is no longer being maintained. Please consider drf-yasg as an alternative/successor. I haven

Marc Gibbons 2.6k Dec 23, 2022
Document Web APIs made with Django Rest Framework

DRF Docs Document Web APIs made with Django Rest Framework. View Demo Contributors Wanted: Do you like this project? Using it? Let's make it better! S

Manos Konstantinidis 626 Nov 20, 2022
Recursive Serialization for Django REST framework

djangorestframework-recursive Overview Recursive Serialization for Django REST framework This package provides a RecursiveField that enables you to se

null 336 Dec 28, 2022
Dropdown population implementation for Django REST Framework

drf-dropdown Dropdown population implementation for Django REST Framework Usage Add DropdownView to API URL # urls.py import dropdown urlpatterns = [

Preeti Yuankrathok 4 Dec 6, 2022
simple api build with django rest framework

Django Rest API django-rest-framework Employees management simple API in this project wrote test suites for endpoints wrote simple doc string for clas

OMAR.A 1 Mar 31, 2022
Simple Crud Api With Django Rest Framework

SIMPLE CRUD API WITH DJANGO REST FRAMEWORK Django REST framework is a powerful and flexible toolkit for building Web APIs. Requirements Python 3.6 Dja

kibet hillary 1 May 3, 2022
BloodDonors: Built using Django REST Framework for the API backend and React for the frontend

BloodDonors By Daniel Yuan, Alex Tian, Aaron Pan, Jennifer Yuan As the pandemic raged, one of the side effects was an urgent shortage of blood donatio

Daniel Yuan 1 Oct 24, 2021
Built on Django Rest Framework, to provide with command execution on linux terminal

Built on Django Rest Framework, to provide with command execution on linux terminal

null 1 Oct 31, 2021
RESTler is the first stateful REST API fuzzing tool for automatically testing cloud services through their REST APIs and finding security and reliability bugs in these services.

RESTler is the first stateful REST API fuzzing tool for automatically testing cloud services through their REST APIs and finding security and reliability bugs in these services.

Microsoft 1.8k Jan 4, 2023