2
\$\begingroup\$

I have a written some code which helps me to get OAuth Access Code from Reddit. Reddit uses standard OAuth2, so like any other OAuther server, here's are the steps to perform:

  1. The client/app sends app key, app secret and redirect URL to browser.
  2. User authorizes it and gives permission.
  3. Reddit sends request back, with code to earlier given redirect URL.
  4. The code can be used for further access.

The way my script works:

  1. I am using praw. I first create a praw object and pass this to server code with required info like app key, app secret and redirect URL:

    oauthserver = PrawOAuth2Server(reddit_client=reddit_client,
                                   app_key=app_key,
                                   app_secret=app_secret,
                                   state=user_agent)
    
  2. Start the server. This opens the URL in browser and prompts user for authorization. Most of the magic happens at this stage. This not only starts the server (to handle redirect_url request), but also receives the code:

    oauthserver.start()
    
  3. Then later I can get the access code, refresh token using one of Praw's method:

    oauthserver.get_access_codes()
    

Example usage code:

import praw
from PrawOauth2Server import PrawOAuth2Server

user_agent = '...'
app_key = '...'
app_secret = '...'
scopes = ['identity', 'submit']

reddit_client = praw.Reddit(user_agent=user_agent)
oauth_server = PrawOAuth2Server(reddit_client,
                                app_key=app_key,
                                app_secret=app_secret,
                                state=user_agent)
oauth_server.start()
print(oauth_server.get_access_codes())

Finally, here is the code I want to be reviewed:

import webbrowser

import tornado.ioloop
import tornado.web


REDIRECT_URL = 'http://127.0.0.1:65010/authorize_callback'
SCOPES = ['identity']
REFRESHABLE = True
CODE = None


class AuthorizationHandler(tornado.web.RequestHandler):

    def get(self):
        global CODE
        CODE = self.get_argument('code')
        tornado.ioloop.IOLoop.current().stop()


class PrawOAuth2Server:

    def __init__(self, reddit_client, app_key, app_secret,
                 state, redirect_url=REDIRECT_URL, scopes=SCOPES,
                 refreshable=REFRESHABLE):
        self.reddit_client = reddit_client
        self.app_key = app_key
        self.app_secret = app_secret
        self.state = state
        self.redirect_url = redirect_url
        self.scopes = set(scopes)
        self.refreshable = refreshable
        self.code = None

        self._set_app_info()

    def _set_app_info(self):
        self.reddit_client.set_oauth_app_info(self.app_key, self.app_secret,
                                              self.redirect_url)

    def get_auth_url(self):
        return self.reddit_client.get_authorize_url(self.state,
                                                    self.scopes,
                                                    self.refreshable)

    def start(self):
        global CODE
        url = self.get_auth_url()
        webbrowser.open(url)
        tornado.ioloop.IOLoop.current().start()
        self.code = CODE

    def get_access_codes(self):
        return self.reddit_client.get_access_information(self.code)

application = tornado.web.Application([
    (r'/authorize_callback', AuthorizationHandler),
])
application.listen(65010)
  1. I want any general suggestion/advice related to above code
  2. I really want to change the way I am handling CODE (fetching it from request object, using it as global variable etc). I am not able to find way to make this better.
\$\endgroup\$
  • \$\begingroup\$ This goes outside the scope of codereview, but are you trying to write a bot or an actual app? Because if you're writing a reddit bot you don't actually need to start up your own OAuth server. \$\endgroup\$ – m0meni Jul 5 '15 at 12:31
  • \$\begingroup\$ I am trying to write a bot. Reddit is going to drop login support and all bots/scripts have to use Oauth only. So, I want to turn my code into a library so that its easier for beginner. Also, can you tell me why it is out of scope for CR and how do I edit to make it come under the required guidelines and scope? \$\endgroup\$ – avi Jul 5 '15 at 12:40
  • \$\begingroup\$ I am aware, and I recently wrote a bot under the same constraints. The server is 100% unnecessary even for OAuth. Take a look at this: github.com/reddit/reddit/wiki/OAuth2-Quick-Start-Example \$\endgroup\$ – m0meni Jul 5 '15 at 13:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.