python-social-auth and oauth2 support for django-rest-framework

Overview

Django REST Framework Social OAuth2

This module provides OAuth2 social authentication support for applications in Django REST Framework.

The aim of this package is to help set up social authentication for your REST API. It also helps setting up your OAuth2 provider.

This package relies on python-social-auth and django-oauth-toolkit. You should probably read their docs if you were to go further than what is done here. If you have some hard time understanding OAuth2, you can read a simple explanation here.

Installation

Install with pip:

pip install django-rest-framework-social-oauth2

Add the following to your INSTALLED_APPS:

INSTALLED_APPS = (
    ...
    'oauth2_provider',
    'social_django',
    'rest_framework_social_oauth2',
)

Include social auth urls to your urls.py:

urlpatterns = patterns(
    ...
    (r'^auth/', include('rest_framework_social_oauth2.urls')),
)

Add these context processors to your TEMPLATE_CONTEXT_PROCESSORS:

TEMPLATE_CONTEXT_PROCESSORS = (
    ...
    'social_django.context_processors.backends',
    'social_django.context_processors.login_redirect',
)

NB: since Django version 1.8, the TEMPLATE_CONTEXT_PROCESSORS is deprecated, set the 'context_processors' option in the 'OPTIONS' of a DjangoTemplates backend instead:

TEMPLATES = [
    {
        ...
        'OPTIONS': {
            'context_processors': [
                ...
                'social_django.context_processors.backends',
                'social_django.context_processors.login_redirect',
            ],
        },
    }
]

You can then enable the authentication classes for Django REST Framework by default or per view (add or update the REST_FRAMEWORK and AUTHENTICATION_BACKENDS entries in your settings.py)

REST_FRAMEWORK = {
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        ...
        # 'oauth2_provider.ext.rest_framework.OAuth2Authentication',  # django-oauth-toolkit < 1.0.0
        'oauth2_provider.contrib.rest_framework.OAuth2Authentication',  # django-oauth-toolkit >= 1.0.0
        'rest_framework_social_oauth2.authentication.SocialAuthentication',
    ),
}
AUTHENTICATION_BACKENDS = (
    ...
   'rest_framework_social_oauth2.backends.DjangoOAuth2',
   'django.contrib.auth.backends.ModelBackend',
)

The settings of this app are:

  • DRFSO2_PROPRIETARY_BACKEND_NAME: name of your OAuth2 social backend (e.g "Facebook"), defaults to "Django"
  • DRFSO2_URL_NAMESPACE: namespace for reversing URLs

Setting Up a New Application

Go to Django admin and add a new Application with the following configuration:

  • client_id and client_secret should be left unchanged
  • user should be your superuser
  • redirect_uris should be left blank
  • client_type should be set to confidential
  • authorization_grant_type should be set to 'Resource owner password-based'
  • name can be set to whatever you'd like

The installation is done, you can now test the newly configured application.

It is recommended that you read the docs from python-social-auth and django-oauth-toolkit if you would like to go further. If you want to enable a social backend (e.g. Facebook), check the docs of python-social-auth on supported backends and django-social-auth on backend configuration.

Testing the Setup

Now that the installation is done, let's try out the various functionality. We will assume for the following examples that the REST API is reachable on http://localhost:8000.

  • Retrieve a token for a user using curl:

    curl -X POST -d "client_id=<client_id>&client_secret=<client_secret>&grant_type=password&username=<user_name>&password=<password>" http://localhost:8000/auth/token
    

<client_id> and <client_secret> are the keys generated automatically. you can find in the model Application you created.

  • Refresh token:

    curl -X POST -d "grant_type=refresh_token&client_id=<client_id>&client_secret=<client_secret>&refresh_token=<your_refresh_token>" http://localhost:8000/auth/token
    
  • Exchange an external token for a token linked to your app:

    curl -X POST -d "grant_type=convert_token&client_id=<client_id>&client_secret=<client_secret>&backend=<backend>&token=<backend_token>" http://localhost:8000/auth/convert-token
    

<backend> here needs to be replaced by the name of an enabled backend (e.g. "Facebook"). Note that PROPRIETARY_BACKEND_NAME is a valid backend name, but there is no use to do that here. <backend_token> is for the token you got from the service utilizing an iOS app for example.

  • Revoke tokens:

    Revoke a single token:

    curl -X POST -d "client_id=<client_id>&client_secret=<client_secret>&token=<your_token>" http://localhost:8000/auth/revoke-token
    

    Revoke all tokens for a user:

    curl -H "Authorization: Bearer <token>" -X POST -d "client_id=<client_id>" http://localhost:8000/auth/invalidate-sessions
    

Authenticating Requests

As you have probably noticed, we enabled a default authentication backend called SocialAuthentication. This backend lets you register and authenticate your users seamlessly with your REST API.

The class simply retrieves the backend name and token from the Authorization header and tries to authenticate the user using the corresponding external provider. If the user was not yet registered on your app, it will automatically create a new user for this purpose.

Example authenticated request:

curl -H "Authorization: Bearer <backend_name> <backend_token>" http://localhost:8000/route/to/your/view

Integration Examples

For each authentication provider, the top portion of your REST API settings.py file should look like this:

INSTALLED_APPS = (
    ...
    # OAuth
    'oauth2_provider',
    'social_django',
    'rest_framework_social_oauth2',
)

TEMPLATES = [
    {
        ...
        'OPTIONS': {
            'context_processors': [
                ...
                # OAuth
                'social_django.context_processors.backends',
                'social_django.context_processors.login_redirect',
            ],
        },
    }
]

REST_FRAMEWORK = {
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': (
        ...
        # OAuth
        # 'oauth2_provider.ext.rest_framework.OAuth2Authentication',  # django-oauth-toolkit < 1.0.0
        'oauth2_provider.contrib.rest_framework.OAuth2Authentication',  # django-oauth-toolkit >= 1.0.0
        'rest_framework_social_oauth2.authentication.SocialAuthentication',
    )
}

Listed below are a few examples of supported backends that can be used for social authentication.

Facebook Example

To use Facebook as the authorization backend of your REST API, your settings.py file should look like this:

AUTHENTICATION_BACKENDS = (
    # Others auth providers (e.g. Google, OpenId, etc)
    ...

    # Facebook OAuth2
    'social_core.backends.facebook.FacebookAppOAuth2',
    'social_core.backends.facebook.FacebookOAuth2',

    # django-rest-framework-social-oauth2
    'rest_framework_social_oauth2.backends.DjangoOAuth2',

    # Django
    'django.contrib.auth.backends.ModelBackend',
)

# Facebook configuration
SOCIAL_AUTH_FACEBOOK_KEY = '<your app id goes here>'
SOCIAL_AUTH_FACEBOOK_SECRET = '<your app secret goes here>'

# Define SOCIAL_AUTH_FACEBOOK_SCOPE to get extra permissions from Facebook.
# Email is not sent by default, to get it, you must request the email permission.
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
    'fields': 'id, name, email'
}

Remember to add this new Application in your Django admin (see section "Setting up Application").

You can test these settings by running the following command:

curl -X POST -d "grant_type=convert_token&client_id=<client_id>&client_secret=<client_secret>&backend=facebook&token=<facebook_token>" http://localhost:8000/auth/convert-token

This request returns the "access_token" that you should use with every HTTP request to your REST API. What is happening here is that we are converting a third-party access token (<user_access_token>) to an access token to use with your API and its clients ("access_token"). You should use this token on each and further communications between your system/application and your api to authenticate each request and avoid authenticating with Facebook every time.

You can get the ID (SOCIAL_AUTH_FACEBOOK_KEY) and secret (SOCIAL_AUTH_FACEBOOK_SECRET) of your app at https://developers.facebook.com/apps/.

For testing purposes, you can use the access token <user_access_token> from https://developers.facebook.com/tools/accesstoken/.

For more information on how to configure python-social-auth with Facebook visit http://python-social-auth.readthedocs.io/en/latest/backends/facebook.html.

Google Example

To use Google OAuth2 as the authorization backend of your REST API, your settings.py file should look like this:

AUTHENTICATION_BACKENDS = (
    # Others auth providers (e.g. Facebook, OpenId, etc)
    ...

    # Google OAuth2
    'social_core.backends.google.GoogleOAuth2',

    # django-rest-framework-social-oauth2
    'rest_framework_social_oauth2.backends.DjangoOAuth2',

    # Django
    'django.contrib.auth.backends.ModelBackend',
)

# Google configuration
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = <your app id goes here>
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = <your app secret goes here>

# Define SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE to get extra permissions from Google.
SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = [
    'https://www.googleapis.com/auth/userinfo.email',
    'https://www.googleapis.com/auth/userinfo.profile',
]

Remember to add the new Application in your Django admin (see section "Setting up Application").

You can test these settings by running the following command:

curl -X POST -d "grant_type=convert_token&client_id=<django-oauth-generated-client_id>&client_secret=<django-oauth-generated-client_secret>&backend=google-oauth2&token=<google_token>" http://localhost:8000/auth/convert-token

This request returns an "access_token" that you should use with every HTTP requests to your REST API. What is happening here is that we are converting a third-party access token (<user_access_token>) to an access token to use with your API and its clients ("access_token"). You should use this token on each and further communications between your system/application and your API to authenticate each request and avoid authenticating with Google every time.

You can get the ID (SOCIAL_AUTH_GOOGLE_OAUTH2_KEY) and secret (SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET) of your app at https://console.developers.google.com/apis/credentials and more information on how to create one on https://developers.google.com/identity/protocols/OAuth2.

For testing purposes, you can use the access token <user_access_token> from https://developers.google.com/oauthplayground/.

For more information on how to configure python-social-auth with Google visit https://python-social-auth.readthedocs.io/en/latest/backends/google.html#google-oauth2.

Comments
  • Error when try to get access from facebook backend

    Error when try to get access from facebook backend

    Hello first of all thank @PhilipGarnero for your great library. I read about and i love it but i get this error: {"detail":"Invalid token header. Invalid backend" } when i run follow command: curl -H "Authorization: Bearer facebook user_access_token" http://localhost:8000/auth/convert-token Please help me i try to solve this error since 3 days but i fail. please i need your help @PhilipGarnero

    bug 
    opened by gelog93 25
  • Google Oauth2

    Google Oauth2

    Have you ever used this with Google's Oauth2?

    I followed your example to convert a facebook token, and it worked perfectly. However, when I try to use google-oauth2 as the backend, I always get this message:

    {  
       "error_description":"Backend responded with HTTP403: { "error":{  
          "errors":[  
             {  
                "domain":"usageLimits",
                "reason":"dailyLimitExceededUnreg",
                "message":"Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.",
                "extendedHelp":"https://code.google.com/apis/console"
             }
          ],
          "code":403,
          "message":"Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
       }
    }.",
    "error":"invalid_request"
    }
    

    From my settings.py:

    AUTHENTICATION_BACKENDS = (
        # Facebook OAuth2
        'social.backends.facebook.FacebookAppOAuth2',
        'social.backends.facebook.FacebookOAuth2',
    
        # Google OAuth2
        'social.backends.google.GoogleOAuth2',
    
        # django-rest-framework-social-oauth2
        'rest_framework_social_oauth2.backends.DjangoOAuth2',
    
        # django
        'django.contrib.auth.backends.ModelBackend',
    )
    
    SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '***'
    SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '***'
    SOCIAL_AUTH_GOOGLE_OAUTH2_SCOPE = ['email',]
    

    My request looks like this:

    curl -v -X POST -d "grant_type=convert_token&client_id=<client_id_here>&client_secret=<client_secret_here>&backend=google-oauth2&token=<google_token_here>" http://localhost:8000/auth/convert-token
    

    Have you seen anything like this?

    question 
    opened by derektoub 17
  • how to retrieve user from token and able to do curl calls only when admin is logged in

    how to retrieve user from token and able to do curl calls only when admin is logged in

    Hi Philip, I'm little new to DRF and Oauth2. So, this might be a silly question again. I need your help to understand this.

    I've successfully authenticated user from facebook. But I'm not able to validate the same in application. Whenever I hit http://localhost:8000/users/user/1/ I get HTTP 401 Unauthorized Attached views.py for user model. I'm not able to views.txt

    get user from token supplied. So

    Can you help me how to get user from token? Thanks in advance!

    invalid 
    opened by ajay2611 15
  • unsupported_grant_type

    unsupported_grant_type

    I'm trying to authenticate an user following the instructions in the README, but when I request a token for an user, I receive:

    {"error": "unsupported_grant_type"}
    

    In my application the "Authorization grant type" field is "password" value:

    In [1]: from oauth2_provider.models import Application
    
    In [2]: a = Application.objects.get(id=1)
    
    In [11]: a.authorization_grant_type
    Out[11]: u'password'
    

    What I'm doing wrong?

    question wontfix 
    opened by rodolphopivetta 14
  • Running the facebook tutorial and getting

    Running the facebook tutorial and getting "Invalid client_id parameter value."

    I'm putting in the right client id and secret after following the fb example on the page and I keep getting "{"error_description": "Invalid client_id parameter value.", "error": "invalid_request"}.

    Any ideas?

    question 
    opened by dsrizvi 14
  • Authentication error while testing my application.

    Authentication error while testing my application.

    Hi,

    I am using django-rest-framework-social-oauth2 along with django rest framework to develop an app. All was running well and good but when it came to testing the code, I found a bizzare error.

    At the start of my testing code, I created a superuser and an application registered to him. Afterwards, I called the /auth/convert-token endpoint with my facebook access token. While it did return me an access_token, subsequent calling of other endpoints with this returned access_token always failed with the message,

    "Authentication credentials were not provided"

    I tried to investigate it by placing breakpoints in the function create_token of rest_framework_social_oauth2.views where I found that the AccessToken.objects.create call was not actually creating a new row in my test database (I found this by placing breakpoints after the call and investigating with external database viewer).

    Note that this behavior is explicit to the testing code.

    Can you please tell me what seems to be the problem here?

    I am using django 1.8 with postgresql as backend and django-oauth-toolkit 0.8.1 and django-rest-framework-social-oauth2 0.0.8

    invalid 
    opened by PraveshKoirala 14
  • Grant type error running user login (with username/password)

    Grant type error running user login (with username/password)

    I'm running a command like that to get the credentials of a existing user:

    curl -X POST -d "client_id=3X7OViEQ3H3VTW7D5sV86cE6MHxGLFKbBbgXikJe&client_secret=wXXb8iPbuJxIK3ckCVkBj0nQDn7sdFOK4SfQK55B0NcexvNIaGsXI0xwWK1lGRXjUa4SIgyzRBfCjkWfnHaex3vcHiIwykZTgsOuQsMNHnTPCrMXQMXy7NkZA8hE4NAF&grant_type=password&[email protected]&password=admin123" http://localhost:8000/api/v1/auth/token/
    

    I verified the client_id/client_secret and they are right, and the grant type also. (In the app the Authorization grant type and Client type are set to Confidential and Resource owner password-based). However I'm always getting this error:

    {"error_description":"Invalid credentials given.","error":"invalid_grant"}
    

    The social login is working normally with facebook. But the login/password is not. Is this problem related to bad configuration?

    invalid 
    opened by JoabMendes 11
  • NotImplementedError on authentication while trying to access APIView method

    NotImplementedError on authentication while trying to access APIView method

    Hi, I just setup django-rest-framework-social-oauth2, converted a token succefully(from facebook token to my app token) but when I'm trying to access an @apiview, it keep me showing this error:

    
    File "/Library/Python/2.7/site-packages/social/backends/base.py", line 85, in pipeline
        out = self.run_pipeline(pipeline, pipeline_index, *args, **kwargs)
      File "/Library/Python/2.7/site-packages/social/backends/base.py", line 112, in run_pipeline
        result = func(*args, **out) or {}
      File "/Library/Python/2.7/site-packages/social/pipeline/social_auth.py", line 6, in social_details
        return {'details': dict(backend.get_user_details(response), **details)}
      File "/Library/Python/2.7/site-packages/social/backends/base.py", line 165, in get_user_details
        raise NotImplementedError('Implement in subclass')
    NotImplementedError: Implement in subclass
    

    I am using this header "Authorization: Bearer MyApp <converted_token>".

    Here is my view:

    class VoucherList(APIView):
        permission_classes = (IsAuthenticated,)
        """
        List all user's vouchers
        """
        def get(self, request, format=None):
            vouchers = Voucher.objects.filter(owner=request.user)
            serializer = VoucherSerializer(vouchers, many=True)
            return Response(serializer.data)
    

    And here is my current settings:

    """
    Django settings for MyApp project.
    
    Generated by 'django-admin startproject' using Django 1.9.2.
    
    For more information on this file, see
    https://docs.djangoproject.com/en/1.9/topics/settings/
    
    For the full list of settings and their values, see
    https://docs.djangoproject.com/en/1.9/ref/settings/
    """
    
    import os
    
    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    
    
    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
    
    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = 'mhqk8#$_mq#+btw4vx^g4#e4(o^38$539)672z4wl7hjetij3@'
    
    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = True
    
    ALLOWED_HOSTS = []
    
    
    # Application definition
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'rest_framework',
        'oauth2_provider',
        'social.apps.django_app.default',
        'rest_framework_social_oauth2',
        'djangobower',
        'api',
        'website',
    ]
    
    PROPRIETARY_BACKEND_NAME = 'MyApp'
    
    AUTHENTICATION_BACKENDS = (
    
        # Facebook OAuth2
        'social.backends.facebook.FacebookAppOAuth2',
        'social.backends.facebook.FacebookOAuth2',
    
        # django-rest-framework-social-oauth2
        'rest_framework_social_oauth2.backends.DjangoOAuth2',
    
        # Django
        'django.contrib.auth.backends.ModelBackend',
    )
    
    SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
    SOCIAL_AUTH_FACEBOOK_KEY = '*****'
    SOCIAL_AUTH_FACEBOOK_SECRET = '*****'
    SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'
    
    MIDDLEWARE_CLASSES = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    
    ROOT_URLCONF = 'myapp.urls'
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                    'social.apps.django_app.context_processors.backends',
                    'social.apps.django_app.context_processors.login_redirect',
                ],
            },
        },
    ]
    
    
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            # OAuth
            'oauth2_provider.ext.rest_framework.OAuth2Authentication',
            'rest_framework_social_oauth2.authentication.SocialAuthentication',
        )
    }
    
    WSGI_APPLICATION = 'myapp.wsgi.application'
    
    
    # Database
    # https://docs.djangoproject.com/en/1.9/ref/settings/#databases
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }
    
    
    # Password validation
    # https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
    
    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]
    
    # Internationalization
    # https://docs.djangoproject.com/en/1.9/topics/i18n/
    
    LANGUAGE_CODE = 'en-us'
    
    TIME_ZONE = 'UTC'
    
    USE_I18N = True
    
    USE_L10N = True
    
    USE_TZ = True
    
    
    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/1.9/howto/static-files/
    
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'static')
    
    #Media files (JPEG, PNG, VIDEOS)
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    
    # Django bower settings
    #
    STATICFILES_FINDERS = (
        'django.contrib.staticfiles.finders.FileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
        'djangobower.finders.BowerFinder',
    )
    
    BOWER_COMPONENTS_ROOT = os.path.abspath(os.path.join(BASE_DIR, 'components'))
    
    BOWER_INSTALLED_APPS = (
        'bootstrap-material-design',
        'moment',
        'lrsjng/jquery-qrcode'
    )
    
    
    question 
    opened by adheus 9
  • Intermittent issue

    Intermittent issue "Invalid token header. No credentials provided."

    Hi all,

    I followed the instructions on github and got up and running in no time. Everything was working well but for no apparent reason it seems to intermittently fail to detect the 'Authentication' Header and gives the following error;

    "detail": "Invalid token header. No credentials provided."

    I am exchanging a facebook token for a DOT one as per the instructions for social signin and I successfully get a token back. But subsequent calls to my endpoints with the DOT token is failing.

    It's quite strange because it really does seem intermittent and seems to work fine one moment and then every endpoint is rejected the next.

    Any suggestions would be much appreciated.

    Env: Python 3.4.3 Django==1.10.5 django-oauth-toolkit==0.12.0 djangorestframework==3.5.3 django-rest-framework-social-oauth2==1.0.5

    #Settings Snippet

    INSTALLED_APPS = [
        <snip>
    
        'oauth2_provider',
        'social_django',
        'rest_framework_social_oauth2',
    ]
    
    OAUTH2_PROVIDER = {
        'OAUTH2_BACKEND_CLASS': 'oauth2_provider.oauth2_backends.JSONOAuthLibCore'
    }
    
    #### Move to Config
    SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL = True
    
    ## Facebook configuration
    SOCIAL_AUTH_FACEBOOK_KEY = 'snip'
    SOCIAL_AUTH_FACEBOOK_SECRET = 'snip'
    
    # Define SOCIAL_AUTH_FACEBOOK_SCOPE to get extra permissions from facebook. Email is not sent by default, to get it, you must request the email permission:
    SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
    SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
        'fields': 'id, name, email'
    }
    
    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.IsAuthenticated',
        ],
        'PAGE_SIZE': 15,
        'DATETIME_FORMAT': "%d-%b-%y",
        'COERCE_DECIMAL_TO_STRING': False,
        'DEFAULT_AUTHENTICATION_CLASSES': (
            # OAuth
            'oauth2_provider.ext.rest_framework.OAuth2Authentication',
            'rest_framework_social_oauth2.authentication.SocialAuthentication',
        )
    }
    
    AUTHENTICATION_BACKENDS = (
        # Facebook OAuth2
        'social_core.backends.facebook.FacebookAppOAuth2',
        'social_core.backends.facebook.FacebookOAuth2',
    
        # #Social Auth
        'rest_framework_social_oauth2.backends.DjangoOAuth2',
        # Django
        'django.contrib.auth.backends.ModelBackend',
    )
    
    MIDDLEWARE = [
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'django.middleware.locale.LocaleMiddleware',
        'oauth2_provider.middleware.OAuth2TokenMiddleware',
    ]
    
    ......
    
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': ['templates'],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.template.context_processors.i18n',
                    'django.contrib.messages.context_processors.messages',
                    # Social Auth
                    'social_django.context_processors.backends',
                    'social_django.context_processors.login_redirect',
                ],
            },
        },
    ]
    
    invalid 
    opened by daesu 8
  • AttributeError: 'generator' object has no attribute 'session'

    AttributeError: 'generator' object has no attribute 'session'

    Ok, this is a really weird error and it passes through a few modules.

    When I try to POST to auth/convert-token, like so:

    curl -X POST -d "grant_type=convert_token&client_id=<client_id>&client_secret=<client_secret>&backend=facebook&token=<token>" http://localhost:8000/auth/convert-token
    

    I get the error: AttributeError: 'generator' object has no attribute 'session'

    I notice that ConvertTokenView calls the OAuthLibMixin for create_token_response:

    (see rest_framework_social_oauth2/views.py line 34)

    class ConvertTokenView(CsrfExemptMixin, OAuthLibMixin, View):
        """
        Implements an endpoint to provide access tokens
        The endpoint is used in the following flows:
        * Authorization code
        * Password
        * Client credentials
        """
        server_class = SocialTokenServer
        validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS
        oauthlib_backend_class = KeepRequestCore
    
        def post(self, request, *args, **kwargs):
            url, headers, body, status = self.create_token_response(request)
            response = HttpResponse(content=body, status=status)
    
            for k, v in headers.items():
                response[k] = v
            return response
    

    This leads down a winding path that eventually gets to oauthlib. In the code below, the header value for 'Django-request-object' goes from being a WSGIRequest to a generator without any output, the result of the encode method here:

    (see oauthlib/common.py line 380) self.headers = CaseInsensitiveDict(encode(headers or {}))

    The problem, then, is that by the time the request gets back to the SocialTokenGrant class in your library here:

    (see rest_framework_social_oauth2/oauth2_grants.py line 80)

            # TODO: Find a better way to pass the django request object
            strategy = load_strategy(request=request.headers["Django-request-object"])
    

    It's no longer a real request. And, a few calls down the chain in python-social-auth, it blows up:

    (see social/strategies/django_strategy.py line 30

    class DjangoStrategy(BaseStrategy):
        DEFAULT_TEMPLATE_STRATEGY = DjangoTemplateStrategy
    
        def __init__(self, storage, request=None, tpl=None):
            self.request = request
            self.session = request.session if request else {}
            super(DjangoStrategy, self).__init__(storage, tpl)
    

    and produces the error: AttributeError: 'generator' object has no attribute 'session'

    Any idea how to work around this? Is there another way to get back to the Django request without having to rely on the headers coming through?

    Here are the relevant parts of my requirements.txt:

    Django==1.8.1
    djangorestframework==3.1.2
    six==1.9.0
    wsgiref==0.1.2
    python-social-auth==0.2.12
    django-oauth-toolkit==0.9.0
    django-rest-framework-social-oauth2==1.0.0
    

    and settings.py

    AUTHENTICATION_BACKENDS = (
        # Facebook OAuth2
        'social.backends.facebook.FacebookAppOAuth2',
        'social.backends.facebook.FacebookOAuth2',
    
        # django-rest-framework-social-oauth2
        'rest_framework_social_oauth2.backends.DjangoOAuth2',
    
        # Django
        'django.contrib.auth.backends.ModelBackend',
    )
    
    
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
            'oauth2_provider.ext.rest_framework.OAuth2Authentication',
            'rest_framework_social_oauth2.authentication.SocialAuthentication',
        ),
        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.IsAuthenticated',
        ),
    }
    
    SOCIAL_AUTH_FACEBOOK_KEY = env_var('SOCIAL_AUTH_FACEBOOK_KEY')
    SOCIAL_AUTH_FACEBOOK_SECRET = env_var('SOCIAL_AUTH_FACEBOOK_SECRET')
    
    TEMPLATE_CONTEXT_PROCESSORS = (
        'django.contrib.auth.context_processors.auth',
        'django.template.context_processors.debug',
        'django.template.context_processors.i18n',
        'django.template.context_processors.media',
        'django.template.context_processors.static',
        'django.template.context_processors.tz',
        'django.contrib.messages.context_processors.messages',
        'social.apps.django_app.context_processors.backends',
        'social.apps.django_app.context_processors.login_redirect',
    )
    
    MIDDLEWARE_CLASSES = (
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'django.middleware.security.SecurityMiddleware',
        'social.apps.django_app.middleware.SocialAuthExceptionMiddleware',
    )
    
    bug 
    opened by mikeedwards 8
  • Inconsistency with handling client credentials passed in request

    Inconsistency with handling client credentials passed in request

    Hi

    I see that I need to pass client_id and client_secret in the request always for /auth/token/ and /auth/revoke-token/ endpoints, basically the ones which are from oauth2_provider, But the /auth/convert-token/ and /auth/invalidate-sessions/ endpoints, views for both of which are defined in this lib itself, seem to work even when client_id and client_secret is not passed!

    How do we make sure that client credentials are always passed in the request ?

    enhancement 
    opened by ashishtajane 8
  • How to associate an existing user with multiple social accounts (different emails)? [DRF_SOCIAL_OAUTH2]

    How to associate an existing user with multiple social accounts (different emails)? [DRF_SOCIAL_OAUTH2]

    0

    I'm trying to associate user with multiple social accounts in Django Rest Framework. After user login, user can associate with social accounts (it doesn't matter same email or different email). Now I am using the library drf-social-oauth2. I have done signIn/singUp part. According to Social_Auth_Pipeline [https://python-social-auth.readthedocs.io/en/latest/pipeline.html] I added this code to associate user

    SOCIAL_AUTH_PIPELINE = ( 'social_core.pipeline.social_auth.social_details', 'social_core.pipeline.social_auth.social_uid', 'social_core.pipeline.social_auth.auth_allowed', 'social_core.pipeline.social_auth.social_user', 'social_core.pipeline.user.get_username', 'social_core.pipeline.social_auth.associate_by_email', 'social_core.pipeline.user.create_user', 'social_core.pipeline.social_auth.associate_user', 'social_core.pipeline.social_auth.load_extra_data', 'social_core.pipeline.user.user_details', )

    The endpoint "http://localhost:8000/auth/convert-token" can handle the singin/singup using social auth.(eg. Facebook, Google) social_core.pipeline.social_auth.associate_by_email managed to associate the user if same email.

    My Question is How can I connect/associate Social Accounts (* different email/same email) with current login user using drf_social_oauth2?

    Do I need to add field in user table to associate? OR Do I need to add something to setting.py?... Please advise me. Thank you.

    opened by sawohnmarshwe 0
  • I am getting a 401 Error (Unauthorized) and Uncaught (in promise) Error. Same is working fine on PostMan

    I am getting a 401 Error (Unauthorized) and Uncaught (in promise) Error. Same is working fine on PostMan

    We seem to be getting a 401 error with the new django admin with drf social oauth2. But working fine on Postman ** We are getting a 401 Error (Unauthorized) when we pass the clientid and client_secret through browser. The same clientID and secret returns the tokens on PostMan. error1 error2 error3 error4 error5

    Go to Login page where the signin button is' Click on 'Signin' Scroll down to 'Console' POST http://127.0.0.1:8000/auth/token/ 401 (Unauthorized) and Uncaught (in promise) Error: Request failed with status code 401 Expected behavior An object with access and refresh token

    opened by Madhu25666 0
  • why im getting invalid client error while trying to post in postman

    why im getting invalid client error while trying to post in postman

    hi i was trying to post in postman using some parameters like client_id and client secret and token which i got it from Facebook[enter image description here][2] developer app #here is my reqest url:http://localhost:8000/api/social/convert-token?grant_type=convert_token&client_id=sdklhsjgvdshfuahhddkaj37637utydew7&client_secret=dgshjhsdfkgaskflj8363589klsskjnlksfjnljhfjmj83889ij&backend=facebook&token=lkdfjlkjhdsfkljhbdsncvkjdsh763uhkdjcbgjhxsgckjdsh7ytfgklfclkfoit76ejvmljfdlkjndsi736uihd

    #postman

    #also my setting.py

    from pathlib import Path

    Build paths inside the project like this: BASE_DIR / 'subdir'.

    BASE_DIR = Path(file).resolve().parent.parent

    Quick-start development settings - unsuitable for production

    See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/

    SECURITY WARNING: keep the secret key used in production secret!

    SECURITY WARNING: don't run with debug turned on in production!

    DEBUG = True

    ALLOWED_HOSTS = []

    Application definition

    INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'coreapp', 'cloudinary', 'oauth2_provider', 'social_django', 'rest_framework_social_oauth2', ]

    MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]

    ROOT_URLCONF = 'foodhub.urls'

    TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', 'social_django.context_processors.backends', 'social_django.context_processors.login_redirect', ], }, }, ]

    WSGI_APPLICATION = 'foodhub.wsgi.application'

    Database

    https://docs.djangoproject.com/en/3.2/ref/settings/#databases

    DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', } }

    Password validation

    https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators

    AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ]

    Internationalization

    https://docs.djangoproject.com/en/3.2/topics/i18n/

    LANGUAGE_CODE = 'en-us'

    TIME_ZONE = 'UTC'

    USE_I18N = True

    USE_L10N = True

    USE_TZ = True

    Static files (CSS, JavaScript, Images)

    https://docs.djangoproject.com/en/3.2/howto/static-files/

    STATIC_URL = '/static/'

    Default primary key field type

    https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

    DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

    LOGIN_REDIRECT_URL='/' import cloudinary import cloudinary.uploader import cloudinary.api

    #config heroku import django_heroku django_heroku.settings(locals())

    #CSRF_TRUSTED_ORIGINS =['http://127.0.0.1:8000/restaurant/sign_up']

    AUTHENTICATION_BACKENDS = ( 'social_core.backends.facebook.FacebookOAuth2', 'django.contrib.auth.backends.ModelBackend', )

    Facebook configuration

    SOCIAL_AUTH_FACEBOOK_KEY = 'FACEBOOK_KEY' SOCIAL_AUTH_FACEBOOK_SECRET = 'facebook_secret'

    Define SOCIAL_AUTH_FACEBOOK_SCOPE to get extra permissions from Facebook.

    Email is not sent by default, to get it, you must request the email permission.

    SOCIAL_AUTH_FACEBOOK_SCOPE = ['email'] SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = { 'fields': 'id, name, email,picture.type(large)'

    the url.py

    from re import template from django.contrib import admin from django.urls import path,include from django.contrib.auth import views as auth_views from django.contrib.auth import views from coreapp import views

    urlpatterns = [ #Web View - Admin path('admin/', admin.site.urls), path('', views.home,name='home'),

    #web View - Restaurant
    path('restaurant/sign_in/',auth_views.LoginView.as_view(template_name='restaurant/sign_in.html'),name='restaurant_sign_in'),
    path('restaurant/sign_out/',auth_views.LogoutView.as_view(next_page='/'),name='restaurant_sign_out'),
    path('restaurant/sign_up', views.restaurant_sign_up,name='restaurant_sign_up'),
     path('restaurant/', views.restaurant_home,name='restaurant_home'),
     
     #APIs
     # /convert-token (sing_in/sing_up) ,/revoke-token(sign-out)
    path('api/social/', include('rest_framework_social_oauth2.urls')),
    

    ]

    opened by galomari 1
  • Fixbug Fixing

    Fixbug Fixing "urls" to support Django 4, older versions Fixes #254

    This helps with Django4.0 and would also work with the older version.

    Replace

    from django.conf.urls import url, include
    

    To

    from django.conf.urls import include
    try:
        from django.conf.urls import url
    except ImportError:
        from django.urls import re_path as url
    
    opened by islam-kamel 0
  • Quick fix to enable this package to work with Django 4 and the older versions

    Quick fix to enable this package to work with Django 4 and the older versions

    Hi There, would it be possible to add this line of code within the "rest_framework_social_oauth2/urls.py" file. This helps with Django4.0 and would also work with the older version.

    Replace

    from django.conf.urls import url, include
    
    

    To

    from django.conf.urls import include
    try:
        from django.conf.urls import url
    except ImportError:
        from django.urls import re_path as url
    
    
    
    opened by vigneshwrn9 1
  • Change django urls import path in case of ImportError

    Change django urls import path in case of ImportError

    Ideally we should decide which module to import based on the Django version, but this is a stop-gap solution to get things running for Django 4 onwards.

    opened by xennygrimmato 5
Owner
null
Django-react-firebase-auth - A web app showcasing OAuth2.0 + OpenID Connect using Firebase, Django-Rest-Framework and React

Demo app to show Django Rest Framework working with Firebase for authentication

Teshank Raut 6 Oct 13, 2022
API with high performance to create a simple blog and Auth using OAuth2 ⛏

DogeAPI API with high performance built with FastAPI & SQLAlchemy, help to improve connection with your Backend Side to create a simple blog and Cruds

Yasser Tahiri 111 Jan 5, 2023
A full Rest-API With Oauth2 and JWT for request & response a JSON file Using FastAPI and SQLAlchemy 🔑

Pexon-Rest-API A full Rest-API for request & response a JSON file, Building a Simple WorkFlow that help you to Request a JSON File Format and Handling

Yasser Tahiri 15 Jul 22, 2022
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 878 Jan 4, 2023
Django Auth Protection This package logout users from the system by changing the password in Simple JWT REST API.

Django Auth Protection Django Auth Protection This package logout users from the system by changing the password in REST API. Why Django Auth Protecti

Iman Karimi 5 Oct 26, 2022
Social auth made simple

Python Social Auth Python Social Auth is an easy-to-setup social authentication/registration mechanism with support for several frameworks and auth pr

Matías Aguirre 2.8k Dec 24, 2022
Social auth made simple

Python Social Auth Python Social Auth is an easy-to-setup social authentication/registration mechanism with support for several frameworks and auth pr

Matías Aguirre 2.8k Dec 24, 2022
User-related REST API based on the awesome Django REST Framework

Django REST Registration User registration REST API, based on Django REST Framework. Documentation Full documentation for the project is available at

Andrzej Pragacz 399 Jan 3, 2023
JSON Web Token Authentication support for Django REST Framework

REST framework JWT Auth Notice This project is currently unmaintained. Check #484 for more details and suggested alternatives. JSON Web Token Authenti

José Padilla 3.2k Dec 31, 2022
JSON Web Token Authentication support for Django REST Framework

REST framework JWT Auth JSON Web Token Authentication support for Django REST Framework Overview This package provides JSON Web Token Authentication s

Styria Digital Development 178 Jan 2, 2023
Foundation Auth Proxy is an abstraction on Foundations' authentication layer and is used to authenticate requests to Atlas's REST API.

foundations-auth-proxy Setup By default the server runs on http://0.0.0.0:5558. This can be changed via the arguments. Arguments: '-H' or '--host': ho

Dessa - Open Source 2 Jul 3, 2020
FastAPI extension that provides JWT Auth support (secure, easy to use, and lightweight)

FastAPI JWT Auth Documentation: https://indominusbyte.github.io/fastapi-jwt-auth Source Code: https://github.com/IndominusByte/fastapi-jwt-auth Featur

Nyoman Pradipta Dewantara 468 Jan 1, 2023
A Python inplementation for OAuth2

OAuth2-Python Discord Inplementation for OAuth2 login systems. This is a simple Python 'app' made to inplement in your programs that require (shitty)

Prifixy 0 Jan 6, 2022
OAuth2 goodies for the Djangonauts!

Django OAuth Toolkit OAuth2 goodies for the Djangonauts! If you are facing one or more of the following: Your Django app exposes a web API you want to

Jazzband 2.7k Jan 1, 2023
OAuth2 goodies for the Djangonauts!

Django OAuth Toolkit OAuth2 goodies for the Djangonauts! If you are facing one or more of the following: Your Django app exposes a web API you want to

Jazzband 2.7k Dec 31, 2022
Provide OAuth2 access to your app

django-oauth2-provider django-oauth2-provider is a Django application that provides customizable OAuth2-authentication for your Django projects. Docum

Caffeinehit 334 Jul 27, 2022
A wagtail plugin to replace the login by an OAuth2.0 Authorization Server

Wagtail OAuth2.0 Login Plugin to replace Wagtail default login by an OAuth2.0 Authorization Server. What is wagtail-oauth2 OAuth2.0 is an authorizatio

Gandi 7 Oct 7, 2022
Basic auth for Django.

Basic auth for Django.

bichanna 2 Mar 25, 2022
Auth-Starters - Different APIs using Django & Flask & FastAPI to see Authentication Service how its work

Auth-Starters Different APIs using Django & Flask & FastAPI to see Authentication Service how its work, and how to use it. This Repository based on my

Yasser Tahiri 7 Apr 22, 2022