Closed mafr95 closed 10 months ago
I have the same issue with the cloud password. And I updated my tapo C210 too
I have the same issue, C210 and updated to 1.3.9
I have the same issue, C210 and updated to 1.3.9. 2x C210 with 1.3.7. works fine.
Same problem
Looks like they changed how the authorization works. Someone will need to inspect the communication and find a new proper username and password for videos playback / control on some cameras, then we can update the integration or find out what changed - what username/password is used for video playback (not rtsp) and what and how is used for control?
I do not have the update available for my cameras.
Please try it directly with pytapo library - 3rd party account and password used to work as well as admin and cloud password.
Follow https://github.com/JurajNyiri/pytapo#install and then try running this script:
from pytapo import Tapo
user = "" # 3rd party account name
password = "" # 3rd party account password
password_cloud = "" # cloud password
host = "" # ip of the camera, example: 192.168.1.52
tapo = Tapo(host, "admin", password_cloud)
request = tapo.getBasicInfo()
print(request)
tapo = Tapo(host, user, password)
request = tapo.getBasicInfo()
print(request)
Expected response would be the same output twice containing information about camera. Make sure to fill in the 4 variables.
I get this output:
Traceback (most recent call last):
File "/home/pi/testtapo.py", line 7, in
Could you try this:
from pytapo import Tapo
user = "" # 3rd party account name
password = "" # 3rd party account password
password_cloud = "" # cloud password
host = "" # ip of the camera, example: 192.168.1.52
tapo = Tapo(host, user, password)
request = tapo.getBasicInfo()
print(request)
tapo = Tapo(host, "admin", password_cloud)
request = tapo.getBasicInfo()
print(request)
Please make sure to post full output.
If you get access working via the 3rd party account, can you try if control works? Try setting for example privacy mode https://github.com/JurajNyiri/pytapo/blob/main/pytapo/__init__.py#L567 (tapo.setPrivacyMode(True)) .
Hi, I have the same issue with my C210 running on 1.3.9, even the authentication with the local camera account is failing:
Traceback (most recent call last):
File "C:\Users\local\Repos\Tapo\tapo.py", line 8, in <module>
tapo = Tapo(host, user, password)
File "C:\Users\local\Repos\Tapo\.venv\lib\site-packages\pytapo\__init__.py", line 53, in __init__
self.basicInfo = self.getBasicInfo()
File "C:\Users\local\Repos\Tapo\.venv\lib\site-packages\pytapo\__init__.py", line 554, in getBasicInfo
return self.executeFunction(
File "C:\Users\local\Repos\Tapo\.venv\lib\site-packages\pytapo\__init__.py", line 142, in executeFunction
data = self.performRequest(
File "C:\Users\local\Repos\Tapo\.venv\lib\site-packages\pytapo\__init__.py", line 171, in performRequest
self.ensureAuthenticated()
File "C:\Users\local\Repos\Tapo\.venv\lib\site-packages\pytapo\__init__.py", line 73, in ensureAuthenticated
return self.refreshStok()
File "C:\Users\local\Repos\Tapo\.venv\lib\site-packages\pytapo\__init__.py", line 121, in refreshStok
raise Exception("Invalid authentication data")
Exception: Invalid authentication data
Make sure to always restart the camera before executing and not use it anywhere else (including the official app) as there is limited number of control slots available.
It is the same behavior with local authentication not working, even after a fresh reboot
That is different to what was reported in OP. Let's wait for more users to try this eliminate user error or camera weirdness.
In any case, we will need someone to sniff the traffic going from phone to camera on firmware 1.3.9 document it here, and see what is done differently, only then I can start working on the fix.
Guide: https://httptoolkit.com/docs/guides/android/ including the part "Intercepting traffic from 3rd party Android apps with certificate pinning"
I'm here to report the same behavior with my Tapo C210 after updating to 1.3.9. Along with others, I've encountered the 'Invalid cloud password' error through the Home Assistant integration and an 'Exception: Invalid authentication data' error when using the suggested Python login script. Notably, my Synology DiskStation (Surveillance Station) still manages to connect using third-party login credentials. From memory, the update notes mentioned enhanced security measures in the authentication process. This could mean that what we're seeing might be the start of broader issues as similar authentication updates roll out to other Tapo cameras.
Description
Yesterday I updated my Tapo C210 camera to version 1.3.9. After that, the integration could no longer connect to the camera. I decided to delete the camera from the integration and add it again. But every time I enter my cloud password, the error message "Invalid cloud password" appears. I have now checked the password 10 times. It is definitely correct. I suspect it has something to do with the camera update. Previously it worked without any problems.
I have two other cameras. (C200 and C220) I was able to add them with the same cloud password without any problems.
In the meantime, I removed the camera from the Tapo app, reset it and added it again. But without success.
Reproduction Steps
- Update C210 to version 1.3.9 Build 231019 Rel. 13805n(4555)
- Add camera in tapo integration
- Enter correct ip adress
- Enter correct username and passwort for camera account (created via tapo app)
- Enter cloud password ==> failed
Expected behavior
Add camera to integration
If applicable, add error logs.
No response
Device Firmware
1.3.9 Build 231019 Rel. 13805n(4555)
Using stream component
Yes
Does camera work via official integrations?
Yes
Camera has all attributes filled out in developer tools
Yes
HASS Environment
RPI 4
Search for similar issues
Yes
Additional information
No response
Same thing happens after firmware upgrade.
I have pushed a new code: https://github.com/JurajNyiri/pytapo/tree/debug_new_firmware
Download it manually, and next to README.md create file test.py with content:
from pytapo import Tapo
# Camera
user = "" # 3rd party account name
password = "" # 3rd party account password
password_cloud = "" # cloud password
host = "" # ip of the camera, example: 192.168.1.52
try:
tapo = Tapo(host, "admin", password_cloud)
request = tapo.getBasicInfo()
print(request)
except Exception:
pass
try:
tapo = Tapo(host, user, password)
request = tapo.getBasicInfo()
print(request)
except Exception:
pass
Post the whole output of the script.
pyTapo - Version for debugging new firmware
True
admin
{'Host': 'REDACTED', 'Referer': 'REDACTED', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}
200
{"error_code": -40413, "result" : { "data": {"code": -40401, "encrypt_type": ["3"], "key": "REDACTED", "nonce": "REDACTED", "device_confirm": "REDACTED"}}}
pyTapo - Version for debugging new firmware
True
[USERNAME REDACTED]
{'Host': 'REDACTED', 'Referer': 'REDACTED', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}
200
{"error_code": -40401, "result" : { "data": {"code": -40411, "encrypt_type": ["1", "2"], "key": "REDACTED", "nonce": "REDACTED"}}}
@JurajNyiri, that is INVALID_NONCE(-40413). And that -40411 doesn't make any sense.
The "encrypt_type": ["3"]
is indeed interesting.
@viprapp what is inside device_confirm? That field is new, as well as "encrypt_type": ["3"]
Previously we had only 1 and 2.
Edit: try putting in incorrect cloud password as well. Does the response change?
Each time the script is executed, the 'device_confirm' field generates an 80-character, uppercase hexadecimal string, while the first 'nonce' (associated with 'admin') is 16 characters in uppercase hexadecimal format. The second 'nonce' (related to 'username') produces an 8-character alphanumeric string. 'device_confirm' and both 'nonces' change with every run of the script.
Also, inputting an incorrect cloud password doesn't alter the script's output, with the exception of the 'nonces' and 'device_confirm' fields, which are regenerated.
Please try the same script with this https://github.com/JurajNyiri/pytapo/tree/debug_new_firmware_sha256
Looks like some progress
pyTapo - Version for debugging new firmware 2
True
admin
{'Host': 'REDACTED', 'Referer': 'REDACTED', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}
200
{"error_code": 0, "result" : { "stok": "REDACTED", "user_group": "root", "start_seq": 0}}
pyTapo - Version for debugging new firmware 2
True
[USERNAME REDACTED]
{'Host': 'REDACTED', 'Referer': 'REDACTED', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}
200
{"error_code": -40401, "result" : { "data": {"code": -40411, "encrypt_type": ["1", "2"], "key": "REDACTED", "nonce": "REDACTED"}}}
Woah! That was unexpected.
Try now again with branch https://github.com/JurajNyiri/pytapo/tree/debug_new_firmware_sha256, pushed more debug changes, new script:
from pytapo import Tapo
# Camera
user = "" # 3rd party account name
password_cloud = "" # cloud password
host = "" # ip of the camera, example: 192.168.1.52
tapo = Tapo(host, "admin", password_cloud)
request = tapo.getBasicInfo()
print(request)
@viprapp, could you also make sure that you have set up the non-admin local account in the Tapo app and you are using the right password for that?
@GSzabados I think this is the case of a camera refusing control without admin acc, there are cameras like that out, for example C200v3 C310 and probably C210 as well. That is why we default to control via admin acc in the integration.
Are those the Homekit compatible cameras?
@viprapp, could you also make sure that you have set up the non-admin local account in the Tapo app and you are using the right password for that?
Yes, I've consistently used the same local non-admin username and password for all tests, which were set up in the Tapo app. This is further corroborated by the fact that my Synology Surveillance Station can still connect to the C210 camera using these third-party credentials without any issues. This seems to align with JurajNyiri's hypothesis regarding the admin account behavior post-update.
@viprapp please take a look at https://github.com/JurajNyiri/HomeAssistant-Tapo-Control/issues/436#issuecomment-1792572589 when you have the time.
pyTapo - Version for debugging new firmware 3
getBasicInfo
executeFunction
True
admin
{'Host': 'REDACTED', 'Referer': 'REDACTED', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'REDACTED', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}
{"error_code": 0, "result": {"stok": "REDACTED", "user_group": "root", "start_seq": 0}}
200
{"error_code": 0, "result": {"stok": "REDACTED", "user_group": "root", "start_seq": 0}}
{"error_code":0,"seq":0,"result":{"response":"REDACTED"}}
Traceback (most recent call last):
File "../pytapo_debug/test.py", line 8, in <module>
tapo = Tapo(host, "admin", password_cloud)
File "../pytapo_debug/pytapo/__init__.py", line 56, in __init__
self.basicInfo = self.getBasicInfo()
File "../pytapo_debug/pytapo/__init__.py", line 565, in getBasicInfo
return self.executeFunction(
File "../pytapo_debug/pytapo/__init__.py", line 152, in executeFunction
data = self.performRequest(
File "../pytapo_debug/pytapo/__init__.py", line 211, in performRequest
if not self.responseIsOK(res):
File "../pytapo_debug/pytapo/__init__.py", line 134, in responseIsOK
raise Exception(
Exception: Error communicating with Tapo Camera. Status code: 500
Please try again, same script, just pull the latest changes in https://github.com/JurajNyiri/pytapo/tree/debug_new_firmware_sha256
Edit: I also noticed {"error_code":0,"seq":0,"result":{"response":"REDACTED"}}.. Error code 0, what was in response?
pyTapo - Version for debugging new firmware 4
getBasicInfo
executeFunction
True
admin
{'Host': 'REDACTED', 'Referer': 'REDACTED', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}
{"error_code": 0, "result": {"stok": "REDACTED", "user_group": "root", "start_seq": 0}}
200
{"error_code": 0, "result": {"stok": "REDACTED", "user_group": "root", "start_seq": 0}}
{"error_code":0,"seq":0,"result":{"response":"REDACTED"}}
{'method': 'multipleRequest', 'params': {'requests': [{'method': 'getDeviceInfo', 'params': {'device_info': {'name': ['basic_info']}}}]}, 'seq': 1}
Traceback (most recent call last):
File "../pytapo_debug2/test.py", line 8, in <module>
tapo = Tapo(host, "admin", password_cloud)
File "../pytapo_debug2/pytapo/__init__.py", line 57, in __init__
self.basicInfo = self.getBasicInfo()
File "../pytapo_debug2/pytapo/__init__.py", line 570, in getBasicInfo
return self.executeFunction(
File "../pytapo_debug2/pytapo/__init__.py", line 153, in executeFunction
data = self.performRequest(
File "../pytapo_debug2/pytapo/__init__.py", line 216, in performRequest
if not self.responseIsOK(res):
File "../pytapo_debug2/pytapo/__init__.py", line 135, in responseIsOK
raise Exception(
Exception: Error communicating with Tapo Camera. Status code: 500
Additionally, the response contains a 128-character alphanumeric string with '/' and '+' characters, which could indicate base64 encoding.
What is inside {"error_code":0,"seq":0,"result":{"response":"REDACTED"}}
?
Another update: https://github.com/JurajNyiri/pytapo/tree/debug_new_firmware_sha256 with a clearer debugging. Please do not redact everything, only confidential information such as password, stok, mac, dev_id and oem_id. There is no reason to redact anything other than that. I do appreciate the help but you redacted important information 3 times now and it is making debugging a lot harder.
What is inside {"error_code":0,"seq":0,"result":{"response":"REDACTED"}}?
Additionally, the response contains a 128-character alphanumeric string with '/' and '+' characters, which could indicate base64 encoding.
It is a string that looks like this (I kept the + and / dilimeters, the rest is randomized but same charset):
{"error_code":0,"seq":0,"result":{"response":"SaR5xPV6f/sQgudugVow4NxA7VUk9Cs81CT9Wi3h5lCVcy3Yudos5a5yGskQwJ17Pckgwze0vtu824ummnFDH+ZDtxPRYbFpDtZbwX2yE+ePmhvirznkGGZ4DQzwt5GP"}}
@viprapp please run again https://github.com/JurajNyiri/pytapo/tree/debug_new_firmware_sha256 Please do not redact more than password, stok, mac, dev_id and oem_id. It isn't necessary and its making debugging impossible. Feel free to share privately if it would make you feel better.
pyTapo - Version for debugging new firmware 6
{'data': '{"method": "login", "params": {"hashed": true, "password": "REDACTED", "username": "admin"}}', 'headers': {'Host': 'REDACTED', 'Referer': 'REDACTED', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}, 'verify': False}
{"error_code": 0, "result" : { "stok": "REDACTED", "user_group": "root", "start_seq": 0}}
{'data': '{"method": "multipleRequest", "params": {"requests": [{"method": "getDeviceInfo", "params": {"device_info": {"name": ["basic_info"]}}}]}, "seq": 1}', 'headers': {'Host': 'REDACTED', 'Referer': 'REDACTED', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}, 'verify': False}
{"error_code":0,"seq":0,"result":{"response":"SaR5xPV6f/sQgudugVow4NxA7VUk9Cs81CT9Wi3h5lCVcy3Yudos5a5yGskQwJ17Pckgwze0vtu824ummnFDH+ZDtxPRYbFpDtZbwX2yE+ePmhvirznkGGZ4DQzwt5GP"}}
Traceback (most recent call last):
File "../pytapo_debug3/test.py", line 8, in <module>
tapo = Tapo(host, "admin", password_cloud)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "../pytapo_debug3/pytapo/__init__.py", line 58, in __init__
self.basicInfo = self.getBasicInfo()
^^^^^^^^^^^^^^^^^^^
File "../pytapo_debug3/pytapo/__init__.py", line 573, in getBasicInfo
return self.executeFunction(
^^^^^^^^^^^^^^^^^^^^^
File "../pytapo_debug3/pytapo/__init__.py", line 158, in executeFunction
data = self.performRequest(
^^^^^^^^^^^^^^^^^^^^
File "../pytapo_debug3/pytapo/__init__.py", line 220, in performRequest
if not self.responseIsOK(res):
^^^^^^^^^^^^^^^^^^^^^^
File "../pytapo_debug3/pytapo/__init__.py", line 141, in responseIsOK
raise Exception(
Exception: Error communicating with Tapo Camera. Status code: 500
I understand the importance of these details for debugging and appreciate your patience. As for {"response":"SaR5xPV6f/sQgudugVow4NxA7VUk9Cs81CT9Wi3h5lCVcy3Yudos5a5yGskQwJ17Pckgwze0vtu824ummnFDH+ZDtxPRYbFpDtZbwX2yE+ePmhvirznkGGZ4DQzwt5GP"}}
if you require the actual non-randomised response, I'm willing to share it privately, once I'm clear about the type of data it represents and any potential implications for my home security setup.
I have two cameras like this; one is still working and the other not. I deleted the non-working and reinstalled, getting the invalid cloud password error. when I changed the passwor in the Tapo app, I noticed that it now requires seven characters but my previous password used only seven. Could this have anything to do with the problem?
I have two cameras like this; one is still working and the other not. I deleted the non-working and reinstalled, getting the invalid cloud password error. when I changed the passwor in the Tapo app, I noticed that it now requires seven characters but my previous password used only seven. Could this have anything to do with the problem?
I think this theory is unlikely. According to Tapo, there should be 8-32 characters and "At least two types of the following characters must be included: Letters, numbers and symbols." My current one has 20 characters with letters, numbers and symbols.
@viprapp it should contain whatever we requested before, in this case basic info of camera. Here is mine working example for comparison:
{'data': '{"method": "login", "params": {"hashed": true, "password": "REDACTED", "username": "admin"}}', 'headers': {'Host': '192.168.100.70', 'Referer': 'https://192.168.100.70', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}, 'verify': False}
{"error_code": 0, "result" : { "stok": "REDACTED", "user_group": "root"}}
{'data': '{"method": "multipleRequest", "params": {"requests": [{"method": "getDeviceInfo", "params": {"device_info": {"name": ["basic_info"]}}}]}, "seq": 1}', 'headers': {'Host': '192.168.100.70', 'Referer': 'https://192.168.100.70', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}, 'verify': False}
{ "result": { "responses": [ { "method": "getDeviceInfo", "result": { "device_info": { "basic_info": { "device_type": "SMART.IPCAMERA", "device_model": "C200", "device_name": "C200 1.0", "device_info": "C200 1.0 IPC", "hw_version": "1.0", "sw_version": "1.1.16 Build 211209 Rel.37726n(4555)", "device_alias": "Bedroom", "features": "3", "barcode": "", "mac": "REDACTED", "dev_id": "REDACTED", "oem_id": "REDACTED", "hw_desc": "00000000000000000000000000000000" } } }, "error_code": 0 } ] }, "error_code": 0 }
{'data': '{"method": "multipleRequest", "params": {"requests": [{"method": "getPresetConfig", "params": {"preset": {"name": ["preset"]}}}]}, "seq": 2}', 'headers': {'Host': '192.168.100.70', 'Referer': 'https://192.168.100.70', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}, 'verify': False}
{ "result": { "responses": [ { "method": "getPresetConfig", "result": { "preset": { "preset": { "id": [ "1", "2" ], "name": [ "Privacy", "Room" ], "read_only": [ "0", "0" ], "position_pan": [ "0.920372", "-0.066701" ], "position_tilt": [ "0.716080", "0.716080" ] } } }, "error_code": 0 } ] }, "error_code": 0 }
{'data': '{"method": "multipleRequest", "params": {"requests": [{"method": "getDeviceInfo", "params": {"device_info": {"name": ["basic_info"]}}}]}, "seq": 3}', 'headers': {'Host': '192.168.100.70', 'Referer': 'https://192.168.100.70', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}, 'verify': False}
{ "result": { "responses": [ { "method": "getDeviceInfo", "result": { "device_info": { "basic_info": { "device_type": "SMART.IPCAMERA", "device_model": "C200", "device_name": "C200 1.0", "device_info": "C200 1.0 IPC", "hw_version": "1.0", "sw_version": "1.1.16 Build 211209 Rel.37726n(4555)", "device_alias": "Bedroom", "features": "3", "barcode": "", "mac": "REDACTED", "dev_id": "REDACTED", "oem_id": "REDACTED", "hw_desc": "00000000000000000000000000000000" } } }, "error_code": 0 } ] }, "error_code": 0 }
{'device_info': {'basic_info': {'device_type': 'SMART.IPCAMERA', 'device_model': 'C200', 'device_name': 'C200 1.0', 'device_info': 'C200 1.0 IPC', 'hw_version': '1.0', 'sw_version': '1.1.16 Build 211209 Rel.37726n(4555)', 'device_alias': 'Bedroom', 'features': '3', 'barcode': '', 'mac': 'REDACTED', 'dev_id': 'REDACTED', 'oem_id': 'REDACTED', 'hw_desc': '00000000000000000000000000000000'}}}
If it is indeed base64 encoded string, the randomisation you introduced to obfuscate it corrupted it.
@viprapp it should contain whatever we requested before, in this case basic info of camera. Here is mine working example for comparison:
{'data': '{"method": "login", "params": {"hashed": true, "password": "REDACTED", "username": "admin"}}', 'headers': {'Host': '192.168.100.70', 'Referer': 'https://192.168.100.70', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}, 'verify': False} {"error_code": 0, "result" : { "stok": "REDACTED", "user_group": "root"}} {'data': '{"method": "multipleRequest", "params": {"requests": [{"method": "getDeviceInfo", "params": {"device_info": {"name": ["basic_info"]}}}]}, "seq": 1}', 'headers': {'Host': '192.168.100.70', 'Referer': 'https://192.168.100.70', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}, 'verify': False} { "result": { "responses": [ { "method": "getDeviceInfo", "result": { "device_info": { "basic_info": { "device_type": "SMART.IPCAMERA", "device_model": "C200", "device_name": "C200 1.0", "device_info": "C200 1.0 IPC", "hw_version": "1.0", "sw_version": "1.1.16 Build 211209 Rel.37726n(4555)", "device_alias": "Bedroom", "features": "3", "barcode": "", "mac": "REDACTED", "dev_id": "REDACTED", "oem_id": "REDACTED", "hw_desc": "00000000000000000000000000000000" } } }, "error_code": 0 } ] }, "error_code": 0 } {'data': '{"method": "multipleRequest", "params": {"requests": [{"method": "getPresetConfig", "params": {"preset": {"name": ["preset"]}}}]}, "seq": 2}', 'headers': {'Host': '192.168.100.70', 'Referer': 'https://192.168.100.70', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}, 'verify': False} { "result": { "responses": [ { "method": "getPresetConfig", "result": { "preset": { "preset": { "id": [ "1", "2" ], "name": [ "Privacy", "Room" ], "read_only": [ "0", "0" ], "position_pan": [ "0.920372", "-0.066701" ], "position_tilt": [ "0.716080", "0.716080" ] } } }, "error_code": 0 } ] }, "error_code": 0 } {'data': '{"method": "multipleRequest", "params": {"requests": [{"method": "getDeviceInfo", "params": {"device_info": {"name": ["basic_info"]}}}]}, "seq": 3}', 'headers': {'Host': '192.168.100.70', 'Referer': 'https://192.168.100.70', 'Accept': 'application/json', 'Accept-Encoding': 'gzip, deflate', 'User-Agent': 'Tapo CameraClient Android', 'Connection': 'close', 'requestByApp': 'true', 'Content-Type': 'application/json; charset=UTF-8'}, 'verify': False} { "result": { "responses": [ { "method": "getDeviceInfo", "result": { "device_info": { "basic_info": { "device_type": "SMART.IPCAMERA", "device_model": "C200", "device_name": "C200 1.0", "device_info": "C200 1.0 IPC", "hw_version": "1.0", "sw_version": "1.1.16 Build 211209 Rel.37726n(4555)", "device_alias": "Bedroom", "features": "3", "barcode": "", "mac": "REDACTED", "dev_id": "REDACTED", "oem_id": "REDACTED", "hw_desc": "00000000000000000000000000000000" } } }, "error_code": 0 } ] }, "error_code": 0 } {'device_info': {'basic_info': {'device_type': 'SMART.IPCAMERA', 'device_model': 'C200', 'device_name': 'C200 1.0', 'device_info': 'C200 1.0 IPC', 'hw_version': '1.0', 'sw_version': '1.1.16 Build 211209 Rel.37726n(4555)', 'device_alias': 'Bedroom', 'features': '3', 'barcode': '', 'mac': 'REDACTED', 'dev_id': 'REDACTED', 'oem_id': 'REDACTED', 'hw_desc': '00000000000000000000000000000000'}}}
If it is indeed base64 encoded string, the randomisation you introduced to obfuscate it corrupted it.
@JurajNyiri, thank you for providing your example, it clarifies what kind of output is expected. I understand now that the base64 string likely contains the basic info of the camera which is indeed sensitive. I'm hesitant to share the full string as it likely contains details like MAC, dev_id, and oem_id.
Could you guide me on how to securely share the required info without exposing these sensitive elements?
Is it base64? You can decode it to confirm. Or you can send the string to me juraj.nyiri@gmail.com. Realistically there is absolutely nothing anyone can do with those data though even if you shared it here. -- that is why I redact password in the debugging code above, that's really the only thing that matters when shared.
@JurajNyiri, I've sent an email with the terminal output where only the stok is redacted. I attempted to decode the string, but the standard base64 decoder wasn't successful.
At this point we will need someone who has the new firmware to inspect the traffic between the app and local cameras and document the requests so that we can learn from it. I did not receive the firmware yet.
I am going to drop this here: https://portswigger.net/burp/documentation/desktop/mobile/config-android-device (community free version works, no root required, install cert as user, sign in to app first before activating the proxy).
Or if someone could get a link to the latest firmware:
POST https://[IP_ADDRESS]/stok=[TOKEN]/ds
{
"method": "get",
"cloud_config": {
"name": ["upgrade_info"]
}
}
@GSzabados https://github.com/tapo-firmware/Directory The latest is not there yet though.
Hello,
Same issue with C210 updated to 1.3.9.
@JurajNyiri, I send you by email the exchanges collected with the local proxy after a connection with app. I hope this helps ^^
For what it's worth, I have 2xC210. One is firmware 1.37 and connects & works perfectly, the other is 1.3.9 and has the "cloud password error".
Thank you @bonvga (also thanks for providing the camera for testing!) I now have everything I need to continue research and implement new authorization method.
So far I was able to find out how the new authorization works and was able to successfully replicate it - https://github.com/JurajNyiri/pytapo/blob/encryption_3/pytapo/__init__.py#L153 and I am now able to get stok just like before. The issue is with the requests now, they are all encrypted and decrypted with some algorithm and I do not know how.
This one will take a while. Summonning @depau @GSzabados I need your help!
This was fun.
Fixed in https://github.com/JurajNyiri/HomeAssistant-Tapo-Control/releases/tag/5.4.0 .
Description
Yesterday I updated my Tapo C210 camera to version 1.3.9. After that, the integration could no longer connect to the camera. I decided to delete the camera from the integration and add it again. But every time I enter my cloud password, the error message "Invalid cloud password" appears. I have now checked the password 10 times. It is definitely correct. I suspect it has something to do with the camera update. Previously it worked without any problems.
I have two other cameras. (C200 and C220) I was able to add them with the same cloud password without any problems.
In the meantime, I removed the camera from the Tapo app, reset it and added it again. But without success.
Reproduction Steps
Expected behavior
Add camera to integration
If applicable, add error logs.
No response
Device Firmware
1.3.9 Build 231019 Rel. 13805n(4555)
Using stream component
Yes
Does camera work via official integrations?
Yes
Camera has all attributes filled out in developer tools
Yes
HASS Environment
RPI 4
Search for similar issues
Yes
Additional information
No response