Question

When I make a redirect from main.py, it works, but when I try to redirect from within a method that it calls, nothing happens. There is no error, the program simply does nothing.

main.py

from githubauth import GetAuthTokenHandler 

class AuthUser(webapp2.RequestHandler):
    """
    If no environment variable exists with the access token in it,
    auth the user as an admin. If it does exist, auth them as a regular
    user.
    """

    def get(self):

        if not ACCESS_TOKEN:
            # No access token exists, auth user as admin 
            get_auth_token = GetAuthTokenHandler() 
            get_auth_token.get()

githubauth.py

import webapp2

class GetAuthTokenHandler(webapp2.RequestHandler):
    """Redirect users to github to get an access request token."""

    def get(self):
        self.redirect('http://api.github.com/authorize')
Was it helpful?

Solution 2

You try to create a webapp2 request handler, but it cannot be done this way. get_auth_token is not a WSGI webapp2 handler instance. If you do not change githubauth.py you have to change your main.py.

class AuthUser(webapp2.RequestHandler):

def get(self):

    if not ACCESS_TOKEN:
        self.redirect(to your GetAuthTokenHandler)

This will result in two redirects if you do not have an access token.

OTHER TIPS

It depends on what kind of authorization you're doing with Github, there are two ways to do that, OAuth token authorization and Web Application Flow.

OAuth Token Authorization

If you're doing OAuth authorization, you don't have to create a request handler to fetch Github auth token, request handler is for serving specific url on your server, for this kind of task, you should use urlfetch().

So the whole flow should be like the following code:

import webapp2
from google.appengine.api import urlfetch

def getAuthToken():
    github_auth_url = "http://api.github.com/authorizations"
    result = urlfetch.fetch(github_auth_url)
    return result

class AuthUser(webapp2.RequestHandler):
    def get(self):
        if not ACCESS_TOKEN:
            # No access token exists, auth user as admin 
            get_auth_token = getAuthToken() 
            # do something with your token...

Redirect Authorization (Web Application Flow)

This is the case if you have applied a client id, and want to be authorized by users as a standalone web application, the steps of this kind authorization is more complicated than former one:

  1. Redirect users to request GitHub access
  2. GitHub redirects back to your site

If you don't know about this flow, take a look at Github OAuth - Web Application Flow

Let's see how could we do within Google App Engine

Redirect users to request Github access

This is the part which involved in your sample, simply redirect user to the authorize url with specified parameters

from urllib import urlencode

class AuthUser(webapp2.RequestHandler):
    def get(self):
        # ... do something ...

        # Github configuration
        github_client_id = "Your github client id..."
        github_redirect_url = "Your url for github redirecting users back to your GAE"
        github_scope = "Gtihub scopes...."

        github_authorize_url = "http://github.com/login/oauth/authorize"
        github_authorize_parameters = {
                'client_id': github_client_id,
                'redirect_url': github_redirect_url,
                'scope': github_scop
                }

        if not ACCESS_TOKEN:
            # if no access_token found on your site, redirect users to Github for authorization
            url_to_redirect = "%s?%s" % (github_authorize_url, urlencode(github_authorize_parameters))
            self.redirect(url_to_redirect)

Github redirects users back to your site

Github will redirect users back to your site based on the previous parameter redirect_url, so you will have to prepare another request handler for receiving redirection from Github.

(You can do this is the same request handler, but it will mess your code)

The redirection back from the step 1 will contains one parameter, code, you will need it to exchange for an access token.

from urllib import urlencode

class GithubRequestHandler(webapp2.RequestHandler):
    def get(self):
        # this handler need to be bind to redirect_url
        # get authentication code
        github_code = self.request.get('code')

        # prepare data to exchange access token
        github_token_url = "https://github.com/login/oauth/access_token"
        github_token_parameters = {
                'client_id': 'Your Github client id',
                'client_secret': 'Your Github client secret',
                'code': github_code}

        # exchange access token
        data = urlfetch.fetch(github_token_url, payload=urlencode(github_token_parameter), method='POST')
        # data will perform in the following form:
        #     access_token=e72e16c7e42f292c6912e7710c838347ae178b4a&scope=user%2Cgist&token_type=bearer
        # extract access_token from the string

        # save the access_token to user's model

P.S.

the code is kinda of simulation of your application flow, it needs some tuning to be able to run on production :)

RequestHandler needs to be instantiated with a request and a response for things to work properly. That said, instantiating one and calling methods on it from inside the handler-method of another is pretty weird.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top