Jack P
Jack P

Reputation: 479

How to use OAuth1 with aiohttp

I have successfully implemented OAuth1 with the regular requests module like this:

import requests
from requests_oauthlib import OAuth1


oauth = OAuth1(client_key=oauth_cred["consumer_key"], client_secret=oauth_cred["consumer_secret"], resource_owner_key=oauth_cred["access_token"], resource_owner_secret=oauth_cred["access_token_secret"])

session = requests.Session()

session.auth = oauth

When trying to transfer this to aiohttp, I have not been able to get it to work. Substituting aiohttp.ClientSession() for requests.Session() gives me {'errors': [{'code': 215, 'message': 'Bad Authentication data.'}]}.

I have looked at some solutions on the internet like https://github.com/klen/aioauth-client, but this seems to be a different approach. I just want it to function exactly like in my example above.

I tried

import aiohttp
from aioauth_client import TwitterClient


oauth = TwitterClient(consumer_key=oauth_cred["consumer_key"], consumer_secret=oauth_cred["consumer_secret"], oauth_token=oauth_cred["access_token"], oauth_token_secret=oauth_cred["access_token_secret"])

session = aiohttp.ClientSession()

session.auth = oauth

but I got the same error.

How can I get this to work?

Upvotes: 2

Views: 1476

Answers (1)

Yay295
Yay295

Reputation: 1855

Using oauthlib:

import oauthlib.oauth1, aiohttp, asyncio

async def main():
    # Create the Client. This can be reused for multiple requests.
    client = oauthlib.oauth1.Client(
        client_key = oauth_cred['consumer_key'],
        client_secret = oauth_cred['consumer_secret'],
        resource_owner_key = oauth_cred['access_token'],
        resource_owner_secret = oauth_cred['access_token_secret']
    )

    # Define your request. In my code I'm POSTing so that's what I have here,
    # but if you're doing something different you'll need to change this a bit.
    uri = '...'
    http_method = 'POST'
    body = '...'
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }

    # Sign the request data. This needs to be called for each request you make.
    uri,headers,body = client.sign(
        uri = uri,
        http_method = http_method,
        body = body,
        headers = headers
    )

    # Make your request with the signed data.
    async with aiohttp.ClientSession() as session:
        async with session.post(uri, data=body, headers=headers, raise_for_status=True) as r:
            ...

# asyncio.run has a bug on Windows in Python 3.8 https://bugs.python.org/issue39232
#asyncio.run(main())
asyncio.get_event_loop().run_until_complete(main())

The oauthlib.oauth1.Client constructor takes a bunch more parameters too if you need them (for basic use you don't). The official documentation isn't very thorough, but the doc comment on the method itself is pretty good.

The doc comment on the Client.sign method has more information about the parameters it takes.

Upvotes: 1

Related Questions