Use new withings oauth2 refresh token endpoint (#65134)

This commit is contained in:
Nenad Bogojevic 2022-01-28 17:48:16 +01:00 committed by GitHub
parent da355438aa
commit 1a878b4024
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 15 deletions

View file

@ -9,7 +9,7 @@ import asyncio
from aiohttp.web import Request, Response
import voluptuous as vol
from withings_api import WithingsAuth
from withings_api import AbstractWithingsApi, WithingsAuth
from withings_api.common import NotifyAppli
from homeassistant.components import webhook
@ -84,7 +84,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
conf[CONF_CLIENT_ID],
conf[CONF_CLIENT_SECRET],
f"{WithingsAuth.URL}/oauth2_user/authorize2",
f"{WithingsAuth.URL}/oauth2/token",
f"{AbstractWithingsApi.URL}/v2/oauth2",
),
)

View file

@ -1111,3 +1111,46 @@ class WithingsLocalOAuth2Implementation(LocalOAuth2Implementation):
"""Return the redirect uri."""
url = get_url(self.hass, allow_internal=False, prefer_cloud=True)
return f"{url}{AUTH_CALLBACK_PATH}"
async def _token_request(self, data: dict) -> dict:
"""Make a token request and adapt Withings API reply."""
new_token = await super()._token_request(data)
# Withings API returns habitual token data under json key "body":
# {
# "status": [{integer} Withings API response status],
# "body": {
# "access_token": [{string} Your new access_token],
# "expires_in": [{integer} Access token expiry delay in seconds],
# "token_type": [{string] HTTP Authorization Header format: Bearer],
# "scope": [{string} Scopes the user accepted],
# "refresh_token": [{string} Your new refresh_token],
# "userid": [{string} The Withings ID of the user]
# }
# }
# so we copy that to token root.
if body := new_token.pop("body", None):
new_token.update(body)
return new_token
async def async_resolve_external_data(self, external_data: Any) -> dict:
"""Resolve the authorization code to tokens."""
return await self._token_request(
{
"action": "requesttoken",
"grant_type": "authorization_code",
"code": external_data["code"],
"redirect_uri": external_data["state"]["redirect_uri"],
}
)
async def _async_refresh_token(self, token: dict) -> dict:
"""Refresh tokens."""
new_token = await self._token_request(
{
"action": "requesttoken",
"grant_type": "refresh_token",
"client_id": self.client_id,
"refresh_token": token["refresh_token"],
}
)
return {**token, **new_token}

View file

@ -15,7 +15,6 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the sensor config entry."""
entities = await async_create_entities(
hass,
entry,

View file

@ -216,13 +216,15 @@ class ComponentFactory:
self._aioclient_mock.clear_requests()
self._aioclient_mock.post(
"https://account.withings.com/oauth2/token",
"https://wbsapi.withings.net/v2/oauth2",
json={
"refresh_token": "mock-refresh-token",
"access_token": "mock-access-token",
"type": "Bearer",
"expires_in": 60,
"userid": profile_config.user_id,
"body": {
"refresh_token": "mock-refresh-token",
"access_token": "mock-access-token",
"type": "Bearer",
"expires_in": 60,
"userid": profile_config.user_id,
},
},
)

View file

@ -90,13 +90,15 @@ async def test_config_reauth_profile(
aioclient_mock.clear_requests()
aioclient_mock.post(
"https://account.withings.com/oauth2/token",
"https://wbsapi.withings.net/v2/oauth2",
json={
"refresh_token": "mock-refresh-token",
"access_token": "mock-access-token",
"type": "Bearer",
"expires_in": 60,
"userid": "0",
"body": {
"refresh_token": "mock-refresh-token",
"access_token": "mock-access-token",
"type": "Bearer",
"expires_in": 60,
"userid": "0",
},
},
)