Skip to content

fix: token persistence and startup reliability#286

Open
Obero wants to merge 4 commits intogvigroux:masterfrom
Obero:fix/token-persistence-and-startup-reliability
Open

fix: token persistence and startup reliability#286
Obero wants to merge 4 commits intogvigroux:masterfrom
Obero:fix/token-persistence-and-startup-reliability

Conversation

@Obero
Copy link
Copy Markdown

@Obero Obero commented Mar 8, 2026

This PR fixes three related issues that caused the integration to fail authentication on every HA restart.

The hOn integration requires a full OAuth2 round-trip on every HA restart. If the network is briefly unavailable at boot (common in Docker setups, which is my case, where containers start before routing is fully established), the entry fails permanently with no retry and no useful error message in the UI.

This PR addresses the root cause and its side effects:

  • Tokens obtained during a successful auth are reused on the next startup, making the OAuth2 flow the exception rather than the rule.
  • When auth does fail (network down, expired token), HA retries automatically instead of giving up.
  • The config flow no longer crashes with "Unknown error occurred" when a transient network error occurs during credential validation.

Tested on HA running in Docker.

I'm open to any feedback so we can integrate these fixes in next version of your plugin 🙏

Obero added 4 commits March 8, 2026 16:32
…nit__

Motivation:
- When HonConnection is created with explicit email/password (e.g. during
  config flow validation), _cognitoToken, _id_token and _refresh_token were
  never set, causing AttributeError on any subsequent access.

Modifications:
- Initialize _id_token, _refresh_token and _cognitoToken to "" before the
  if/else branch so both construction paths are safe.

Result:
- No more AttributeError when the config flow validates credentials.
Motivation:
- After every HA restart the integration performs the full Salesforce OAuth2
  flow, which requires user interaction if the network is temporarily
  unavailable at boot time.
- Tokens (cognito + id) obtained during a successful auth are valid for
  several hours and can be reused as-is.

Modifications:
- After a successful /auth/v1/login call, save cognito_token and token
  (id_token) back to the config entry via async_update_entry so they
  survive restarts.
- Add async_try_saved_token(): if both tokens are present in the entry,
  probe the appliance endpoint directly; return True on success so the
  full OAuth2 round-trip is skipped entirely.
- Call async_try_saved_token() at the top of async_authorize() before
  attempting the Salesforce login flow.

Result:
- On a normal restart the integration loads immediately using the cached
  tokens without touching the Salesforce login endpoint.
- When the saved token is expired or rejected the integration falls back
  to the standard full-auth flow transparently.
Motivation:
- async_setup_entry previously called async_authorize() without checking
  its return value and without handling exceptions.
- A network error or auth failure at boot caused the entry to be silently
  marked as failed with no retry, leaving all appliances unavailable
  permanently until the user manually reconfigured.

Modifications:
- Wrap async_authorize() in try/except: any exception is re-raised as
  ConfigEntryNotReady so HA schedules an automatic retry.
- Check the boolean return value: a False result (bad credentials or
  upstream error) also raises ConfigEntryNotReady.

Result:
- On a transient network failure at startup HA retries setup automatically
  (30 s, then exponential back-off) without user intervention.
Motivation:
- async_authorize() can raise ClientConnectorError on transient network
  failures (e.g. DNS timeout at boot or brief routing hiccup).
- The unhandled exception bubbled up to HA's config flow handler, which
  displayed a generic "Unknown error occurred" dialog instead of the
  expected "Invalid credentials" form, giving the user no actionable
  feedback and no way to retry cleanly.

Modifications:
- Import aiohttp in config_flow.py.
- Wrap async_authorize() in try/except ClientConnectorError in both
  async_step_user and async_step_reconfigure; treat a connector error as
  an auth failure (auth_ok = False) so the form is redisplayed.
- Close the HonConnection session unconditionally (moved out of the
  conditional) to avoid session leaks on error.

Result:
- A transient network error during credential validation shows the
  "Invalid credentials" form instead of crashing with an opaque dialog,
  allowing the user to simply retry submission.
@Obero
Copy link
Copy Markdown
Author

Obero commented Mar 26, 2026

@gvigroux Thanks for your review and approval :)

Not to rush you, just so I understand: do you expect something from me before merging this branch ? Or you will just do it when it's appropriate ?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants