Simple OAuth 2 in Python (urllib + oauthlib)

When using OAuth 2 API from Python, I couldn't find a concrete method when using ʻurllib + ʻoauthlib, so I tried it myself.

This time, Netatmo API is described as an example, but if it is an API that supports OAuth 2, the method should be almost the same.

Why urllib + oauthlib

ʻUrllib is well organized as a library to send HTTP requests, ʻoauthlib is well organized as a library to handle OAuth, and if you are dealing with OAuth 2 clients in Python, it is the simplest to combine the two. Because I thought.

However, since Simple ≠ Easy, those who want Easy should use Requests-OAuthlib.

Reference: [urllib \ .request is sufficient for Python HTTP client -Qiita](https://qiita.com/hoto17296/items/8fcf55cc6cd823a18217#post-%E3%83%AA%E3%82%AF%E3% 82% A8% E3% 82% B9% E3% 83% 88% E3% 82% 92% E6% 8A% 95% E3% 81% 92% E3% 82% 8B)

Advance preparation

ʻOauthlib` is not a standard module, so install it.

$ pip install oauthlib

Since ʻurllibandjson` are used throughout, import them.

import urllib
import json

Obtain the information required for authentication.

NETATMO_API_CLIENT_ID = 'xxxxxxxxxxxxxxxx'
NETATMO_API_CLIENT_SECRET = 'xxxxxxxxxxxxxxxx'
NETATMO_API_SCOPE = ['read_station']
NETATMO_API_REDIRECT_URL = 'http://localhost/callback'

This time I just want to use the GET / getmeasure API, so the scope only needs to be read_station.

Get an Access Token

First, create a WebApplicationClient object.

from oauthlib.oauth2 import WebApplicationClient

oauth = WebApplicationClient(NETATMO_API_CLIENT_ID)

Next, generate a URL to get the Authorization Code.

url, headers, body = oauth.prepare_authorization_request('https://api.netatmo.com/oauth2/authorize', redirect_url=NETATMO_API_REDIRECT_URL, scope=NETATMO_API_SCOPE)
print(url)  

The URL for asking the user for permission is displayed.

A web application redirects the user to this URL, and if the user accepts it, it jumps to the Redirect URL specified by the Authorization Code.

Here, it is assumed that the Redirect URL is accessed with the following parameters.

authorization_response = 'https://localhost/callback?state=xxxxxxxx&code=xxxxxxxx'

Now that we have the Authorization Code, we will use it to get an Access Token.

url, headers, body = oauth.prepare_token_request('https://api.netatmo.com/oauth2/token', authorization_response=authorization_response, client_secret=NETATMO_API_CLIENT_SECRET)
req = urllib.request.Request(url, body.encode(), headers=headers)
with urllib.request.urlopen(req) as res:
    oauth.parse_request_body_response(res.read())

ʻOauth.prepare_token_request prepares request parameters for getting Access Token. At this time, it is not necessary to parse the Authorization Code by yourself from ʻauthorization_response, just pass it as an argument.

For the Netatmo API, you need to specify the Client Secret here, but I think it's the same for most APIs.

If you pass the result of the Access Token acquisition request to ʻoauth.parse_request_body_response as it is, it will be set to ʻoauth.access_token etc. without permission.

Authentication is now complete.

Access the API using an Access Token

Try accessing GET / getmeasure. https://dev.netatmo.com/apidocumentation/weather#getmeasure

columns = ['temperature', 'co2', 'humidity', 'pressure', 'noise']
params = {
    'date_begin': 1577836800,  # 2020-01-01 00:00:00 UTC
    'device_id': 'xx:xx:xx:xx:xx:xx',
    'scale': '30min',
    'type': ','.join(columns),
    'optimize': 'false',
}
url = 'https://api.netatmo.com/api/getmeasure?' + urllib.parse.urlencode(params)
url, headers, body = oauth.add_token(url)
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req) as res:
    data = json.load(res)

The ʻAuthorization header has been added to the headers obtained by ʻoauth.add_token.

Update Access Token

The Netatmo API has a short access token expiration date of 3 hours, so if it exceeds this, it is necessary to renew the access token using Refresh Token.

url, headers, body = oauth.prepare_refresh_token_request('https://api.netatmo.com/oauth2/token', client_id=NETATMO_API_CLIENT_ID, client_secret=NETATMO_API_CLIENT_SECRET)
req = urllib.request.Request(url, body.encode(), headers=headers)
with urllib.request.urlopen(req) as res:
    oauth.parse_request_body_response(res.read())

ʻOauth.prepare_refresh_token_request prepares request parameters for updating the Access Token. (Refresh Token etc. held inside ʻoauth is automatically set as a request parameter)

For the Netatmo API, you need to specify the Client ID and Client Secret additionally here.

Recommended Posts

Simple OAuth 2 in Python (urllib + oauthlib)
Simple gRPC in Python
Simple regression analysis in Python
Simple IRC client in python
First simple regression analysis in Python
Implementing a simple algorithm in Python 2
Run a simple algorithm in Python
Simple gacha logic written in Python
A simple HTTP client implemented in Python
Try drawing a simple animation in Python
Create a simple GUI app in Python
Write a simple greedy algorithm in Python
Write a simple Vim Plugin in Python 3
Quadtree in Python --2
Python in optimization
CURL in python
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Unittest in python
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
N-Gram in Python
Programming in python
Plink in Python
Constant in python
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
StepAIC in Python
My urllib (python)
N-gram in python
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python
Constant in python
nCr in Python.
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Quad-tree in Python
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
LiNGAM in Python
Flatten in python
flatten in python
Studying Mathematics in Python: Solving Simple Probability Problems
A simple Pub / Sub program note in Python
Notes for implementing simple collaborative filtering in Python
Create a simple momentum investment model in Python