RealmTeam / django-rest-framework-social-oauth2

python-social-auth and oauth2 support for django-rest-framework
MIT License
1.06k stars 191 forks source link

Adding a Custom Backed to python-social-auth #200

Closed Chitrank-Dixit closed 5 years ago

Chitrank-Dixit commented 5 years ago

I am trying to add a custom backend and here is the code. I had copied it from Google backend.

class BaseMyAuthAuth(object):
    def get_user_id(self, details, response):
        """Use google email as unique id"""
        if self.setting('USE_UNIQUE_USER_ID', False):
            if 'sub' in response:
                return response['sub']
            else:
                return response['id']
        else:
            return details['email']

    def get_user_details(self, response):
        """Return user details from Google API account"""
        if 'username' in response:
            email = response['username']
        else:
            email = ''

        name, given_name, family_name = (
            response.get('name', ''),
            response.get('given_name', ''),
            response.get('family_name', ''),
        )

        fullname, first_name, last_name = self.get_user_names(
            name, given_name, family_name
        )
        return {'username': email.split('@', 1)[0],
                'email': email,
                'fullname': fullname,
                'first_name': first_name,
                'last_name': last_name}

class BaseMyAuthOAuth2API(BaseMyAuthAuth):
    def user_data(self, access_token, *args, **kwargs):
        """Return user data from Google API"""
        url = urljoin(self.API_URL, '/oauth/me')
        return self.get_json(
            url,
            headers={
                'Authorization': 'Bearer %s' % access_token,
            },
        )

    def revoke_token_params(self, token, uid):
        return {'token': token}

    def revoke_token_headers(self, token, uid):
        return {'Content-type': 'application/json'}

class MyAuthOAuth2(BaseMyAuthOAuth2API, BaseOAuth2):
    """Google OAuth2 authentication backend"""
    name = 'myauth'
    REDIRECT_STATE = False
    API_URL = settings.AUTH_URL
    AUTHORIZATION_URL = settings.AUTH_AUTHORIZE_URL
    ACCESS_TOKEN_URL = settings.AUTH_ACCESS_TOKEN_URL
    ACCESS_TOKEN_METHOD = 'POST'
    # The order of the default scope is important
    #DEFAULT_SCOPE = ['openid', 'email', 'profile']
    EXTRA_DATA = [
        ('refresh_token', 'refresh_token', True),
        ('expires_in', 'expires'),
        ('token_type', 'token_type', True)
    ]

It runs well and fetches all the user data needed, but after that it always try to create a new user, on the other hand. If we see Google backend does not create a new user if the user already exists.

My custom backend gives me issue on this file at path

/venv/lib/python3.6/site-packages/django/contrib/auth/__init__.py

        try:
            user = backend.authenticate(request, **credentials)
        except PermissionDenied:
            # This backend says to stop in our tracks - this user should not be allowed in at all.
            break

and google backend goes to different path /venv/lib/python3.6/site-packages/rest_framework_social_oauth2/oauth2_grants.py

        try:
            user = backend.do_auth(access_token=request.token)
        except requests.HTTPError as e:
            raise errors.InvalidRequestError(
                description="Backend responded with HTTP{0}: {1}.".format(e.response.status_code,
                                                                          e.response.text),
                request=request)

this is the difference I have found out so far.

PhilipGarnero commented 5 years ago

I can't really help you out on this one, try to check with python social auth how you should develop your backend. This library handles only the link between third party backends and tokens not user creation.