Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Oauth2 - login with Google

Tags:

I have been searching for 2 days for an answer, but nothing came up.

I am trying to make integrate Oauth2 for login with Google on Django. The code I have throws an exception - "The token is invalid".

This happens:

resp, content = client.request(access_token_url, "POST")     if resp['status'] != '200':         print content         raise Exception("Invalid response from Google."+content) 

in google_authenticate()

Please, help me.

My code:

    def google_login(request):     scope = "https://www.googleapis.com/auth/userinfo.profile"      request_token_url = "https://www.google.com/accounts/OAuthGetRequestToken?scope=%s" % scope     authorize_url = 'https://www.google.com/accounts/OAuthAuthorizeToken'     authenticate_url = "https://accounts.google.com/o/oauth2/auth"      response_type = "code"     redirect_uri = "http://127.0.0.1:8000/login/google/auth"     scope = "https://www.googleapis.com/auth/userinfo.profile"      oauth_key = settings.GOOGLE_KEY     oauth_secret = settings.GOOGLE_SECRET      consumer = oauth.Consumer(oauth_key, oauth_secret)     client = oauth.Client(consumer)      # Step 1: Get a request token. This is a temporary token that is used for      # having the user authorize an access token and to sign the request to obtain      # said access token.      resp, content = client.request(request_token_url, "POST")     request_token = dict(urlparse.parse_qsl(content))      if resp['status'] != '200':         raise Exception("Invalid response from Google.")      # Step 2. Store the request token in a session for later use.     request.session['request_token'] = dict(cgi.parse_qsl(content))      # Step 3. Redirect the user to the authentication URL.     url = "%s?oauth_token=%s&client_id=%s&response_type=%s&redirect_uri=%s&scope=%s" % (authenticate_url,         request.session['request_token']['oauth_token'],         oauth_key,response_type,redirect_uri,scope)      return HttpResponseRedirect(url)  def google_authenticate(request):     access_token_url = 'https://www.google.com/accounts/OAuthGetAccessToken'      oauth_key = settings.GOOGLE_KEY     oauth_secret = settings.GOOGLE_SECRET      consumer = oauth.Consumer(oauth_key, oauth_secret)      # Step 1. Use the request token in the session to build a new client.     token = oauth.Token(request.session['request_token']['oauth_token'],         request.session['request_token']['oauth_token_secret'])     if 'oauth_verifier' in request.GET:         token.set_verifier(request.GET['oauth_verifier'])     client = oauth.Client(consumer, token)      # Step 2. Request the authorized access token from Google.     resp, content = client.request(access_token_url, "POST")     if resp['status'] != '200':         print content         raise Exception("Invalid response from Google."+content)      access_token = dict(cgi.parse_qsl(content))      # Step 3. Lookup the user or create them if they don't exist.     try:         user = User.objects.get(username=access_token['screen_name'])     except User.DoesNotExist:         # When creating the user I just use their [email protected]         # for their email and the oauth_token_secret for their password.         # These two things will likely never be used. Alternatively, you          # can prompt them for their email here. Either way, the password          # should never be used.         user = User.objects.create_user(access_token['screen_name'],             '%[email protected]' % access_token['screen_name'],             access_token['oauth_token_secret'])          # Save our permanent token and secret for later.         profile = Profile()         profile.user = user         profile.oauth_token = access_token['oauth_token']         profile.oauth_secret = access_token['oauth_token_secret']         profile.save()      # Authenticate the user and log them in using Django's pre-built      # functions for these things.     user = authenticate(username=access_token['screen_name'],         password=access_token['oauth_token_secret'])     login(request, user)      return HttpResponseRedirect('/') 
like image 846
Meir Avatar asked Apr 22 '12 19:04

Meir


1 Answers

After a long time, and many hours spent gone to waste, I gave up with OAuth2 since it is difficult to configure, and all I need is to log a user in. The following code should help someone who needs to do something similar, and can be customized. All I did was follow the instructions on forming the urls and such here -> https://developers.google.com/accounts/docs/OAuth2Login

I made two views (for anyone not using Django - pages) and made a link to the first one: This page I called login/google and made a link to it from the login page.

def google_login(request):     token_request_uri = "https://accounts.google.com/o/oauth2/auth"     response_type = "code"     client_id = XXXXXX-your_client_id     redirect_uri = "http://mysite/login/google/auth"     scope = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email"     url = "{token_request_uri}?response_type={response_type}&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}".format(         token_request_uri = token_request_uri,         response_type = response_type,         client_id = client_id,         redirect_uri = redirect_uri,         scope = scope)     return HttpResponseRedirect(url) 

The above code redirected to the second page (this page must be defined as a redirect uri in the google app definitions). I called this page login/google/auth:

def google_authenticate(request):     parser = Http()     login_failed_url = '/'     if 'error' in request.GET or 'code' not in request.GET:         return HttpResponseRedirect('{loginfailed}'.format(loginfailed = login_failed_url))      access_token_uri = 'https://accounts.google.com/o/oauth2/token'     redirect_uri = "http://mysite/login/google/auth"     params = urllib.urlencode({         'code':request.GET['code'],         'redirect_uri':redirect_uri,         'client_id':XXXXX_your_google_key,         'client_secret':XXXXX_your_google_secret,         'grant_type':'authorization_code'     })     headers={'content-type':'application/x-www-form-urlencoded'}     resp, content = parser.request(access_token_uri, method = 'POST', body = params, headers = headers)     token_data = jsonDecode(content)     resp, content = parser.request("https://www.googleapis.com/oauth2/v1/userinfo?access_token={accessToken}".format(accessToken=token_data['access_token']))     #this gets the google profile!!     google_profile = jsonDecode(content)     #log the user in-->     #HERE YOU LOG THE USER IN, OR ANYTHING ELSE YOU WANT     #THEN REDIRECT TO PROTECTED PAGE     return HttpResponseRedirect('/dashboard') 

I really hope this helps people out there, and saves them the hours I wasted. Comments on the code are more than welcome!

like image 158
Meir Avatar answered Sep 24 '22 19:09

Meir