From 281c4e41a51312eed71a7254539b98e4ed2ba0c3 Mon Sep 17 00:00:00 2001 From: Ben Adida <ben@adida.net> Date: Sun, 7 Nov 2010 16:12:01 -0800 Subject: [PATCH] tweaked oauth login to be multi-server capable, added linked auth --- auth/auth_systems/__init__.py | 3 +- auth/auth_systems/linkedin.py | 91 ++++++++++++++++++++++++ auth/auth_systems/oauthclient/client.py | 35 +++++---- auth/auth_systems/twitter.py | 12 +++- auth/media/login-icons/linkedin.png | Bin 0 -> 20289 bytes settings.py.sample | 4 ++ 6 files changed, 130 insertions(+), 15 deletions(-) create mode 100644 auth/auth_systems/linkedin.py create mode 100644 auth/media/login-icons/linkedin.png diff --git a/auth/auth_systems/__init__.py b/auth/auth_systems/__init__.py index 8f13235..39f5ef1 100644 --- a/auth/auth_systems/__init__.py +++ b/auth/auth_systems/__init__.py @@ -1,8 +1,9 @@ AUTH_SYSTEMS = {} -import twitter, password, cas, facebook, google, yahoo +import twitter, password, cas, facebook, google, yahoo, linkedin AUTH_SYSTEMS['twitter'] = twitter +AUTH_SYSTEMS['linkedin'] = linkedin AUTH_SYSTEMS['password'] = password AUTH_SYSTEMS['cas'] = cas AUTH_SYSTEMS['facebook'] = facebook diff --git a/auth/auth_systems/linkedin.py b/auth/auth_systems/linkedin.py new file mode 100644 index 0000000..9a939e2 --- /dev/null +++ b/auth/auth_systems/linkedin.py @@ -0,0 +1,91 @@ +""" +LinkedIn Authentication +""" + +from oauthclient import client + +from django.core.urlresolvers import reverse +from django.http import HttpResponseRedirect + +from auth import utils + +from xml.etree import ElementTree + +import logging + +from django.conf import settings +API_KEY = settings.LINKEDIN_API_KEY +API_SECRET = settings.LINKEDIN_API_SECRET + +# some parameters to indicate that status updating is possible +STATUS_UPDATES = False +STATUS_UPDATE_WORDING_TEMPLATE = "Tweet %s" + +OAUTH_PARAMS = { + 'root_url' : 'https://api.linkedin.com/uas', + 'request_token_path' : '/oauth/requestToken', + 'authorize_path' : '/oauth/authorize', + 'authenticate_path' : '/oauth/authenticate', + 'access_token_path': '/oauth/accessToken' +} + +def _get_new_client(token=None, token_secret=None): + if token: + return client.LoginOAuthClient(API_KEY, API_SECRET, OAUTH_PARAMS, token, token_secret) + else: + return client.LoginOAuthClient(API_KEY, API_SECRET, OAUTH_PARAMS) + +def _get_client_by_token(token): + return _get_new_client(token['oauth_token'], token['oauth_token_secret']) + +def get_auth_url(request, redirect_url): + client = _get_new_client() + try: + tok = client.get_request_token() + except: + return None + + request.session['request_token'] = tok + url = client.get_authenticate_url(tok['oauth_token']) + return url + +def get_user_info_after_auth(request): + tok = request.session['request_token'] + login_client = _get_client_by_token(tok) + access_token = login_client.get_access_token(verifier = request.GET.get('oauth_verifier', None)) + request.session['access_token'] = access_token + + user_info_xml = ElementTree.fromstring(login_client.oauth_request('http://api.linkedin.com/v1/people/~:(id,first-name,last-name)', args={}, method='GET')) + + user_id = user_info_xml.findtext('id') + first_name = user_info_xml.findtext('first-name') + last_name = user_info_xml.findtext('last-name') + + return {'type': 'linkedin', 'user_id' : user_id, 'name': "%s %s" % (first_name, last_name), 'info': {}, 'token': access_token} + + +def user_needs_intervention(user_id, user_info, token): + """ + check to see if user is following the users we need + """ + return None + +def _get_client_by_request(request): + access_token = request.session['access_token'] + return _get_client_by_token(access_token) + +def update_status(user_id, user_info, token, message): + """ + post a message to the auth system's update stream, e.g. twitter stream + """ + return + #twitter_client = _get_client_by_token(token) + #result = twitter_client.oauth_request('http://api.twitter.com/1/statuses/update.json', args={'status': message}, method='POST') + +def send_message(user_id, user_name, user_info, subject, body): + pass + +def send_notification(user_id, user_info, message): + pass + + diff --git a/auth/auth_systems/oauthclient/client.py b/auth/auth_systems/oauthclient/client.py index e1a4e18..c9e6b82 100644 --- a/auth/auth_systems/oauthclient/client.py +++ b/auth/auth_systems/oauthclient/client.py @@ -1,5 +1,6 @@ ''' Python Oauth client for Twitter +modified to work with other oAuth logins like LinkedIn (Ben Adida) Used the SampleClient from the OAUTH.org example python client as basis. @@ -13,22 +14,26 @@ import webbrowser import oauth as oauth from urlparse import urlparse -class TwitterOAuthClient(oauth.OAuthClient): - api_root_url = 'https://twitter.com' #for testing 'http://term.ie' - api_root_port = "80" +class LoginOAuthClient(oauth.OAuthClient): #set api urls def request_token_url(self): - return self.api_root_url + '/oauth/request_token' + return self.server_params['root_url'] + self.server_params['request_token_path'] def authorize_url(self): - return self.api_root_url + '/oauth/authorize' + return self.server_params['root_url'] + self.server_params['authorize_path'] def authenticate_url(self): - return self.api_root_url + '/oauth/authenticate' + return self.server_params['root_url'] + self.server_params['authenticate_path'] def access_token_url(self): - return self.api_root_url + '/oauth/access_token' + return self.server_params['root_url'] + self.server_params['access_token_path'] #oauth object - def __init__(self, consumer_key, consumer_secret, oauth_token=None, oauth_token_secret=None): + def __init__(self, consumer_key, consumer_secret, server_params, oauth_token=None, oauth_token_secret=None): + """ + params should be a dictionary including + root_url, request_token_path, authorize_path, authenticate_path, access_token_path + """ + self.server_params = server_params + self.sha1_method = oauth.OAuthSignatureMethod_HMAC_SHA1() self.consumer = oauth.OAuthConsumer(consumer_key, consumer_secret) if ((oauth_token != None) and (oauth_token_secret!=None)): @@ -97,8 +102,11 @@ class TwitterOAuthClient(oauth.OAuthClient): def get_authenticate_url(self, token): return self.authenticate_url() + '?oauth_token=' +token - def get_access_token(self,token=None): - r = self.oauth_request(self.access_token_url()) + def get_access_token(self,token=None,verifier=None): + if verifier: + r = self.oauth_request(self.access_token_url(), args={'oauth_verifier': verifier}) + else: + r = self.oauth_request(self.access_token_url()) token = self.oauth_parse_response(r) self.token = oauth.OAuthConsumer(token['oauth_token'],token['oauth_token_secret']) return token @@ -117,6 +125,9 @@ class TwitterOAuthClient(oauth.OAuthClient): return self.http_wrapper(req.get_normalized_http_url(),req.to_postdata()) +## +## the code below needs to be updated to take into account not just Twitter +## if __name__ == '__main__': consumer_key = '' @@ -125,7 +136,7 @@ if __name__ == '__main__': consumer_key = raw_input('Please enter consumer key: ') while not consumer_secret: consumer_secret = raw_input('Please enter consumer secret: ') - auth_client = TwitterOAuthClient(consumer_key,consumer_secret) + auth_client = LoginOAuthClient(consumer_key,consumer_secret) tok = auth_client.get_request_token() token = tok['oauth_token'] token_secret = tok['oauth_token_secret'] @@ -133,7 +144,7 @@ if __name__ == '__main__': webbrowser.open(url) print "Visit this URL to authorize your app: " + url response_token = raw_input('What is the oauth_token from twitter: ') - response_client = TwitterOAuthClient(consumer_key, consumer_secret,token, token_secret) + response_client = LoginOAuthClient(consumer_key, consumer_secret,token, token_secret, server_params={}) tok = response_client.get_access_token() print "Making signed request" #verify user access diff --git a/auth/auth_systems/twitter.py b/auth/auth_systems/twitter.py index 73f8bfe..56ea1ab 100644 --- a/auth/auth_systems/twitter.py +++ b/auth/auth_systems/twitter.py @@ -22,11 +22,19 @@ DM_TOKEN = settings.TWITTER_DM_TOKEN STATUS_UPDATES = True STATUS_UPDATE_WORDING_TEMPLATE = "Tweet %s" +OAUTH_PARAMS = { + 'root_url' : 'https://twitter.com', + 'request_token_path' : '/oauth/request_token', + 'authorize_path' : '/oauth/authorize', + 'authenticate_path' : '/oauth/authenticate', + 'access_token_path': '/oauth/access_token' +} + def _get_new_client(token=None, token_secret=None): if token: - return client.TwitterOAuthClient(API_KEY, API_SECRET, token, token_secret) + return client.LoginOAuthClient(API_KEY, API_SECRET, OAUTH_PARAMS, token, token_secret) else: - return client.TwitterOAuthClient(API_KEY, API_SECRET) + return client.LoginOAuthClient(API_KEY, API_SECRET, OAUTH_PARAMS) def _get_client_by_token(token): return _get_new_client(token['oauth_token'], token['oauth_token_secret']) diff --git a/auth/media/login-icons/linkedin.png b/auth/media/login-icons/linkedin.png new file mode 100644 index 0000000000000000000000000000000000000000..745ef3b3d2e4cb37773ae70604dae7344d7705c9 GIT binary patch literal 20289 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 literal 0 HcmV?d00001 diff --git a/settings.py.sample b/settings.py.sample index 7fe210b..d9d81ca 100644 --- a/settings.py.sample +++ b/settings.py.sample @@ -153,6 +153,10 @@ TWITTER_REASON_TO_FOLLOW = "we can direct-message you when the result has been c # the token for Helios to do direct messaging TWITTER_DM_TOKEN = {"oauth_token": "", "oauth_token_secret": "", "user_id": "", "screen_name": ""} +# LinkedIn +LINKEDIN_API_KEY = '' +LINKEDIN_API_SECRET = '' + # email server EMAIL_HOST = 'localhost' EMAIL_PORT = 1025 -- GitLab