[Python-modules-commits] [python-social-auth] 12/131: Add support for Untappd as an OAuth v2 backend

Wolfgang Borgert debacle at moszumanska.debian.org
Sat Dec 24 15:16:56 UTC 2016


This is an automated email from the git hooks/post-receive script.

debacle pushed a commit to tag v0.2.20
in repository python-social-auth.

commit 57501b129ad3e5826333fa74889bf911a61c4cca
Author: Scott Vitale <svvitale at gmail.com>
Date:   Mon Apr 11 20:13:18 2016 -0600

    Add support for Untappd as an OAuth v2 backend
---
 README.rst                 |   2 +
 docs/backends/index.rst    |   1 +
 docs/backends/untappd.rst  |  27 ++++++++++++
 social/backends/untappd.py | 100 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 130 insertions(+)

diff --git a/README.rst b/README.rst
index ec4e25a..20c17ce 100644
--- a/README.rst
+++ b/README.rst
@@ -123,6 +123,7 @@ or current ones extended):
     * Twilio_ Auth
     * Twitter_ OAuth1
     * Uber_ OAuth2
+    * Untappd_ OAuth2
     * VK.com_ OpenAPI, OAuth2 and OAuth2 for Applications
     * Weibo_ OAuth2
     * Withings_ OAuth1
@@ -325,3 +326,4 @@ check `django-social-auth LICENSE`_ for details:
 .. _PixelPin: http://pixelpin.co.uk
 .. _Zotero: http://www.zotero.org/
 .. _Pinterest: https://www.pinterest.com
+.. _Untappd: https://untappd.com/
diff --git a/docs/backends/index.rst b/docs/backends/index.rst
index 97cf5fb..819c227 100644
--- a/docs/backends/index.rst
+++ b/docs/backends/index.rst
@@ -140,6 +140,7 @@ Social backends
    twitch
    twitter
    uber
+   untappd
    vend
    vimeo
    vk
diff --git a/docs/backends/untappd.rst b/docs/backends/untappd.rst
new file mode 100644
index 0000000..bb1157a
--- /dev/null
+++ b/docs/backends/untappd.rst
@@ -0,0 +1,27 @@
+Untappd
+=======
+
+Untappd uses OAuth v2 for Authentication, check the `official docs`_.
+
+- Create an app by filling out the form here: `Add App`_
+
+- Apps are approved on a one-by-one basis, so you'll need to wait a few days to get your client ID and secret.
+
+- Fill ``Client ID`` and ``Client Secret`` values in the settings::
+
+        SOCIAL_AUTH_UNTAPPD_KEY = '<App UID>'
+        SOCIAL_AUTH_UNTAPPD_SECRET = '<App secret>'
+
+- Add the backend to the ``AUTHENTICATION_BACKENDS`` setting::
+
+        AUTHENTICATION_BACKENDS = (
+            ...
+            'social.backends.untappd.UntappdOAuth2',
+            ...
+        )
+
+- Then you can start using ``{% url social:begin 'untappd' %}`` in
+  your templates
+
+.. _official docs: https://untappd.com/api/docs
+.. _Add App: https://untappd.com/api/register?register=new
diff --git a/social/backends/untappd.py b/social/backends/untappd.py
new file mode 100644
index 0000000..8d5b71d
--- /dev/null
+++ b/social/backends/untappd.py
@@ -0,0 +1,100 @@
+import requests
+
+from social.backends.oauth import BaseOAuth2
+from social.exceptions import AuthFailed
+from social.utils import handle_http_errors
+
+
+class UntappdOAuth2(BaseOAuth2):
+    """Untappd OAuth2 authentication backend"""
+    name = 'untappd'
+    AUTHORIZATION_URL = 'https://untappd.com/oauth/authenticate/'
+    ACCESS_TOKEN_URL = 'https://untappd.com/oauth/authorize/'
+    BASE_API_URL = 'https://api.untappd.com'
+    USER_INFO_URL = BASE_API_URL + '/v4/user/info/'
+    ACCESS_TOKEN_METHOD = 'GET'
+    STATE_PARAMETER = False
+    REDIRECT_STATE = False
+    EXTRA_DATA = [
+        ('id', 'id'),
+        ('bio', 'bio'),
+        ('date_joined', 'date_joined'),
+        ('location', 'location'),
+        ('url', 'url'),
+        ('user_avatar', 'user_avatar'),
+        ('user_avatar_hd', 'user_avatar_hd'),
+        ('user_cover_photo', 'user_cover_photo')
+    ]
+
+    def auth_params(self, state=None):
+        client_id, client_secret = self.get_key_and_secret()
+        params = {
+            'client_id': client_id,
+            'redirect_url': self.get_redirect_uri(),
+            'response_type': self.RESPONSE_TYPE
+        }
+        return params
+
+    def process_error(self, data):
+        """ All errors from Untappd are contained in the 'meta' key of the response. """
+        response_code = data.get('meta', {}).get('http_code')
+        if response_code is not None and response_code != requests.codes.ok:
+            raise AuthFailed(self, data['meta']['error_detail'])
+
+    @handle_http_errors
+    def auth_complete(self, *args, **kwargs):
+        """Completes login process, must return user instance"""
+        client_id, client_secret = self.get_key_and_secret()
+        code = self.data.get('code')
+
+        self.process_error(self.data)
+
+        # Untapped sends the access token request with URL parameters, not a body
+        response = self.request_access_token(
+            self.access_token_url(),
+            method=self.ACCESS_TOKEN_METHOD,
+            params={
+                'response_type': 'code',
+                'code': code,
+                'client_id': client_id,
+                'client_secret': client_secret,
+                'redirect_url': self.get_redirect_uri()
+            }
+        )
+
+        self.process_error(response)
+
+        # Both the access_token and the rest of the response are buried in the 'response' key
+        return self.do_auth(response['response']['access_token'], response=response['response'],
+                            *args, **kwargs)
+
+    def get_user_details(self, response):
+        """Return user details from an Untappd account"""
+        # Start with the user data as it was returned
+        user_data = response['user']
+
+        # Make a few updates to match expected key names
+        user_data.update({
+            'username': user_data.get('user_name'),
+            'email': user_data.get('settings', {}).get('email_address', ''),
+            'first_name': user_data.get('first_name'),
+            'last_name': user_data.get('last_name'),
+            'fullname': user_data.get('first_name') + ' ' + user_data.get('last_name')
+        })
+        return user_data
+
+    def get_user_id(self, details, response):
+        """Return a unique ID for the current user, by default from server
+        response."""
+        return response['user'].get(self.ID_KEY)
+
+    def user_data(self, access_token, *args, **kwargs):
+        """Loads user data from service"""
+        response = self.get_json(self.USER_INFO_URL, params={
+            'access_token': access_token,
+            'compact': 'true'
+        })
+        self.process_error(response)
+
+        # The response data is buried in the 'response' key
+        return response['response']

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-social-auth.git



More information about the Python-modules-commits mailing list