homebridge-dyson-pure-cool: API error 401 since yesterday

Seems like authentication is failing again, I guess Dyson changed something again?

[3/3/2021, 8:55:16 AM] [DysonPureCoolPlatform] Checked user account.
[3/3/2021, 8:55:16 AM] [DysonPureCoolPlatform] Signing in.
[3/3/2021, 8:55:17 AM] [DysonPureCoolPlatform] Error while signing in. Status Code: 401
[3/3/2021, 8:55:17 AM] [DysonPureCoolPlatform] API could not be reached. Retry is disabled.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 6
  • Comments: 79 (6 by maintainers)

Most upvoted comments

A workaround that just worked for me was to log out of the latest iOS app, log back in, then reboot homebridge.

I finally had some time to find a viable solution for 2FA. With the help of @sweetw0r and @coraxx I added a separate flow for retrieving the credentials for all your devices. The plugin now has a small website where you can retrieve the credentials by logging into the Dyson account. The plugin no longer directly communicated with the Dyson API. New version 2.0.0 is live on npm.

Let me know that you think. I haven’t tried the non-2FA flow, as my account has already been migrated to 2FA, however, the old flow is also implemented in the “website” for retrieving credentials.

A workaround that just worked for me was to log out of the latest iOS app, log back in, then reboot homebridge.

Hi @jakemauer, I tried that but no luck

EDIT: correction, logging out/in via iOS app, restarting Homebridge fixes it for me. It just takes a few minutes

I got the same error, but finally managed to get it working like this:

  1. stop Homebridge
  2. log out of Dyson from their mobile app
  3. type in the command to restart Homebridge but don’t press enter
  4. log in to Dyson from their mobile app (on the same network as your Homebridge) and complete the 2FA
  5. immediately as you log in, press enter on the Homebridge restart command

I follow EXACTLY all steps and it worked!! Among the hundreds of methods to get the credential, only this one works! Thank you!!!

Looks like the secret here is the wifipassword of the device printed on the manual / sticker on the front of the fan.

It is first hashed (SHA512) and then base64 encoded. that is the “password” that you can also fetch with the manifest API:

wifiPassword = "<wifiPassword>“
hash = crypto.createHash('sha512')
hash.update(wifiPassword)
buffer = hash.digest()
password =  buffer.toString("base64")

However, this alone is not sufficient as the value for the “credentials” field for the plugin.

Looking at the source it is the base64 encoded JSON stringified apiConfig (as fetched from the manifest endpoint) with the addition of a “password” field to represent the sha512 hashed / base 64 encoded json string.

see (here)[https://github.com/lukasroegner/homebridge-dyson-pure-cool/blob/7287ae32d1e947242ab5c7655a79d3adbe3a2bf6/src/dyson-pure-cool-platform.js#L240] and (here)[https://github.com/lukasroegner/homebridge-dyson-pure-cool/blob/7287ae32d1e947242ab5c7655a79d3adbe3a2bf6/src/dyson-pure-cool-platform.js#L268]

For me this was:

{"Serial":"<serial>”,"Name":"<device_name>“,"Version":"<device_version>“,"LocalCredentials":"<from_manifest>“,"AutoUpdate":true,"NewVersionAvailable":true,"ProductType":"475","ConnectionType":"wss", "password": "<hashed/base64encoded wifi password>”}

It is possible to log in using the new authentication flow (that requires the 2FA email). I followed this comment to figure out how to do that.

It looks like you can circumvent the authentication with dyson completely if you have the wifi password (and other information you can get mostly from dyson link). It appears that the plugin is only using part of the information it gets from the manifests API: https://github.com/lukasroegner/homebridge-dyson-pure-cool/blob/7287ae32d1e947242ab5c7655a79d3adbe3a2bf6/src/dyson-pure-cool-platform.js#L323

in particular the fields apiConfig.Name, apiConfig.Serial, apiConfig.ProductType, apiConfig.Version, apiConfig.password

I was able to do the following given that I know the serial (from sticker or dyson link), name (from dyson link), version (software version in dyson link), product type (from the front sticker final 3 digits of product SSID) and wifi password.

wifiPassword = "<wifiPassword>“
hash = crypto.createHash('sha512')
hash.update(wifiPassword)
buffer = hash.digest()
password =  buffer.toString("base64")

serial = "<Serial>“
name = "<Room Name>“
version = "<Software Version>“
productType = "<Device Type>“

json = {"Serial": serial, "Name": name,"Version": version,"ProductType": productType, "password": password}

credentials = Buffer.from(JSON.stringify(json)).toString('base64')
console.log(credentials)

Hopefully that helps someone who has been struggling to the re-auth flow to work.

I got the same error, but finally managed to get it working like this:

  1. stop Homebridge
  2. log out of Dyson from their mobile app
  3. type in the command to restart Homebridge but don’t press enter
  4. log in to Dyson from their mobile app (on the same network as your Homebridge) and complete the 2FA
  5. immediately as you log in, press enter on the Homebridge restart command

Logout and login, there providing the additional auth. code sent by mail from Dyson and then a reboot of Homebridge did it for me as well! It was sufficient to do it on one iOS device.

Am 04.03.2021 um 18:53 schrieb Jake Mauer notifications@github.com:

If I have the Dyson app running on multiple devices, I assume that most likely I have to do this in all of them. Do you only run it on one device? … Am 04.03.2021 um 04:18 schrieb Jake Mauer @.***>:  A workaround that just worked for me was to log out of the latest iOS app, log back in, then reboot homebridge. — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

My assumption is logging in to one of the apps should do it. What happens when you try?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.

They really seem to have changed something. The release information for the latest update of the Dyson iOS app say something about new interface for room climate devices (https://apps.apple.com/de/app/dyson-link/id993135524). It also states changes to authentification (2 step auth).

@sweetw0r I just quickly played around with the new API calls a bit (in python). This is how you could login with the 2FA and receive a token. Though I do not know how new API calls look like using this token.

If someone is interested, here some pseudo code (working but no logic combining them):

import requests

# This checks if the user/email exists
url = 'https://appapi.cp.dyson.com/v3/userregistration/email/userstatus'
params = {'country': 'DE'}
payload = {'Email': 'XYZ@domain.tld'}
headers = {'user-agent': 'android client'}
r = requests.post(url, params=params, headers=headers, json=payload, verify = False)
# returns something like:
# {"accountStatus":"ACTIVE","authenticationMethod":"EMAIL_PWD_2FA"}
print (r.text)


# This will trigger sending the email with 2FA code
url = 'https://appapi.cp.dyson.com/v3/userregistration/email/auth'
params = {'country': 'DE'}
payload = {'Email': 'XYZ@domain.tld', 'Password': 'SecretDysonAccountPassword'}
headers = {'user-agent': 'android client'}
r = requests.post(url, params=params, headers=headers, json=payload, verify = False)
# returns something like:
# {"challengeId":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"}
print (r.text)


# Get the challenge id from previous call and the 6 digit code from the 2FA email
url = 'https://appapi.cp.dyson.com/v3/userregistration/email/verify'
params = {'country': 'DE'}
payload = {'Email': 'XYZ@domain.tld', 'Password': 'SecretDysonAccountPassword', "challengeId":"result from previous call", 'otpCode': '6 digit code received via email'}
headers = {'user-agent': 'android client'}
r = requests.post(url, params=params, headers=headers, json=payload, verify = False)
# returns something like:
# {"account":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","token":"xxxxx-xxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxx","tokenType":"Bearer"}
print (r.text)

I followed the instructions above to make it work successfully, then copied the creds into the config. Working great now.

A workaround that just worked for me was to log out of the latest iOS app, log back in, then reboot homebridge.

Not working for me… anyone else still having issues?

Are you on the latest app version? I had to supply a two-factor code sent to my email before I could login to the iOS app, which is new behavior I think.