From c963bc40632d365fda28872327d5249f92118e79 Mon Sep 17 00:00:00 2001 From: Vadym Zakovinko Date: Mon, 28 Feb 2011 19:07:19 +0200 Subject: [PATCH] added linkedin support --- .gitignore | 1 + example/settings.py | 1 + example/templates/home.html | 1 + social_auth/backends/linkedin.py | 77 ++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+) create mode 100644 social_auth/backends/linkedin.py diff --git a/.gitignore b/.gitignore index f951e96..095d624 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ build/ dist/ django_social_auth.egg-info/ social_auth.egg-info/ +env/ diff --git a/example/settings.py b/example/settings.py index f2e7d7c..8e63d87 100644 --- a/example/settings.py +++ b/example/settings.py @@ -67,6 +67,7 @@ AUTHENTICATION_BACKENDS = ( 'social_auth.backends.google.GoogleOAuthBackend', 'social_auth.backends.google.GoogleBackend', 'social_auth.backends.yahoo.YahooBackend', + 'social_auth.backends.linkedin.LinkedinBackend', 'social_auth.backends.OpenIDBackend', 'social_auth.backends.contrib.livejournal.LiveJournalBackend', 'django.contrib.auth.backends.ModelBackend', diff --git a/example/templates/home.html b/example/templates/home.html index c040c2c..d9dbf51 100644 --- a/example/templates/home.html +++ b/example/templates/home.html @@ -8,6 +8,7 @@ diff --git a/social_auth/backends/linkedin.py b/social_auth/backends/linkedin.py new file mode 100644 index 0000000..931b8f8 --- /dev/null +++ b/social_auth/backends/linkedin.py @@ -0,0 +1,77 @@ +""" +Linkedin OAuth support + +No extra configurations are needed to make this work. +""" +import urlparse +import xml +from xml.etree import ElementTree + +from social_auth.backends import ConsumerBasedOAuth, OAuthBackend, USERNAME + + +LINKEDIN_SERVER = 'linkedin.com' +LINKEDIN_REQUEST_TOKEN_URL = 'https://api.%s/uas/oauth/requestToken' % LINKEDIN_SERVER +LINKEDIN_ACCESS_TOKEN_URL = 'https://api.%s/uas/oauth/accessToken' % LINKEDIN_SERVER +LINKEDIN_AUTHORIZATION_URL = 'https://www.%s/uas/oauth/authenticate' % LINKEDIN_SERVER +LINKEDIN_CHECK_AUTH = 'https://api.%s/v1/people/~' % LINKEDIN_SERVER + + +class LinkedinBackend(OAuthBackend): + """Linkedin OAuth authentication backend""" + name = 'linkedin' + + def get_user_details(self, response): + """Return user details from Linkedin account""" + return { + 'first_name': response['first-name'], + 'last_name': response['last-name'], + 'email': '', # not supplied + } + + +class LinkedinAuth(ConsumerBasedOAuth): + """Linkedin OAuth authentication mechanism""" + AUTHORIZATION_URL = LINKEDIN_AUTHORIZATION_URL + REQUEST_TOKEN_URL = LINKEDIN_REQUEST_TOKEN_URL + ACCESS_TOKEN_URL = LINKEDIN_ACCESS_TOKEN_URL + SERVER_URL = 'api.%s' % LINKEDIN_SERVER + AUTH_BACKEND = LinkedinBackend + SETTINGS_KEY_NAME = 'LINKEDIN_CONSUMER_KEY' + SETTINGS_SECRET_NAME = 'LINKEDIN_CONSUMER_SECRET' + + def user_data(self, access_token): + """Return user data provided""" + request = self.oauth_request(access_token, LINKEDIN_CHECK_AUTH) + raw_xml = self.fetch_response(request) + try: + xml = ElementTree.fromstring(raw_xml) + data = _xml_to_dict(xml) + url = data['site-standard-profile-request']['url'] + url = url.replace('&', '&') + data['id'] = urlparse.parse_qs(url)['key'][0] + + return data + except (xml.parsers.expat.ExpatError, KeyError, IndexError): + return None + + @classmethod + def enabled(cls): + return True + + +# Backend definition +BACKENDS = { + 'linkedin': LinkedinAuth, +} + + +def _xml_to_dict(xml): + data = {} + for child in xml.getchildren(): + if child.getchildren(): + data[child.tag] = _xml_to_dict(child) + else: + data[child.tag] = child.text + + return data -- 2.39.5