Nothing except "None" returned for my Python web.py Facebook app when I turn on "OAuth 2.0 for Canvas"
Question: I am a beginning Facebook app developer, but I'm an experienced developer. I'm
using web.py as my web framework, and to make matters a bit worse, I'm new to
Python.

I'm running into an issue, where when I try to switch over to using the newer
"OAuth 2.0 for Canvas", I simply can't get anything to work. The only thing
being returned in my Facebook app is "None".

My motivation for turning on OAuth 2.0 is because it sounds like Facebook is
going to force it by July, and I might as well learn it now and now have to
rewrite it in a few weeks.

I turned on "OAuth 2.0 for Canvas" in the Advanced Settings, and rewrote my
code to look for "signed_request" that is POSTed to my server whenever my test
user tries to access my app.

My code is the following (I've removed debugging statements and error checking
for brevity):

    
    
    #!/usr/bin/env python
    
    import base64
    import web
    import minifb
    import urllib
    import json
    
    FbApiKey = "AAAAAA"
    FbActualSecret = "BBBBBB"
    CanvasURL = "http://1.2.3.4/fb/"
    RedirectURL="http://apps.facebook.com/CCCCCCCC/"
    RegURL = 'https://graph.facebook.com/oauth/authorize?client_id=%s&redirect_uri=%s&type=user_agent&display=page' % (FbApiKey, RedirectURL)
    
    urls = (
      '/fb/', 'index',
    )
    app = web.application(urls, locals())
    
    def authorize():
        args = web.input()
    
        signed_request = args['signed_request']
    
        #split the signed_request via the .
        strings = signed_request.split('.')
    
        hmac = strings[0]
        encoded = strings[1]
    
        #since uslsafe_b64decode requires padding, add the proper padding
        numPads = len(encoded) % 4
        encoded = encoded + "=" * numPads
        unencoded = base64.urlsafe_b64decode(str(encoded))
    
        #convert signedRequest into a dictionary
        signedRequest = json.loads(unencoded)
    
        try:
                #try to find the oauth_token, if it's not there, then
                #redirect to the login page
                access_token = signedRequest['oauth_token']
                print(access_token)
        except:
                print("Access token not found, redirect user to login")
                redirect = "<script type=\"text/javascript\">\ntop.location.href=\"" +_RegURL + "\";\n</script>"
                print(redirect)
                return redirect
    
        # Do something on the canvas page
        returnString = "<html><body>Hello</body></html>"
        print(returnString)
    
    class index:
        def GET(self):
            authorize()
    
        def POST(self):
            authorize()
    
    if __name__ == "__main__":
        app.run()
    

For the time being, I want to concentrate on the case where the user is
already logged in, so assume that oauth_token is found.

My question is: Why is my "Hello" not being outputted, and instead all I see
is "None"?

It appears that I'm missing something very fundamental, because I swear to
you, I've scoured the Internet for solutions, and I've read the Facebook pages
on this many times. Similarly, I've found many good blogs and stackoverflow
questions that document precisely how to use OAuth 2.0 and signed_request. But
the fact that I am getting a proper oauth_token, but my only output is "None"
makes me think there is something fundamental that I'm doing incorrectly. I
realize that "None" is a special word in python, so maybe that's the cause,
but I can't pin down exactly what I'm doing wrong.

When I turn off OAuth 2.0, and revert my code to look for the older POST data,
I'm able to easily print stuff to the screen.

Any help on this would be greatly appreciated!


Answer: How embarrassing!

In my authorize function, I return a string. But since class index is calling
authorize, it needs to be returned from the class, not from authorize. If I
return the return from authorize, it works.

