Skip to content

Commit 0516d3c

Browse files
committed
fix: spurious oauth token requests when we already have a valid token.
1 parent 86c1146 commit 0516d3c

File tree

3 files changed

+37
-16
lines changed

3 files changed

+37
-16
lines changed

drivers/SmartThings/sonos/src/api/cmd_handlers.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ local function _do_send_to_group(driver, device, payload)
2424
local household_id, group_id = driver.sonos:get_group_for_device(device)
2525
payload[1].householdId = household_id
2626
payload[1].groupId = group_id
27-
local maybe_token, err = driver:get_oauth_token()
27+
local maybe_token, err = driver:get_cached_oauth_token()
2828
if err then
2929
log.warn(string.format("notice: get_oauth_token -> %s", err))
3030
end
@@ -40,7 +40,7 @@ local function _do_send_to_self(driver, device, payload)
4040
local household_id, player_id = driver.sonos:get_player_for_device(device)
4141
payload[1].householdId = household_id
4242
payload[1].playerId = player_id
43-
local maybe_token, err = driver:get_oauth_token()
43+
local maybe_token, err = driver:get_cached_oauth_token()
4444
if err then
4545
log.warn(string.format("notice: get_oauth_token -> %s", err))
4646
end

drivers/SmartThings/sonos/src/api/sonos_connection.lua

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ local _update_subscriptions_helper = function(
6363
groupId = groupId,
6464
playerId = playerId,
6565
}
66-
local maybe_token, err = sonos_conn.driver:get_oauth_token()
66+
local maybe_token, err = sonos_conn.driver:get_cached_oauth_token()
6767
if err then
6868
log.warn(string.format("notice: get_oauth_token -> %s", err))
6969
end
@@ -258,7 +258,7 @@ local function _oauth_reconnect_task(sonos_conn)
258258
local token, channel_error = token_receive_handle:receive()
259259
if not token then
260260
log.warn(string.format("Error requesting token: %s", channel_error))
261-
local _, get_token_err = sonos_conn.driver:get_oauth_token()
261+
local _, get_token_err = sonos_conn.driver:get_cached_oauth_token()
262262
if get_token_err then
263263
log.warn(string.format("notice: get_oauth_token -> %s", get_token_err))
264264
end
@@ -339,9 +339,11 @@ function SonosConnection.new(driver, device)
339339
device.log.warn(
340340
string.format("WebSocket connection no longer authorized, disconnecting")
341341
)
342-
local _, security_err = driver:request_oauth_token()
343-
if security_err then
344-
log.warn(string.format("Error during request for oauth token: %s", security_err))
342+
if not driver:is_waiting_for_oauth_token() then
343+
local _, security_err = driver:request_oauth_token()
344+
if security_err then
345+
log.warn(string.format("Error during request for oauth token: %s", security_err))
346+
end
345347
end
346348
-- closing the socket directly without calling `:stop()` triggers the reconnect loop,
347349
-- which is where we wait for the token to come in.
@@ -482,7 +484,7 @@ function SonosConnection.new(driver, device)
482484
string.format("https://%s:%s", url_ip, SonosApi.DEFAULT_SONOS_PORT)
483485
)
484486
local _, api_key = driver:check_auth(device)
485-
local maybe_token = driver:get_oauth_token()
487+
local maybe_token = driver:get_cached_oauth_token()
486488
local headers = SonosApi.make_headers(api_key, maybe_token and maybe_token.accessToken)
487489
local favorites_response, err, _ =
488490
SonosRestApi.get_favorites(base_url, header.householdId, headers)

drivers/SmartThings/sonos/src/sonos_driver.lua

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,15 @@ function SonosDriver:notify_augmented_data_changed(update_kind, update_key, upda
184184
)
185185
end
186186

187-
if
188-
self.oauth.endpoint_app_info
187+
local maybe_token, _ = self:get_cached_oauth_token()
188+
189+
local should_request_token = self.oauth.endpoint_app_info
189190
and self.oauth.endpoint_app_info.state == "connected"
190191
and not already_connected
191-
then
192+
and type(maybe_token) ~= "table"
193+
and not self:is_waiting_for_oauth_token()
194+
195+
if should_request_token then
192196
local _, err = self:request_oauth_token()
193197
if err then
194198
log.error(string.format("Request OAuth token error: %s", err))
@@ -224,7 +228,7 @@ end
224228
---@return boolean? auth_success true if the driver can authenticate against the provided arguments, false otherwise
225229
---@return string? api_key_or_err if `auth_success` is true, this will be the API key that is known to auth. If `auth_success` is false, this will be nil. If `auth_success` is `nil`, this will be an error message.
226230
function SonosDriver:check_auth(info_or_device)
227-
local maybe_token, _ = self:get_oauth_token()
231+
local maybe_token, _ = self:get_cached_oauth_token()
228232

229233
local token_valid = (api_version >= 14 and security ~= nil)
230234
and self.oauth
@@ -322,30 +326,45 @@ function SonosDriver:check_auth(info_or_device)
322326
)
323327
end
324328

329+
---@return boolean is_connected
330+
function SonosDriver:is_account_linked()
331+
return (
332+
self.oauth
333+
and self.oauth.endpoint_app_info
334+
and self.oauth.endpoint_app_info.state == "connected"
335+
)
336+
and true
337+
or false
338+
end
339+
325340
---@return any? ret nil on permissions violation
326341
---@return string? error nil on success
327342
function SonosDriver:request_oauth_token()
328343
if api_version < 14 or security == nil then
329344
return nil, "not supported"
330345
end
331-
local maybe_token, maybe_err = self:get_oauth_token()
346+
local maybe_token, maybe_err = self:get_cached_oauth_token()
332347
if maybe_err then
333348
log.warn(string.format("get oauth token error: %s", maybe_err))
334349
end
335350
if type(maybe_token) == "table" and type(maybe_token.accessToken) == "string" then
351+
self.waiting_for_oauth_token = false
336352
self.oauth_token_bus:send(maybe_token)
353+
return true
337354
end
338355
local result, err = security.get_sonos_oauth()
339356
if not result then
340357
return nil, string.format("Error requesting OAuth token via Security API: %s", err)
341358
end
342-
self.waiting_for_oauth_token = true
359+
-- if the account isn't linked, then we're not actually "waiting" for the token yet,
360+
-- because we need to wait for the account link to succeed and the endpoint app upsert
361+
self.waiting_for_oauth_token = self:is_account_linked()
343362
return result, err
344363
end
345364

346365
---@return { accessToken: string, expiresAt: number }? the token if a currently valid token is available, nil if not
347366
---@return "token expired"|"no token"|"not supported"|nil reason the reason a token was not provided, nil if there is a valid token available
348-
function SonosDriver:get_oauth_token()
367+
function SonosDriver:get_cached_oauth_token()
349368
if api_version < 14 or security == nil then
350369
return nil, "not supported"
351370
end
@@ -494,7 +513,7 @@ function SonosDriver:handle_player_discovery_info(api_key, info, device)
494513
api_key = api_key or self:get_fallback_api_key()
495514

496515
local rest_url = net_url.parse(info.discovery_info.restUrl)
497-
local maybe_token, no_token_reason = self:get_oauth_token()
516+
local maybe_token, no_token_reason = self:get_cached_oauth_token()
498517
local headers = SonosApi.make_headers(api_key, maybe_token and maybe_token.accessToken)
499518
local response, response_err =
500519
SonosApi.RestApi.get_groups_info(rest_url, info.ssdp_info.household_id, headers)

0 commit comments

Comments
 (0)