I am using Twython to implement OAuth capabilities for my website built with Django. I would like users to be able to register and login using their twitter credentials.
I created the basic views for logging in and registering with twitter information by slightly tweaking the example in the Twython Git repository.
My problem is that users are currently able to register using Twitter OAuth in Firefox and Chrome, but not in Safari. My views implementing this functionality are:
def begin_auth(request):
twitter = Twython(
twitter_token = TWITTER_KEY,
twitter_secret = TWITTER_SECRET,
callback_url = request.build_absolute_uri(reverse('portnoy.views.thanks'))
)
# Request an authorization url to send the user to...
auth_props = twitter.get_authentication_tokens()
# Then send them over there, durh.
request.session['request_token'] = auth_props
return HttpResponseRedirect(auth_props['auth_url'])
def thanks(request, redirect_url='/'):
c = RequestContext(request)
twitter = Twython(
twitter_token = TWITTER_KEY,
twitter_secret = TWITTER_SECRET,
oauth_token = request.session['request_token']['oauth_token'],
oauth_token_secret = request.session['request_token']['oauth_token_secret']
)
# Retrieve the tokens we want...
authorized_tokens = twitter.get_authorized_tokens()
request.session['request_tokens'] = authorized_tokens
debug('thanks', request.session['request_tokens'])
user = User.objects.filter(username=authorized_tokens['screen_name'])
if user.exists():
user = user[0]
user.backend='django.contrib.auth.backends.ModelBackend'
auth.login(request,user)
else:
return render_to_response('twitter_register.html', c)
return HttpResponseRedirect(redirect_url)
In the second view, thanks, I fetch the authorized_tokens and store them in the session, so they are readily accessible in the twitter_register.html page to which unregistered users are directed, thereby allowing unregistered users to sign-up with their Twitter information.
The twitter_register view code up to the failing line in Safari is provided below:
def twitter_register(request):
c = RequestContext(request)
if request.method == 'POST':
email = request.POST.get('email')
password = request.POST.get('password')
if not SafeContact.objects.filter(email=email).exists():
return HttpResponseRedirect('/')
if (User.objects.filter(email=email).exists()):
c['warning'] = "Looks like that email is already in use"
return render_to_response('twitter_register.html', c)
#debug('twitter_register', request.session['request_tokens'])
twitter = Twython(
twitter_token = TWITTER_KEY,
twitter_secret = TWITTER_SECRET,
oauth_token = request.session['request_tokens']['oauth_token'],
oauth_token_secret = request.session['request_tokens']['oauth_token_secret']
)
debug('twitter_register', request.session['request_tokens'])
twitter_user_dict = twitter.showUser(screen_name=request.session['request_tokens']['screen_name'])
All of this works in Firefox and Chrome, but fails in Safari. In particular, in Safari, this code fails on the last provided line of twitter_register:
twitter.showUser(screen_name=request.session['request_tokens']['screen_name']).
yielding the following error:
The error is KeyError: 'screen_name'.
The debug statement debug('thanks', request.session['request_tokens']) prints the authorized_tokens as expected in Firefox and Chrome, but for some reason prints 2x in Safari. The first time it prints, it displays a dictionary of authorized tokens as expected, but on the second print, it displays
thanks: {'<?xml version': '"1.0" encoding="UTF-8"?>\\n<hash>\\n <error>Invalid / expired Token</error>\\n <request>/oauth/access_token</request>\\n</hash>\\n'}
I am quite confused, as this only seems to be happening in Safari (I am testing on v. 5.1.5).
Any advice about how to go about resolving this issue would be highly appreciated. Thanks for taking the time to look at this!