filips123/ZeroFramePy

ZeroFramePy and multiuser does not work correctly

krzotr opened this issue · 6 comments

Hi,

When i try to use ZeroFramePy with multiuser I got error

How to reproduce?

Preparation - Debug:

  • put websocket.enableTrace(True) in _get_websocket
  • put print(message) in _on_request
  1. Go Zeronet web page and logout your current user
  2. Refresh Zeronet web page
  3. Run ZeroFramePy command e.g. siteInfo
  4. I got error {'error': 'No user found'}
error from callback <bound method ZeroFrame._on_request of <__main__.ZeroApp object at 0x7f621f985350>>: 'cmd'
  File "/home/ko/dev/ZeroFramePy/venv/lib64/python3.7/site-packages/websocket/_app.py", line 343, in _callback
    callback(*args)
  File "/home/ko/dev/ZeroFramePy/zeroframe_ws_client/__init__.py", line 184, in _on_request
    cmd = message['cmd']
send: b'\x88\x82\x860l\x9a\x85\xd8'
Traceback (most recent call last):
  File "/home/ko/dev/ZeroFramePy/test.py", line 35, in <module>
    main()
  File "/home/ko/dev/ZeroFramePy/test.py", line 31, in main
    print(result.result())
asyncio.base_futures.InvalidStateError: Result is not set.
  1. Go to Zeronet web and login
  2. Repeat step 3
  3. Everything is OK, I got response from server
{'auth_key': '', '...')

How to resolve?

I think we have to login first to get full access to the API via WebSocket

I will also check this tomorrow.

This is known issue for both ZeroFramePy and ZeroFrameJS:

If ZeroNet instance is using Multiuser plugin, you need to specify a master address of the account you want to use. Account must already exist on the instance.

If you want to create a new account, you also need to specify a master seed of it. Note that this feature is unsafe on the untrusted proxy. Also, it is currently not implemented yet.

Problem is that ZeroFramePy only sends master address as a cookie. But to actually use it, it's private key must already exist on ZeroNet instance. That's why it works when user is logged in (private key is saved) and not when it is logged out.

To support "remote login", you would need to also send private key to instance. ZeroFramePy already supports parameter (multiuser_master_seed) for that, but logging in is currently not implemented.


I'm also working to figure out how to implement this. Problem is that Multiuser plugin (userLoginForm) heavily relies on getting private key input from HTML and JS forms, which are obiusly not supported in this client. Some solution to this would be to modify Multiuser plugin to also add additional command (userLogin) which directly gets private key and logins user without any HTML and JS stuff. I will probably create ZeroNet PR for this in near future.


In the meantime, you have to manually login into ZeroNet instance from web interface. This will save private key so you will be able to use it from ZeroFramePy.

I have found the solution.

To use master address / master seed first of all you have to use your current address which has been sent in cookie to login

How multiuser works?

  1. When you go first time to ZeroNet you received session from server. It means in ZeroNet instance user has been created
set-cookie: master_address=XXXXXXXXX;path=/;max-age=2592000;
  1. When you use API you have to send cookie master_address=XXXXXXXXX

How my patch works?

  1. Download page to get wrapper_key from source code and also get value of current logged user in cookie master_address
  2. Use master_address and wrapper_key from step 1 and make web socket connection
  3. Change user - cmd userLoginForm and send master_seed of address which you want to make request - multiuser_master_seed
  4. Reconnect to API using master_address which you want to make requests multiuser_master_address.
  5. No {'error': 'No user found'} anymore

Now everything is working.

Please see on my ugly code - https://github.com/krzotr/ZeroFramePy/commit/31ff595719bf884587e0ed9f33a357762f14b945

@krzotr Thank you for your code! I will check it, clean it up a bit and include it here.

@krzotr Sorry for the delay but I didn't have mich time to do this. It should now be fixed in 85906fd. Can you check it so I can release changes as a new version?

Although code may look more complicated, it is needed to support:

  1. Instance without Multiuser plugin.
  2. Instance with Multiuser plugin with account provided by instance.
  3. Instance with Multiuser plugin with account address provided by user (account must already exist).
  4. Instance with Multiuser plugin with account address and seed provided by user (account will be created).

I will also port the changes to JS version (I hope soon) and refactor the whole library to be more modular (some time later).

I think that changes from 85906fd should work correctly so I released them as v1.1.0. If this issue still persists, or you have some other issues, please notice me.