Search code examples
google-app-enginegoogle-oauthwebapp2

Write an OAuth2Callback for my AppEngine application


I want to make this scenario happen in an AppEngine application:

When the user requests MyPageHandler, he'll be automatically redirected to a login page (if he's not logged in). Then if the user doesn't not exist in our records, we'll ask him for giving us some credentials (more precisely those specified by https://www.googleapis.com/auth/plus.login ).We store the authorized token for future use. The next time the user connects, he logs in directly.

For this I wrote this code:

decorator = appengine.OAuth2DecoratorFromClientSecrets(
    'my_client_secret.json',
    scope = 'https://www.googleapis.com/auth/plus.login')

@decorator.oauth_aware
def custom_login_required(handler_method):

    def check_login(self, *args, **kwargs):
        user = users.get_current_user()

        if not user:
            return self.redirect(users.create_login_url(self.request.url))
        else:
            usrs = UsersModel.query(UsersModel.email == users.get_current_user().email()).fetch()

            if len(usrs) == 0:
                user = UsersModel(email =  users.get_current_user().email())
                http = decorator.Http()
                myService = build('plus', 'v1', developerKey=api_key, http = http)
                people_resource = service.people()
                people_document = people_resource.get(userId='me').execute()
                user.gplus_profile = people_document['url']
                user.put()
                handler_method(self, *args, **kwargs)
            else:
                #get the link and avatar
                handler_method(self, *args, **kwargs)

    return check_login

class MyPage(webapp2.RequestHandler):
    @custom_login_required
    def get(self):
         .
         .
         #Some Work
         .
         .

class OAuth2CallbackRequestHandler(decorator.callback_handler()):
    def get(self):
         #I do not know how to make use of this
         pass

Thank you.


Solution

  • I finally managed to create the OAuth2CallbackHandler to fit the scenario I already specified in my post. Here is the solution for people having the same issue.

    class OAuth2CallbackRequestHandler(webapp2.RequestHandler):
    
    @decorator.oauth_aware
    def get(self):
    
        user = users.get_current_user()
        if not user:  #user not signed in
            return self.redirect(users.create_login_url(self.request.url))
        else:         #user signed-in
            usrs = UsersModel.query(UsersModel.email == users.get_current_user().email()).fetch()
    
            if len(usrs) == 0: #NEW USER
                if len(self.request.get('code')) != 0:  #user gave us permission
                    credentials = decorator.flow.step2_exchange(self.request.get('code'))  #exchange user-permissions for credentials
                    decorator.set_credentials(credentials)
                    if decorator.has_credentials():  #ensuring credentials are setup
                        http = decorator.http()
                        myService = build('plus', 'v1', developerKey = api_key, http = http)
    
                        user = UsersModel(email =  users.get_current_user().email())
                        people_resource = myService.people()
                        people_document = people_resource.get(userId='me').execute()
                        user.gplus_profile_url = people_document['url']
                        user.gplus_avatar_url = people_document['image']['url']
                        user.display_name = people_document['displayName']
                        user.access_token = credentials.access_token
                        user.refresh_token = credentials.refresh_token #You may need them if you want to update the current information
    
                        user.put()
    
                        return self.redirect('/MyPage')
                    else:
                        return self.redirect('/oauth2callback')
                else:  #we ask user for permission
                    link = decorator.authorize_url()
                    return self.redirect(link)
    
            else:   #USER ALREADY EXISTS
                return self.redirect('/MyPage')
    
    
    class MyPage(webapp2.RequestHandler):
    
    def get(self):
    
        if not users.get_current_user():
            self.redirect('/oauth2callback')
            return
    
        # Continue your work here