Skip to content

fix: normalise username case before Cognito login - #179

Merged
KJonline merged 2 commits into
Pyhass:devfrom
matt-thepie:fix/normalise-username
Nov 2, 2026
Merged

KJonline merged 2 commits into
Pyhass:devfrom
matt-thepie:fix/normalise-username

Conversation

@matt-thepie

Copy link
Copy Markdown
Contributor

Problem

home-assistant/core#185593: Hive login fails if the email is typed with any capital letter, for example when the iOS app autocapitalises the first letter. Hive's Cognito pool treats the username as case-sensitive and answers with NotAuthorizedException, which surfaces as HiveInvalidPassword.

Home Assistant only partly works around this. config_flow.py lower-cases the username for the flow's own Auth(...):

username = self.data[CONF_USERNAME].lower()
self.hive_auth = Auth(
    username=username,

but self.data.update(user_input) keeps the typed value, and that is what is saved in the config entry. On every start, __init__.py passes the entry to the library:

hive_config = dict(entry.data)
...
devices = await hive.session.startSession(hive_config)

and start_session copies it straight onto the auth object (self.auth.username = config["username"]), so any later password or device login uses the capitalised address and fails.

Fix

HiveAuthAsync and HiveAuth now expose username as a property whose setter stores the value trimmed and lower-cased. This covers both the constructor and the reassignment in start_session, with no Home Assistant change needed. File mode (use@file.com) is detected regardless of case as a side effect.

Verification

Live, against a real Hive account with saved device credentials:

Username typed Before After
lowercase (as registered) OK OK
First letter capitalised HiveInvalidPassword OK
All upper case HiveInvalidPassword OK
  • New tests in tests/unit/test_hive_auth_async.py and tests/unit/test_hive_auth.py cover the constructor, reassignment, the USERNAME sent to InitiateAuth, and file-mode detection.
  • Full suite: 1071 passed, 100% coverage. mypy, pylint 10/10, bandit clean. Ruff's three PLR0917 hits are pre-existing on untouched lines and also appear on dev.
  • .secrets.baseline updated because the new property shifts an allowlisted line in hive_auth_async.py.

Home Assistant impact

No public API change. Auth, startSession and the exceptions raised are unchanged, and nothing in the integration reads auth.username back. Checked homeassistant/components/hive/config_flow.py and __init__.py on dev.

🤖 Generated with Claude Code

Hive's Cognito pool treats the email as case-sensitive, so a
capitalised address (for example from mobile autocapitalisation)
fails with HiveInvalidPassword even though the account exists.

Store the username trimmed and lower-cased via a property on both
auth classes, so the constructor and start_session's reassignment
from the Home Assistant config entry are both covered.

Fixes home-assistant/core#185593

Co-Authored-By: Claude Opus 5.5 <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@86b0339). Learn more about missing BASE report.

Additional details and impacted files

Impacted file tree graph

@@          Coverage Diff           @@
##             dev     #179   +/-   ##
======================================
  Coverage       ?   99.96%           
======================================
  Files          ?       30           
  Lines          ?     2655           
  Branches       ?      310           
======================================
  Hits           ?     2654           
  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.py 100.00% <100.00%> (ø)
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.

@KJonline KJonline added the claude-review Run Claude code review on this PR (required for fork PRs) label Nov 1, 2026
@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown
Contributor

🤖 Claude Code Review

Verdict: looks good, no blocking issues. Lower-casing and trimming the username in both auth classes is consistent and tested.

Bugs: none found.

Minor

  • DiscoveryMixin._configure_file_mode (src/session/discovery.py:53) still compares username == "use@file.com" case-sensitively. HiveAuthAsync.use_file is now case-insensitive (Use@File.com is accepted, as the new test shows), but the session's config.file is not. Normalising there too (username.strip().lower()) would keep the two in agreement. This only affects the dev/testing username.
  • The SRP hash, SECRET_HASH and USERNAME all read self.username, so they use the same normalised value. An existing device login is unaffected, because the device key is not derived from the username.

Home Assistant check: I fetched config_flow.py. It already does username = self.data[CONF_USERNAME].lower() for async_set_unique_id and passes the lower-cased value to Auth(username=...). The stored entry keeps the original casing, and start_session reassigns auth.username from that config, which is the path this PR fixes. The change is compatible and no Home Assistant API is touched. username is now a property, but it is still read and set the same way.

Not reviewed: I did not run the test suite. The Codecov report shows the changed lines are covered.


Automated review by Claude Code · workflow run

@KJonline
KJonline merged commit e5c4e78 into Pyhass:dev Nov 2, 2026
15 checks passed
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