st4lk / django-rest-social-auth

OAuth signin with django rest framework
MIT License
519 stars 122 forks source link

Django REST social auth

Lint Tests Coverage Status Pypi version Downloads

OAuth signin with django rest framework.

Requirements

Release notes

Here

Motivation

To have a resource, that will do very simple thing: take the oauth code from social provider (for example facebook) and return the authenticated user. That's it.

I can't find such util for django rest framework. There are packages (for example django-rest-auth), that take access_token, not the code. Also, i've used to work with awesome library python-social-auth, so it will be nice to use it again (now it is split into social-core and social-app-django). In fact, most of the work is done by this package. Current util brings a little help to integrate django-rest-framework and python-social-auth.

Quick start

  1. Install this package to your python distribution:

    pip install rest-social-auth
  2. Do the settings

    Install apps

    INSTALLED_APPS = (
        ...
        'rest_framework',
        'rest_framework.authtoken',  # only if you use token authentication
        'social_django',  # django social auth
        'rest_social_auth',  # this package
        'knox',  # Only if you use django-rest-knox
    )

    social auth settings, look documentation for more details

    SOCIAL_AUTH_FACEBOOK_KEY = 'your app client id'
    SOCIAL_AUTH_FACEBOOK_SECRET = 'your app client secret'
    SOCIAL_AUTH_FACEBOOK_SCOPE = ['email', ]  # optional
    SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {'locale': 'ru_RU'}  # optional
    
    AUTHENTICATION_BACKENDS = (
        'social_core.backends.facebook.FacebookOAuth2',
        # and maybe some others ...
        'django.contrib.auth.backends.ModelBackend',
    )

    Also look optional settings avaliable.

  3. Make sure everything is up do date

    python manage.py migrate
  4. Include rest social urls (choose at least one)

    4.1 session authentication

    path('api/login/', include('rest_social_auth.urls_session')),

    4.2 token authentication

    path('api/login/', include('rest_social_auth.urls_token')),

    4.3 jwt authentication

    path('api/login/', include('rest_social_auth.urls_jwt_pair')),

    or / and

    path('api/login/', include('rest_social_auth.urls_jwt_sliding')),

    4.4 knox authentication

    path('api/login/', include('rest_social_auth.urls_knox')),
  5. You are ready to login users

    Following examples are for OAuth 2.0.

    5.1 session authentication

    • POST /api/login/social/session/

      input:

      {
          "provider": "facebook",
          "code": "AQBPBBTjbdnehj51"
      }

      output:

      {
          "username": "Alex",
          "email": "user@email.com",
          // other user data
      }
      
      + session id in cookies

    5.2 token authentication

    • POST /api/login/social/token/

      input:

      {
          "provider": "facebook",
          "code": "AQBPBBTjbdnehj51"
      }

      output:

      {
          "token": "68ded41d89f6a28da050f882998b2ea1decebbe0"
      }
    • POST /api/login/social/token_user/

      input:

      {
          "provider": "facebook",
          "code": "AQBPBBTjbdnehj51"
      }

      output:

      {
          "username": "Alex",
          "email": "user@email.com",
          // other user data
          "token": "68ded41d89f6a28da050f882998b2ea1decebbe0"
      }

    5.3 jwt authentication (using django-rest-framework-simplejwt)

    • POST /api/login/social/jwt-pair/

    • POST /api/login/social/jwt-pair-user/

      Similar to token authentication, but token is JSON Web Token.

      See JWT.io for details.

      To use it, django-rest-framework-simplejwt must be installed.

      For jwt-pair, the response will include additional "refresh" token:

      {
          "token": "...",
          "refresh": "..."
      }
      Or sliding JWT token:
    • POST /api/login/social/jwt-sliding/

    • POST /api/login/social/jwt-sliding-user/

      Check docs of simplejwt for pair/sliding token difference.

      Note. django-rest-framework-simplejwt doesn't work on python3.6

    5.4 knox authentication

    • POST /api/login/social/knox/
    • POST /api/login/social/knox_user/

      Similar to token authentication, but token is Django Rest Knox Token.

      To use it, django-rest-knox must be installed.

    User model is taken from settings.AUTH_USER_MODEL.

    At input there is also non-required field redirect_uri. If given, server will use this redirect uri in requests, instead of uri got from settings. This redirect_uri must be equal in front-end request and in back-end request. Back-end will not do any redirect in fact.

    It is also possible to specify provider in URL, not in request body. Just append it to the url:

    POST /api/login/social/session/facebook/

    Don't need to specify it in body now:

    {
        "code": "AQBPBBTjbdnehj51"
    }

    Provider defined in URL has higher priority than provider in body. If both are specified - provider will be taken from URL.

OAuth 2.0 workflow with rest-social-auth

  1. Front-end need to know following params for each social provider:

    • clientid # only in case of OAuth 2.0, id of registered application on social service provider_
    • redirecturi # to this url social provider will redirect with code_
    • scope=yourscope # for example email_
    • responsetype=code # same for all oauth2.0 providers_
  2. Front-end redirect user to social authorize url with params from previous point.

  3. User confirms.

  4. Social provider redirects back to redirect_uri with param code.

  5. Front-end now ready to login the user. To do it, send POST request with provider name and code:

    POST /api/login/social/session/

    with data (form data or json)

    provider=facebook&code=AQBPBBTjbdnehj51

    Backend will either signin the user, either signup, either return error.

    Sometimes it is more suitable to specify provider in url, not in request body. It is possible, rest-social-auth will understand that. Following request is the same as above:

    POST /api/login/social/session/facebook/

    with data (form data or json)

    code=AQBPBBTjbdnehj51

OAuth 1.0a workflow with rest-social-auth

  1. Front-end needs to make a POST request to your backend with the provider name ONLY:

    POST /api/login/social/

    with data (form data or json):

    provider=twitter

    Or specify provider in url, in that case data will be empty:

    POST /api/login/social/twitter
  2. The backend will return a short-lived oauth_token request token in the response. This can be used by the front-end to perform authentication with the provider.

  3. User confirms. In the case of Twitter, they will then return the following data to your front-end:

    {
      "redirect_state":  "...bHrz2x0wy43",
      "oauth_token"   :  "...AAAAAAAhD5u",
      "oauth_verifier":  "...wDBdTR7CYdR"
    }
  4. Front-end now ready to login the user. To do it, send POST request again with provider name and the oauth_token and oauth_verifier you got from the provider:

    POST /api/login/social/

    with data (form data or json)

    provider=twitter&oauth_token=AQBPBBTjbdnehj51&oauth_verifier=wDBdTR7CYdR

    Backend will either signin the user, or signup, or return an error. Same as in OAuth 2.0, you can specify provider in url, not in body:

    POST /api/login/social/twitter

This flow is the same as described in satellizer. This angularjs module is used in example project.

rest-social-auth purpose

As we can see, our backend must implement resource for signin the user.

Django REST social auth provides means to easily implement such resource.

List of oauth providers

OAuth 1.0 and OAuth 2.0 providers are supported.

Look python-social-auth for full list. Name of provider is taken from corresponding backend.name property of particular backed class in python-social-auth.

For example for facebook backend we see:

class FacebookOAuth2(BaseOAuth2):
    name = 'facebook'

Here are some provider names:

Provider provider name
Facebook facebook
Google google-oauth2
Vkontakte vk-oauth2
Instagram instagram
Github github
Yandex yandex-oauth2
Twitter twitter
Others ...

Settings

Customization

First of all, customization provided by python-social-auth is also avaliable. For example, use nice mechanism of pipeline to do any action you need during login/signin.

Second, you can override any method from current package. Specify serializer for each view by subclassing the view.

To do it

Check the code of the lib, there is not much of it.

Example

There is an example project.

Facebook, Google and Twitter auth should work, all secret keys are already set.

Example project uses satellizer angularjs module.

Development

Run tests locally

make test

Run tests in all enviroments (can take some time)

make test-tox

Contributors

Thanks to all contributors!