LifeSmart Cloud Authentication#
The LifeSmart integration authenticates against LifeSmart's cloud API using a two-step login flow (/auth.login β /auth.do_auth), then issues all subsequent requests with a signed usertoken. The implementation lives across three files:
config_flow.pyβ HA config-flow steps, credential collection, error surfacingcore/openapi_client.pyβ HTTP calls, signing, region-URL generationdiagnostics.pyβ error-code β advice mapping
Two-Step Login Flow#
Password-based login is triggered when the user selects the password auth method in Step 1 of the cloud flow . The full flow is implemented in login_async():
Step 1 β /auth.login (unsigned POST)
Sends uid, pwd, and appkey to the base API URL. On success the server returns a short-lived token, a userid, and critically a rgn field that identifies the user's home region .
Step 2 β /auth.do_auth (unsigned POST)
Uses the token and userid from Step 1, plus appkey and rgn (falling back to the user's configured region if the server omitted it), to exchange for a long-lived usertoken . After this call, the client updates its internal _usertoken, _region, and _userid in place.
Token-based auth (the other method) skips both steps entirely β the user provides a pre-obtained usertoken directly, and the config flow proceeds straight to device enumeration .
After a successful login, the usertoken and authoritative region are written back into config_data so they persist in the HA config entry .
Token refresh is available via async_refresh_token() which calls /auth.refreshtoken with a flat signed body (different signing scheme from regular API calls).
Region Propagation#
The integration supports eight region codes :
| Code | Label |
|---|---|
cn0 | China VIP |
cn1 | China Backup |
cn2 | China Main (default) |
us | North America |
eur | Europe |
jp | Japan |
apz | Asia Pacific |
auto | Global Auto |
The region is used in two URL-building methods in LifeSmartOAPIClient:
- REST API base URL β
_get_api_url():https://api.{region}.ilifesmart.com/app(falls back tohttps://api.ilifesmart.com/appwhen region is unset orAUTO). - WebSocket URL β
get_wss_url():wss://api.{region}.ilifesmart.com:8443/wsapp/.
Critical: The /auth.login response may return a different rgn than the one the user originally selected. login_async() propagates it to self._region , and validate_input() propagates it into config_data so subsequent REST and WebSocket calls use the correct region . Without this propagation, cn0/cn1/cn2 users would end up hitting the wrong regional endpoint.
Request Signing#
Every regular API call (not login/do_auth) goes through _async_call_api(). The signature is an MD5 hash of a comma-separated string built from: method, any sorted params, time (Unix timestamp), userid, usertoken, appkey, and apptoken . The hash is placed in the system.sign field of the JSON body.
Auth error codes 10004, 10005, and 10006 are treated specially β they raise LifeSmartAuthError instead of the generic LifeSmartAPIError, causing HA to trigger a re-auth flow .
Error Code Mapping#
diagnostics.py maps LifeSmart numeric error codes to a (description, advice, category) tuple via get_error_advice() . The config flow calls this whenever LifeSmartAuthError.code is set, using the advice string as the errors["base"] key shown to the user .
Key auth-related codes :
| Code | Meaning | Category |
|---|---|---|
10002 | AppKey not found | Config issue |
10004 | Invalid signature | Security policy |
10005 | User not authorized | User auth |
10006 | User auth expired | User auth |
10007 | IP not whitelisted | Security policy |
10022 | Redirect required | Server error |
Unknown codes within ranges 10000β10100, 10100β10200, and 20000β20100 are categorized generically rather than causing a crash .