guerrerotook / securitas-direct-new-api

This repository contains the new securitas direct API that can be integrated in Home Assistant
Apache License 2.0
78 stars 30 forks source link

Can't setup the integration anymore #227

Closed chabou-san closed 5 months ago

chabou-san commented 5 months ago

Hello,

First I want to thank you for developing and maintaining this integration. I've been a long user and it usually worked like a charm. Today, a technician from Securitas performed some maintenance on my alarm system and removed (without notice) the local account I use for this integration. Therefore, I had to do the setup process all over again. I removed the integration, stopped HA, updated this integration to the latest tag, restarted HA and went to setup the integration.

Unfortunately, it failed to setup after having set the SMS from 2FA. I received this new kind of error : I guess Securitas changed the JWT token format, since I can read Invalid token type :

Logger: aiohttp.server
Source: /usr/local/lib/python3.12/site-packages/aiohttp/web_protocol.py:421
First occurred: 13:55:03 (1 occurrences)
Last logged: 13:55:03

Error handling request
Traceback (most recent call last):
  File "/config/custom_components/securitas/securitas_direct_new_api/apimanager.py", line 338, in login
    token = jwt.decode(
            ^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/jwt/api_jwt.py", line 210, in decode
    decoded = self.decode_complete(
              ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/jwt/api_jwt.py", line 151, in decode_complete
    decoded = api_jws.decode_complete(
              ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/jwt/api_jws.py", line 198, in decode_complete
    payload, signing_input, header, signature = self._load(jwt)
                                                ^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/jwt/api_jws.py", line 254, in _load
    raise DecodeError(f"Invalid token type. Token must be a {bytes}")
jwt.exceptions.DecodeError: Invalid token type. Token must be a <class 'bytes'>
File "/config/custom_components/securitas/config_flow.py", line 103, in async_step_otp_challenge
    return await self.finish_setup()
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/securitas/config_flow.py", line 107, in finish_setup
    await self.securitas.login()
  File "/config/custom_components/securitas/__init__.py", line 353, in login
    await self.session.login()
  File "/config/custom_components/securitas/securitas_direct_new_api/apimanager.py", line 344, in login
    raise SecuritasDirectError(
custom_components.securitas.securitas_direct_new_api.exceptions.SecuritasDirectError: Failed to decode authentication token None

Let me know if you need more information or how I can help to help you fix this issue.

Thanks in advance !

cantupaz commented 5 months ago

did you try a second time? Sometimes these errors resolve themselves. I don't think they've changed the format of the token (or the integration would stop working for most of us).

chabou-san commented 5 months ago

I’ll try a new time in a few hours, but I did retry some time later and it was still not working. From what I inspected in my web browser inspector, the token format hasn’t changed : I’ve been able to decode the payload.

I think it’s more in the order of the requests that it may have changed, or the token is not repeated after the 2FA validation in the login resquest. I guess the code expects it that way, but the token really is not set at that time. I didn’t spend enough time to understand where the code is not working for me.

cantupaz commented 5 months ago

When you configure the integration try leaving unchecked the "Use 2FA" checkbox. It shouldn't make a difference, but maybe worth a try.

chabou-san commented 5 months ago

I just did some tries, and I'm still blocked at the same place. :(

I did try to leave the checkbox "Use 2FA" unchecked, but I got an error "An error occurred" within the dialog box : I must say I'm not surprised as 2FA is required in France from several months now.

I'm still blocked with the missing token in the login function call error in the logs :

File "/config/custom_components/securitas/config_flow.py", line 153, in async_step_user
    return await self.finish_setup()
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/securitas/config_flow.py", line 107, in finish_setup
    await self.securitas.login()
  File "/config/custom_components/securitas/__init__.py", line 353, in login
    await self.session.login()
  File "/config/custom_components/securitas/securitas_direct_new_api/apimanager.py", line 344, in login
    raise SecuritasDirectError(
custom_components.securitas.securitas_direct_new_api.exceptions.SecuritasDirectError: Failed to decode authentication token None

I'll try to debug a bit, because maybe I already have the token from previous functions and may not need to set it in the login function.

guerrerotook commented 5 months ago

Did you know that you can enable debug logs in the integration so you can see the API output as well?

chabou-san commented 5 months ago

No, I didn't know ! Can you direct me as to where it is explained how to enable it ?

guerrerotook commented 5 months ago

You have to do thing like this in your configuration.yaml

logger:
  default: error
  logs:
    custom_components.securitas: debug
chabou-san commented 5 months ago

Having enabled debug logs, I can see the login request result (the message below means "User correctly validated"), and as "expected" the hash is not set :

{"data":{"xSLoginToken":{"__typename":"XSLoginToken","res":"OK","msg":"Utilisateur correctement validé","hash":null,"refreshToken":null,"legals":false,"changePassword":true,"needDeviceAuthorization":null,"mainUser":false}}}
chabou-san commented 5 months ago

When I log into the website in my browser, the hash is set in the "Validate Device" request, and from there, no login request is made.

When I try to setup the integration, the debug logs for the "Validate Device" don't show the hash, like for the login request:

{"data":{"xSValidateDevice":{"res":"OK","msg":"Demande effectuée correctement","hash":null,"refreshToken":null,"legals":null}}}
cantupaz commented 5 months ago

,"mainUser":false

Looks like you're using a secondary account. It should work, but could you try with your main account?

chabou-san commented 5 months ago

Good catch, you just made my day ! Problem is solved, let me explain (for you guys and possibly other people some day).

I did create a dedicated user for this integration, to separate my usage from the "normal" one (my phone, my web browser etc.). I gave it the access the proper rights (no admin rights for example), but I didn't went to the website with this new account (always used my normal account, as it has admin rights). Your question made me want to connect to securitas website with this new restricted account. Doing so made me "finish the setup of the account" : I realised that it was not fully trusted by securitas yet, and notably I had to change my password, validate it through 2FA and connect again. After doing all theses steps, I have been able to have my account properly validated from securitas POV, and I'm now able to add the integration properly into HA.

Once again, thank you guys for the support, I wouldn't have find it without you. And of course thank you too for the development of this integration :)

cantupaz commented 5 months ago

I'm glad that it worked.