Skip to content

fix: record token_created after device login - #175

Open
matt-thepie wants to merge 3 commits into
Pyhass:devfrom
matt-thepie:fix/device-login-token-created
Open

matt-thepie wants to merge 3 commits into
Pyhass:devfrom
matt-thepie:fix/device-login-token-created

Conversation

@matt-thepie

Copy link
Copy Markdown
Contributor

Summary

device_login() returned the AuthenticationResult without storing it, so auth.token_created stayed None and get_device_data() reported no issue time after a device login. The session then fell back to the epoch default for token_created and treated every start as an expired token. login() and sms_2fa() already go through _store_auth_result(); device_login() now does the same.

Part of #123. The two bugs reported there are already addressed on dev (the forced refresh after _retry_login is gone, and start_session accepts a fourth device_data value carrying token_created), but that fourth value was None whenever the tokens came from a device login, which is every reauth and every library user following the README. This closes that gap.

Home Assistant

Checked homeassistant/components/hive/config_flow.py and __init__.py on dev. The config flow stores self.data["device_data"] = await self.hive_auth.get_device_data() and self.data["tokens"] = self.tokens, and __init__.py passes dict(entry.data) to startSession. HA's first setup goes through login() and sms_2fa(), which already record token_created; this change makes the stored value correct on the device-login path too. No HA code calls device_login directly, and no return shape changes.

Live verification

Against a real account, simulating an HA restart that reloads a JSON-serialised config entry:

Config entry shape Before After
4-value device_data (2.0 flow) token_created=None → epoch default → startup refresh real issue time, correct expiry, no refresh
3-value device_data (legacy 1.0.9 entry) epoch default → startup refresh unchanged (no issue time available; one quick refresh, no fallback)

Both shapes start successfully in under a second on dev either way; the fix removes the unnecessary refresh for the 2.0 shape.

Tests

  • New test_device_login_records_access_token_and_token_created
  • Full suite: 1062 passed, 100% coverage; ruff, mypy, pylint 10/10

🤖 Generated with Claude Code

device_login() returned the AuthenticationResult without storing it, so
auth.token_created stayed None and get_device_data() reported no issue
time after a device login. The session then fell back to the epoch
default for token_created and treated every start as an expired token
(issue Pyhass#123). login() and sms_2fa() already go through
_store_auth_result(); device_login() now does the same.

Verified live: after a device login, start_session with the four-value
device_data from get_device_data() now starts with the real expiry and
performs no startup refresh.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (dev@0294877). Learn more about missing BASE report.

Additional details and impacted files

Impacted file tree graph

@@          Coverage Diff           @@
##             dev     #175   +/-   ##
======================================
  Coverage       ?   99.96%           
======================================
  Files          ?       30           
  Lines          ?     2645           
  Branches       ?      311           
======================================
  Hits           ?     2644           
  Misses         ?        0           
  Partials       ?        1           
Flag Coverage Δ
unittests 99.96% <100.00%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/api/hive_auth_async.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@KJonline KJonline added the claude-review Run Claude code review on this PR (required for fork PRs) label Oct 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

Looks good: device_login() now stores access_token and token_created like login() and sms_2fa() do. I found no bugs.

Bugs: none.

Minor: _store_auth_result reads auth_result["AccessToken"] directly. Cognito always returns it with AuthenticationResult, so this is fine in practice. A mocked or odd response with AuthenticationResult but no AccessToken would now raise KeyError inside device_login(). The guard "AuthenticationResult" in result doesn't cover that, and the existing login() and sms_2fa() paths behave the same way.

Tests: the new test covers access_token, token_created and get_device_data()[3]. Codecov reports coverage at 99.96%.

Project rules: only async source is changed, with no sync edits, no logging of tokens, and no data fixtures. The .secrets.baseline update is just line numbers and a timestamp.

Home Assistant check: I fetched homeassistant/components/hive/__init__.py. It calls hive.session.startSession(hive_config) with hive_config = dict(entry.data) and reads entry.data["device_data"][1] in async_remove_entry. It does not read token_created. The get_device_data() return shape is unchanged, and only the token_created value is now populated after a device login. I didn't fetch the other Home Assistant files, since nothing else there touches this code.

Not reviewed: I didn't run the test suite locally.


Automated review by Claude Code · workflow run

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

claude-review Run Claude code review on this PR (required for fork PRs)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants