Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Answer = 401 (Unauthorized) #13

Open
zian31 opened this issue May 22, 2023 · 9 comments
Open

Answer = 401 (Unauthorized) #13

zian31 opened this issue May 22, 2023 · 9 comments

Comments

@zian31
Copy link

zian31 commented May 22, 2023

Hi.
I've tried to use the "largotef" fork (without the MQTT part) of this program with :

  1. Raspberry with latest Raspberry Pi OS with desktop
    Release date: May 3rd 2023
    System: 32-bit
    Kernel version: 6.1
    Debian version: 11 (bullseye)

  2. Tydom 1.0
    I achieved to configure Tydom 1.0 password with an android Tydom APK V3

  3. Python version is 3.9.6

My test is :
python main.py

The result is always 401 (Unauthorized) :

send: b'GET /mediation/client?mac={my_mac}&appli=1 HTTP/1.1\r\nAccept-Encoding: identity\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nHost: {my_ip}:443\r\nAccept: /\r\nSec-WebSocket-Key: {websocket_key}==\r\nSec-WebSocket-Version: 13\r\n\r\n'
reply: 'HTTP/1.1 401 Unauthorized\r\n'
header: Connection: close
etc...

I've seen on domotics forums (jeedom...) that people have now exactly the same result 401 (Unauthorized) using this program.

But if I use a simple HTML5 websocket code on Chrome (on the Raspberry or on a PC Windows), the websocket connection is working well (but the sending message is not working : disconnection just after) :

index.html :

<!DOCTYPE HTML>
<html>
<head>
<script type = "text/javascript">
function WebSocketTest() {
 if ("WebSocket" in window) {
 alert("WebSocket is supported by your Browser!");
 // Open a web socket
 var ws = new WebSocket("wss://{my_mac}:{my_pass}@IP:443/mediation/client?mac={my_mac}&appli=1");
   ws.onopen = function() {
   alert("WebSocket oppened");
   // Web Socket is connected, send data using send()
   ws.send("GET /info HTTP/1.1\r\nContent-Length: 0\r\nContent-Type: application/json; charset=UTF-8\r\nTransac-Id: 0\r\n\r\n");
   alert("Message is sent...");
   };
   ws.onmessage = function (evt) { 
   var received_msg = evt.data;
   alert("Message is received...");
   };
   ws.onclose = function() { 
   // websocket is closed.
   alert("Connection is closed..."); 
   };
   } else { alert("WebSocket NOT supported by your Browser!"); }
}
</script>
</head>
<body>
<div id = "sse">
<a href = "javascript:WebSocketTest()">Run WebSocket</a>
</div>     
</body>
</html>

So here are my 2 questions :

A. Do you think the 401 answer with your software is due to a new security protection with Debian 11 (bullseye) or python 3.9.6 ?
B. With my little index.html, do you know the right data format in ws.send(data) to send a simple tydom "GET /info" ?

Thanks !

@cth35
Copy link
Owner

cth35 commented May 24, 2023

Hello, for response B, as I can remember, for remote request, you need to add a prefix (cmd_prefix = "\x02") just before the method (GET in your case). So something like this : ws.send("\x02GET /info ...")
I didn't test my prog since a while so I cannot respond to question A. May be they have changed something on server side ?

@SigmaPic
Copy link
Collaborator

SigmaPic commented May 25, 2023

Look at my fork : https://github.com/SigmaPic/python_tydom
I recently fixed something. I don't remember if it was linked to error 401.
Either try my fork or apply the same fix to this code.

@zian31
Copy link
Author

zian31 commented May 25, 2023

Thanks for your answers.
I can now answer :

for B, it's not possible to use simple Javascript for Websockets if ssl is used => Node.JS is needed.
Prefix x02 is needed if IP is not local.

for A, SigmaPic, I've tried yesterday your code https://github.com/SigmaPic/python_tydom and it's working well so it was not a security protection with Debian 11 (bullseye) or python 3.9.6
Your program is the only one working well, all others python tydom on GitHub are answering with 401 at connection.
I've tried to understand where is the difference, but didn't find it for the moment.
In my case, it's perfect, and I've added PUT functions with your cth35 code.

So Thanks a lot for your 2 jobs ! My Tydom is now under control.

@MichelRabozee
Copy link

Hi, thank you SigmaPic, cth35 and zian31 !

@zian31: you said you add the PUT functions to SigmaPic code, is it possible to share your modifications ?

Thank you very much !

@zian31
Copy link
Author

zian31 commented Jun 14, 2023

@MichelRabozee yes, of course, you have to add this code to tydom.py :

async def _send_message_put(self, method, msg, body):
    txt = self.cmd_prefix + method +' ' + msg +" HTTP/1.1\r\nContent-Length: "+ str(len(body)) +"\r\nContent-Type: application/json; charset=UTF-8\r\nTransac-Id: 0\r\n\r\n"+body+"\r\n\r\n"
    a_bytes = bytes(txt, "ascii")
    if not 'pwd' in msg:
        print('>>>>>> Send Request:', method, msg)
    else:
        print('>>>>>> Send Request:', method, 'secret msg')

    await self.connection.send(a_bytes)

    # get response from response queue
    return await self._response_queue.get()

And :

# PUT tydom device data
async def put_device_data(self, id_dev, id_ep, name, value):
    async with self.lock:
        msg_type = '/devices/{}/endpoints/{}/data'.format(id_dev, id_ep)
        req = 'PUT'
        body_type = "[{\"name\":\"" + name + "\",\"value\":\""+ value + "\"}]"
        return await self._send_message_put(method=req, msg=msg_type, body=body_type)

And then (example of UP, wait 2s, STOP) :

    data = await tydom.put_device_data(ID,ID,"positionCmd", "UP")
    print(data)
    await asyncio.sleep(2)
    data = await tydom.put_device_data(ID,ID,"positionCmd", "STOP")
    print(data)

You will find ID with :

    data = await tydom.get_devices_meta()

With that I can open and close my shutters...
You also can know the positions with :

    data = await tydom.get_device_data(ID,ID)

{'name': 'position', 'validity': 'upToDate', 'value': 0} => Volet en haut (butée atteinte)
{'name': 'position', 'validity': 'upToDate', 'value': 100} => Volet en bas (butée atteinte)
{'name': 'position', 'validity': 'upToDate', 'value': None} => Volet en dehors des butées haute ou basse

@MichelRabozee
Copy link

@zian31 , thank you very much !

@MichelRabozee
Copy link

Hello, I was happy too soon, even with SigmaPic's code, I end up with error 401 :-(

./tydom-test.py 
Connecting to tydom 192.168.1.30
Traceback (most recent call last):
  File "/Users/mrabozee/sources/Tydom/./tydom-test.py", line 21, in <module>
    asyncio.get_event_loop().run_until_complete(demo())
  File "/usr/local/Cellar/[email protected]/3.9.14/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 647, in run_until_complete
    return future.result()
  File "/Users/mrabozee/sources/Tydom/./tydom-test.py", line 13, in demo
    await tydom.connect(keep_alive_delay=None)
  File "/Users/mrabozee/sources/Tydom/tydom.py", line 272, in connect
    self.connection = await websockets.client.connect('wss://{}:443/mediation/client?mac={}&appli=1'.format(self.host, self.mac),
  File "/usr/local/lib/python3.9/site-packages/websockets/client.py", line 542, in __await_impl__
    await protocol.handshake(
  File "/usr/local/lib/python3.9/site-packages/websockets/client.py", line 296, in handshake
    raise InvalidStatusCode(status_code)
websockets.exceptions.InvalidStatusCode: server rejected WebSocket connection: HTTP 401

Here is the test code I use (xxxxx is my password):

#!/usr/bin/env python3
from tydom import Tydom
import asyncio

def  callback(uri, data):
    print(uri, data)

async def demo():
    # create tydom instance
    tydom = Tydom("001A25068836", "xxxxx", host='192.168.1.30', request_handler=callback)

    # connect to tydom
    await tydom.connect(keep_alive_delay=None)
    
    # get data
    while True:
        data = await tydom.get_info()
        print(data)
        await asyncio.sleep(5)
        
asyncio.get_event_loop().run_until_complete(demo())

What do I do wrong ?

@zian31
Copy link
Author

zian31 commented Jun 15, 2023

Maybe a bad password :
With App V4, deltadore is auto-generating a password for the Tydom 1.0, it's possible to find it, but not obvious.
With App V3, you can reset and redefine the password of Tydom 1.0
So I used App V3 on android.

@MichelRabozee
Copy link

Thank you, I use an iPhone, but I have an Android only for these kind of tricks \o/ I installed V3 ( https://tydom.fr.aptoide.com/app?store_name=aptoide-web&app_id=58618221 ) and reset the password of the box itself !!!

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

No branches or pull requests

4 participants