Skip to content

Commit e11d226

Browse files
committed
[Fix] Netatmo refresh_token breaking change
1 parent 7d30068 commit e11d226

File tree

4 files changed

+28
-42
lines changed

4 files changed

+28
-42
lines changed

README.md

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,11 @@ For more detailed information see http://dev.netatmo.com
77
I have no relation with the netatmo company, I wrote this because I needed it myself,
88
and published it to save time to anyone who would have same needs.
99

10-
Following the implementation of "Home" everywhere in the Netatmo API with various behavior, the library has been adjusted to include the home parameters in most calls.
11-
If you are using a single account with a single home and single weather station, the library has been implemented so that your code should continue to run without change.
10+
I am trying to make this library survive to continuous Netatmo changes but their habbit to introduce breaking changes anytime without notice make this target hard to reach.
1211

13-
If you have multiple homes or were supplying a station name in some method calls, you will have to adapt your code :
14-
- to supply a home name when looking for data for most class initializers
15-
- to use the new station name set by Netatmo (which is not your previously set value)
16-
17-
>BREAKING CHANGE: Netatmo seems no longer (july 2023) to allow grant_type "password", even for an app credentials that belong to the same account than the home. They have added the capability of creating access_token/refresh_token couple from the dev page (the location where app are created). As a consequence, the username/password credentials can no longer be used and you must replace them with a new parameter REFRESH_TOKEN that you will get from the web interface. To get this token, you are required to specify the scope you want to allow to this token. Select all that apply for your library use.
12+
>BREAKING CHANGEi (july 2023): Netatmo seems no longer (july 2023) to allow grant_type "password", even for an app credentials that belong to the same account than the home. They have added the capability of creating access_token/refresh_token couple from the dev page (the location where app are created). As a consequence, the username/password credentials can no longer be used and you must replace them with a new parameter REFRESH_TOKEN that you will get from the web interface. To get this token, you are required to specify the scope you want to allow to this token. Select all that apply for your library use.
1813
19-
>SHORT VERSION TO UPGRADE: If you where using a netatmo_credentials file, juste remove USERNAME and PASSWORD fields and add a REFRESH_TOKEN field which value is the one you will obtain from the https://dev.netatmo.com in MyApps selecting you app and using "Token Generator" after selecting required scopes.
14+
>NEW BREAKING CHANGE (december 2023): Web generated refresh_tokens are no more long lived tokens, they will be automatically refreshed. Consequences : No more static authentication in the library source and ~/.netatmo-credentials file will be updated to reflect change in the refresh token. This file MUST be writable and if you run Netatmo tools in container, remember to persist this file between container run.
2015
2116
### Install ###
2217

lnetatmo.py

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -42,34 +42,22 @@
4242

4343
# To ease Docker packaging of your application, you can setup your authentication parameters through env variables
4444

45-
# Authentication use :
46-
# 1 - Values hard coded in the library
47-
# 2 - The .netatmo.credentials file in JSON format in your home directory
48-
# 3 - Values defined in environment variables : CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN
49-
50-
# Each level override values defined in the previous level. You could define CLIENT_ID and CLIENT_SECRET hard coded in the library
51-
# and REFRESH_TOKEN in .netatmo.credentials or environment variables
52-
53-
# 1 : Embedded credentials
54-
cred = { # You can hard code authentication information in the following lines
55-
"CLIENT_ID" : "", # Your client ID from Netatmo app registration at http://dev.netatmo.com
56-
"CLIENT_SECRET" : "", # Your client app secret ' '
57-
"REFRESH_TOKEN" : "" # Your scoped refresh token (generated with app credentials)
58-
}
45+
# Authentication:
46+
# 1 - The .netatmo.credentials file in JSON format in your home directory (now mandatory for regular use)
47+
# 2 - Values defined in environment variables : CLIENT_ID, CLIENT_SECRET, REFRESH_TOKEN
5948

60-
# Other authentication setup management (optionals)
49+
# Note that the refresh token being short lived, using envvar will be restricted to speific testing use case
6150

51+
# Note: this file will be rewritten by the library to record refresh_token change
52+
# If you run your application in container, remember to persist this file
6253
CREDENTIALS = expanduser("~/.netatmo.credentials")
54+
with open(CREDENTIALS, "r") as f:
55+
cred = {k.upper():v for k,v in json.loads(f.read()).items()}
6356

6457
def getParameter(key, default):
65-
return getenv(key, default[key])
66-
67-
# 2 : Override hard coded values with credentials file if any
68-
if exists(CREDENTIALS) :
69-
with open(CREDENTIALS, "r") as f:
70-
cred.update({k.upper():v for k,v in json.loads(f.read()).items()})
58+
return getenv(key, default.get(key, None))
7159

72-
# 3 : Override final value with content of env variables if defined
60+
# Override values with content of env variables if defined
7361
_CLIENT_ID = getParameter("CLIENT_ID", cred)
7462
_CLIENT_SECRET = getParameter("CLIENT_SECRET", cred)
7563
_REFRESH_TOKEN = getParameter("REFRESH_TOKEN", cred)
@@ -261,9 +249,11 @@ def renew_token(self):
261249
}
262250
resp = postRequest("authentication", _AUTH_REQ, postParams)
263251
if self.refreshToken != resp['refresh_token']:
264-
print("New refresh token:", resp['refresh_token'])
252+
self.refreshToken = resp['refresh_token']
253+
cred["REFRESH_TOKEN"] = self.refreshToken
254+
with open(CREDENTIALS, "w") as f:
255+
f.write(json.dumps(cred, indent=True))
265256
self._accessToken = resp['access_token']
266-
self.refreshToken = resp['refresh_token']
267257
self.expiration = int(resp['expire_in'] + time.time())
268258

269259

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
setup(
66
name='lnetatmo',
7-
version='3.3.0',
7+
version='4.0.0',
88
classifiers=[
99
'Development Status :: 5 - Production/Stable',
1010
'Intended Audience :: Developers',
@@ -17,7 +17,7 @@
1717
scripts=[],
1818
data_files=[],
1919
url='https://github.com/philippelt/netatmo-api-python',
20-
download_url='https://github.com/philippelt/netatmo-api-python/archive/v3.3.0.tar.gz',
20+
download_url='https://github.com/philippelt/netatmo-api-python/archive/v4.0.0.tar.gz',
2121
license='GPL V3',
2222
description='Simple API to access Netatmo weather station data from any python script.'
2323
)

usage.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Python Netatmo API programmers guide
1717
1818
>2023-07-24, Adding rawAPI call to direct access the netatmo API when no additional support is provided by the library
1919
20+
>2023-12-04, New update to Netatmo authentication rules, no longer long lived refresh token -> credentials MUST be writable, Hard coding credentials in the library no longer possible (bad luck for small home automation device)
21+
2022
No additional library other than standard Python library is required.
2123

2224
Both Python V2.7x and V3.x.x are supported without change.
@@ -38,8 +40,6 @@ Before being able to use the module you will need :
3840
* An application registered from the user account (see http://dev.netatmo.com/dev/createapp) to obtain application credentials.
3941
* Create a couple access_token/refresh_token at the same time with your required scope (depending of your intents on library use)
4042

41-
In the netatmo philosophy, both the application itself and the user have to be registered thus have authentication credentials to be able to access any station. Registration is free for both.
42-
4343

4444

4545
### 2 Setup your authentication information ###
@@ -48,10 +48,9 @@ In the netatmo philosophy, both the application itself and the user have to be r
4848

4949
Copy the lnetatmo.py file in your work directory (or use pip install lnetatmo).
5050

51-
Authentication data can be supplied with 4 different methods (each method override any settings of previous methods) :
51+
Authentication data can be supplied with 3 different methods (each method override any settings of previous methods) :
5252

53-
1. Some or all values can be hard coded in the library source (and default to empty strings). If you use this method, you are back to the initial suggested method. It would be nice to switch to other methods to isolate credentials and ease library upgrades.
54-
2. Some or all values can be overriden in a ~/.netatmo.credentials (in your platform home directory) file containing the keys in JSON format
53+
1. Some or all values can stored in ~/.netatmo.credentials (in your platform home directory) file containing the keys in JSON format
5554

5655
$ cat .netatmo.credentials # Here all values are defined but it is not mandatory
5756
{
@@ -61,19 +60,21 @@ Authentication data can be supplied with 4 different methods (each method overri
6160
}
6261
$
6362

64-
3. Some or all values can be overriden by environment variables. This is the easiest method if your are packaging your application with Docker. It also allow you to do some testing with other accounts without touching your current ~/.netatmo.credentials file
63+
> Due to Netatmo continuous changes, this method is the only one available for production use as the refresh token will be frequently refreshed and this file MUST be writable by the library to keep a usable refresh token.
64+
65+
2. Some or all values can be overriden by environment variables. This is the easiest method if your are packaging your application with Docker. It also allow you to do some testing with other accounts without touching your current ~/.netatmo.credentials file
6566

6667
$ export REFRESH_TOKEN="yyy"
6768
$ python3 MyCodeUsingLnetatmo.py
6869
...
6970
70-
4. Some or all values can be overriden by explicit call to initializer of ClientAuth class
71+
3. Some or all values can be overriden by explicit call to initializer of ClientAuth class
7172

7273
# Example: REFRESH_TOKEN supposed to be defined by one of the previous methods
7374
authData = lnetatmo.ClientAuth( clientId="netatmo-client-id",
7475
clientSecret="secret" )
7576

76-
If you provide all the values, using any method or mix except 4, you can test that everything is working properly by simply running the package as a standalone program.
77+
If you provide all the values, using any method or mix except 3, you can test that everything is working properly by simply running the package as a standalone program.
7778

7879
This will run a full access test to the account and stations and return 0 as return code if everything works well. If run interactively, it will also display an OK message.
7980

0 commit comments

Comments
 (0)