API invalid grant at random intervals
Twice today, around 10:00 UTC/12:00 European time and again just now, around 16:00 UTC/18:00 European time, our automated weather downloader got a 401/Bad Request ("invalid grant:") from the Netatmo API. This required us to go into the Netatmo app definition (https://dev.netatmo.com/apps/...) and generate a new token.
Fortunately we store these in a secret provider separate from our app code, but because we're based in Chicago, the 10:00 UTC outage wasn't discovered for 3 hours.
Is there an issue with the API today?
Comments
62 comments
i have the same problem . did generating a new token help ?
@m.zielinski - yes, but we had to do it twice today, which has only happened when we're testing our own code. Updating the token by hand is also a PITA.
I'm also seeing this issue in my own app as well as in the iPhones apps myatmo and Netatmo Comfort when I log in with the same Netatmo account (email address) on multiple devices.
The "invalid_grant" error is not returned immediately after logging in on a second device, but the login becomes invalid after a while and refreshing the token fails.
I have seen this error first at 16:33 (CEST) today (June 3rd, 2024), so I believe Netatmo rolled out a change today that is causing these problems.
And it just happened again, around 19:30 UTC/21:30 CEST
Each time I refresh the token manually, it asks me to reauthorize the app. This, also, is unusual.
My app could now successfully refresh the auth token on several device in parallel, so maybe this was a temporary problem.
I am seeing the same problem, refreshing tokens fails, a new authorization is required, but that only helps for a while before refreshing tokens fails again. The refreshToken submitted during request for a new one is OK and valid.
Can netatmo comment on this, please?
OK, I debugged this several hours now. What I have found out is: refreshing tokens fails after a specific time with an error saying that the access_token is invalid, and that invalidates the grant.
Re-authorization is required after that to get a fresh grant, however, after a while it starts all over again: invalid access_token >>> invalid grant.
refresh_token is valid and not changed / updated by some other code.
Netatmo, please help or comment.
Hello,
We just did a modification on the token retrieval process :
When you refreshed an access_token using the associated endpoint https://api.netatmo.com/oauth2/token, Netatmo servers responded with a couple of tokens : an access_token and a refresh_token. If the previous access_token was still valid, the refresh_token value was never renewed
Starting from yesterday, this behavior changed to be compliant with the recommendations of the RFC of the OAuth2 Authorization Framework (section 10.4) and improving the security of the data of our users
When refreshing tokens, access_token and refresh_token values will be automatically renewed and former tokens invalidated
So, if you do not update and use the new refresh_token value when refreshing your access_token, your users will be disconnected after 3 hours and you will retrieve an “invalid_grant” error
To fix it, you need to update the tokens value as soon as you get the newly generated ones. If the process is correctly followed, you don't need anymore to redo the /authorize process at each tokens change
Have a good day,
Leslie - Community Manager
I am aware of those changes, but: I get an invalid grant error about 10 minutes after refreshing access_token and refresh_token. The refreshed tokens do not prevent getting an invalid grant error, actually an invalid access_token error comes up 10 minutes after refreshing the tokens.
It looks like the tokens get invalidated by the server even if they have not expired yet and even if no invalid tokens have been used to authenticate. And that happens about 10-15 minutes after refreshing tokens.
@sk, the access_token has a 3 hours lifespan. The refresh_token doesn't have a lifespan so it can only expire in the case a new /token request is sent
Can you check in your code that you don't have a routine to launch a /token request every 10/15 minutes, making the access/refresh_token pair to be invalidated ?
Have a good day,
Leslie - Community Manager
@leslie
My understanding is: if I request new tokens even if the old ones have not expired yet, new ones will simply replace the old ones, and if I then use only the new ones, everything will be fine. Isn't that correct?
Questions:
1.) Do I have to wait for existing tokens to expire before requesting fresh ones?
2.) Will requesting new ones before existing tokens have expired, invalidate the grant?
Currently my code only requests new tokens if the old one has expired. However, I cannot find any information about the fact that generating new ones before the old one has expired might cause any trouble ...
Anyway, my access_token still gets invalidated even before it has expired and before refreshing it.
I ran some more tests and found that the access_token always expires about 10 to 20 minutes after refresh or generation, not 3 hours. During that period no token refresh has been initiated by my code, actually the code was sleeping in background without any interaction at all. Once it comes to foreground after about 10 to 20 minutes, the access_token is reported as invalid.
There must be a reason for that misbehavior on the server side.
Additionally I sometimes get a 500 HTTP error when trying to access the authentication website once the access_token has expired in order to get a fresh grant.
Helpless, clueless and frustrated. It really sucks that there's no way to debug that since we have no insight what exactly causes the access_token to get invalidated.
@sk,
"if I request new tokens even if the old ones have not expired yet, new ones will simply replace the old ones, and if I then use only the new ones, everything will be fine. Isn't that correct?" <= it's indeed the wanted behavior
1.) Do I have to wait for existing tokens to expire before requesting fresh ones? <= not necessarily, you can launch your request before it and use new generated values
2.) Will requesting new ones before existing tokens have expired, invalidate the grant? <= yes, as soon as you receive new values, former ones are immediately invalidated
I'll ask the question to the devs if they have an idea about your problem. I confirm the access_token expiration is 10800 seconds (otherwise I'd receive hundreds of messages surely). The problem can't come from here
Can you send me your code via the contact form + the email address of your Netatmo account ?
Have a good day,
Leslie - Community Manager
Have sent you a message. I doubt I am the only one with this issue, see messages above by 'David': "Each time I refresh the token manually, it asks me to reauthorize the app. This, also, is unusual."
I carried out further tests and found that if an app is running on two devices, the access_token on one device invalidates that of the other device. Since both devices are not necessarily connected to each other, there is no possibility to exchange access_token and refresh_token between the devices. This means that authentication is only ever valid on one device and expires as soon as authentication for the same netatmo account is also carried out on another device.
What solution do you suggest for this problem? It is not possible to exchange the access_token and refresh_token between the devices ...
I believe we're doing everything as required. Here is the relevant code (C# 8.0; some logging and defensive code removed):
I mean, what else can we do?
@David: can you confirm that the access_token expires as soon as you run your programme with an authorisation for one and the same netatmo account on more than one device? My guess is: not only within one instance of an app on one device it is necessary to exchange access_token and refresh_token, but also between several, which will be more or less impossible.
I have tested the whole thing like this:
1) App authorised on device 1, access_token is valid and remains valid.
2) App authorised on device 2: this causes the access_token on device 1 to expire
The whole thing goes on like this, back and forth. Authorisation on device 1 causes the authorisation on device 2 to expire and vice versa. So you can only run an app on one device at a time.
I think this is the cause of the problem: the authorisation is only ever valid on one device and expires as soon as a second device uses the same app with the same netatmo account. So here we now have a real problem, because exchanging the tokens between devices is practically neither possible nor sensible for security reasons.
Perhaps I have simply overlooked something: in that case, I would be very grateful to know how authentication is supposed to work on two independent devices without de-authenticating one of them.
@sk: There is only one device using the API at a time. We actually suspend our production process when we need to test the API directly in our dev environment.
Using the mobile app or the web dashboard does not seem to affect our automated process. In fact, we can find no correlation between the 401/invalid token response and anything we're doing. It's maddening. The process runs in an Azure function app, so it doesn't carry any state between executions (which are 10 minutes apart).
Let's see, I renewed the token at 12:00 UTC, and it's now 15:15 UTC...and so far, it's going fine. It conked out last night at 2 am Chicago time so no one caught it for 5 hours, though, which is not fine.
Quel drôle et quelle surprise. As soon as I posted that it had run for 5 hours without expiring, it promptly expired. Grace a vous, Netatmo.
Yes, it's maddening, that is for sure. I spent 10 hours today on debugging this, no solution so far.
Here are the times that the Netatmo API invalidated our app's token (all times UTC):
2024-06-03 10:00
2024-06-03 19:20
2024-06-03 23:00
2024-06-04 06:20
2024-06-04 15:10
2024-06-04 18:40
So, starting at noon CEST yesterday, then about every 3 1/2 hours. (There are gaps because, for example, 06:20 UTC is 01:20 in Chicago, and no one was awake to reset the token.)
@david: in your "UpdateAccessToken" method, are you saving both the new access token AND the new refresh token returned by the server?
With yesterday's change, the server returns a new refresh token on every refresh, so this must be saved and used when doing the next refresh.
@alexander: Yes, because that has been the documented behavior for quite a while.
Note that we log the condition when an access token is not returned from the API. I haven't seen those warnings in the log. Our logging rules send out an email alert on Warning messages.
The warnings we're actually receiving come from the RefreshToken() method (shown a few posts above), when the act of refreshing the token returns 401/token invalid.
I am also doing it like that and it works fine on one device, but once another device requests authorization, the first one gets unauthorized and the access_token is invalidated. And the other way around. So, for me only one device can be authorized at the same time or the access_token gets invalidated.
So, re-reading the documentation just now, I have a hypothesis about how the Netatmo API changed.
When we refresh the token, we apply the expired token in the authorization header. But looking at https://dev.netatmo.com/apidocumentation/oauth#refreshing-a-token, I'm wondering if the refresh POST should just be unauthenticated?
Netatmo, can you comment on this? Did you change the behavior of https://api.netatmo.com/oauth2/token to fail when it has an expired token in the auth header?
The wrench in that machine is that we're receiving invalid_grant, not access_denied or anything indicating the token itself is the problem. Also, when refreshing the token manually, I have been asked to re-authorize the app each time, which I'm not sure is the way it behaved in the past.
I am also seeing this behavior. Once you try to refresh a token, no grant exists if the token already expired, and because of that a new authorization is required.
Please sign in to leave a comment.