maraujop/requests-oauth

Support oAuth calls without provided access token.

ctoth opened this issue · 5 comments

Currently, some oAuth calls require a consumer key and secret to be set, but are made without an access token. I refer specifically to the Twitter oAuth web flow login process where one must request an authentication URI to forward a user to before possessing a key and secret. Currently the hook does not support this.

I will work on it as soon as I have some free time.

Ok, so I've updated the README showing how to retrieve token information from an API, doing an example using Twitter. It's in dev branch.

I will wait for your feedback before bumping version and uploading it to PyPi. Can you please give it a try?

There is only one thing that bothers me. You cannot create a hook passing consumer information only:

OAuthHook(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET)

Because the order of the parameters is:

oauth_hook = OAuthHook(access_token, access_token_secret, consumer_key, consumer_secret)

But if I reverse the parameters, then you cannot do:

OAuthHook.consumer_key = consumer_key
OAuthHook.consumer_secret = consumer_secret
oauth_hook = OAuthHook(access_token, access_token_secret)

The only fix I can come up with is adding this to the constructor:

    def __init__(self, *args):
        if len(args) == 4:
            access_token = args[0]
            access_token_secret = args[1]
            consumer_key = args[2]
            consumer_secret = args[3]
        elif len(args) == 2:
            consumer_key = args[0]
            consumer_secret = args[1]
            access_token = access_token_secret = None

       [...]

But that doesn't feel pythonic at all, as there cannot be multiple constructors. What do you think?

Cheers,
Miguel

It seems perfectly-reasonable as long as you pass keyword arguments to the constructor.

def __init__(self, consumer_key=None, consumer_secret=None, access_key=None, access_secret=None):
    consumer_key = consumer_key or self.consumer_key #pull it off the class if not passed in
    consumer_secret = consumer_secret or self.consumer_secret

It doesn't allow for positional arguments, but that's perfectly-reasonable in this case and will happen unless we explicitly
have different objects to manage consumer and access tokens.

re removing oAuth2: My thoughts were that yes, backwards compatibility is lost. Obviously people couldn't use the oAuth code for to implement their own generic oAuth services. But it works perfectly with the requests oAuth hook, the actual oAuth2 project looks dead, and if it works why not use it? I agree it could be split off into its own module, oauth_hook/mini_auth.py was the thought I put forth in my commit message.

I just think that this is a better way to go forward than relying on python-oauth2, which appears dead, has some poor design decisions (and so much duplicated code!) and last but not least puts all its code in init.py, which bugs me.

Right, you can always do:

OAuthHook(consumer_key=consumer_key, consumer_secret=consumer_secret)

I will leave it as it is.

On the topic of removing python-oauth2 as a depency. I am completely in favor of the movement, don't get me wrong. I don't use the project, because it's dead. Also I'm not a big fan of some of its design decisions.

My intention is to make requests + request-oauth-hook as the best combo available in Python for OAuth. But this won't be a library for implementing OAuth services. Following UNIX philosophy, one tool that does one thing well done.

In this case I don't care about backwards compatibility. I'm releasing version 0.1.3 today on PyPi and tagging it in git. After that synchronize with my repository and do me a pull request.

I think we shouldn't name the module mini_auth.py, mini doesn't sell well :) I would go for auth.py or utils.py or base.py, what do you think?

Cheers,
Miguel

Ok,

I've uploaded version 0.1.3 to PyPi and tagged it on Github. I'm closing this issue, feel free to open the pull request whenever you are ready.

Cheers,
Miguel