SecKatie / wyzeapy

35 stars 26 forks source link

Add support for Roku authentication #58

Open Klikini opened 1 year ago

Klikini commented 1 year ago

This change adds:

I have tested the authentication process and controlling bulbs and both work perfectly. However, the Wyze test file (and therefore the Roku test file since it's mostly the same so far) reference an async_close method on the Wyzeapy and Rokuapy objects that doesn't seem to exist, and omit a local_control argument on the turn_off, turn_on, and set_color methods of the bulb classes. Adding local_control=True to these seems to work, but I didn't commit that because I don't know how it's intended to be used.

If this is merged, I plan to either: A) add a "use Roku authentication" switch to the Wyze HACS integration that allows switching to Roku mode, or, if the integration is not instanced B) maintain a fork of the Wyze HACS integration that uses Roku mode. Any input here is appreciated :)

CLAassistant commented 1 year ago

CLA assistant check
All committers have signed the CLA.

JoeSchubert commented 1 year ago

Assuming that the token ends up being the same, why do you need to authenticate against the Roku server? Just use the normal auth token in whatever Roku functionally you intend to add for Roku.... I don't see any additional subscription added in this unless I'm missing something?

I'd be willing to bet that this will break the things that Wyze adds extra encryption to, ie: locks and home monitoring, as they likely don't loop those through Roku. At least, I really hope they don't.

Klikini commented 1 year ago

We need to log into the Roku authentication server because the Wyze authentication server doesn't recognize Roku accounts. The Roku authentication server then returns two OAuth tokens: a Roku API token and a "partner" token for the Wyze API. Once the partner token is obtained, it is passed to existing Wyze functions with slight changes in headers: the reason for the separate services is that some of them use different sc/sv values from the Wyze endpoints, and they all require milliseconds for the timestamp parameter, and these are both accounted for in the RokuBaseService class.

The changes I made should not affect the functionality of the WyzeAuthService and BaseService classes, though I don't personally have any Wyze devices to verify this with.

JoeSchubert commented 1 year ago

The Roku authentication server then returns two OAuth tokens: a Roku API token and a "partner" token for the Wyze API.

Ok, and how is re-authentication handled then? Currently when you authenticate to the Wyze server you get an auth token and a refresh token. The auth token expires after about 48 hours and you have to use the refresh token to obtain a new authentication token.

I see some lines that you changed for the refresh token. Is that re-obtained from the Roku server as well?

I honestly have no interest in making a Roku account to test this against and I doubt Josh does either, though I can't speak for him. Or does this use wyze's accounts through Roku's servers? Trying to understand the goal of this, especially if you're using this Wyze API tool without any Wyze devices to test against or use it on.

Just to clarify... Are there more feature additions coming that rely on authenticating against the Roku servers? Otherwise I really don't see what's being gained by supporting the Roku server authentication.

SecKatie commented 1 year ago

@Klikini, thanks for the code! I think that this project is an excellent place for some of this to live (since so much of the backend stuff is the same).

I will do a more thorough code review, but my first thought is that you have done a great job making it multi-provider capable.

On the item of how we should handle the home assistant integration, I think that the best course of action would be to add some switch code controlled by a const somewhere. Then we could fork it, and the only change that would have to be maintained differently would be the name of the integration and that one const.

It would be best, in my opinion, to keep the repos for them separate so that it is clear which one to install for your system (in the selection menus, etc.)

Klikini commented 1 year ago

@JoeSchubert Good point, I assumed the refresh token would work with the Wyze endpoint, but I will need to verify this by capturing mobile app traffic when it performs a refresh, and I am out of town this week so I won't be able to do that for a few days.

@SecKatie Great idea on the fork/flag; I can definitely do that once I'm back home.

JoeSchubert commented 1 year ago

Good point, I assumed the refresh token would work with the Wyze endpoint, but I will need to verify this by capturing mobile app traffic when it performs a refresh

Right. I don't know if it will matter much or not. If a flag is added, it would be easy enough to simply leave the refresh logic to be handled by Roku's servers if that flag is set. However, most of calls currently will call... I think it's "refresh_if_should()" which will try to grab a new token from Wyze with the refresh token. If the token provided from Roku works fine for this, I don't think it will be an issue. But if it doesn't... It will basically break the entire process after about 48 hours or so when things start to think that the token needs refreshed.

Also, I apologize if I came off harsh at all originally. I tend to be fairly blunt.

Klikini commented 1 year ago

@JoeSchubert correct. Do you have any tips for triggering a token refresh while I'm intercepting traffic? Opening the app for the first time in weeks didn't seem to do anything different than usual. (And, at worst, is there any harm in getting a new session token every time it's about to expire?)

JoeSchubert commented 1 year ago

@JoeSchubert correct. Do you have any tips for triggering a token refresh while I'm intercepting traffic? Opening the app for the first time in weeks didn't seem to do anything different than usual. (And, at worst, is there any harm in getting a new session token every time it's about to expire?)

Sorry. For some reason I guess I don't get GitHub email notifications anymore.

I really don't. The refresh logic was already implemented prior to me getting involved here. I don't imagine getting a new token would hurt. However, if the user has MFA enabled... I believe you're going to trigger MFA if you request a new token without using the refresh token. Unless I'm confused about what you're asking?

Klikini commented 1 year ago

@JoeSchubert Roku accounts don't support MFA, so I don't think that would be a problem. That said, I will still try to capture a refresh from the Roku app at some point so we can be prepared if they ever decide to add it.

830008 commented 1 year ago

Sorry to bump this, however, it could be very useful for me.

jhaenchen commented 1 year ago

How's it going? Fight the local home management fight!

Klikini commented 1 year ago

I never succeeded in capturing a session refresh from the Roku Home app.

I ended up buying used LIFX bulbs for cheap to put in the fixture I was going to use the Roku bulbs in :/

I'm hoping they update them to support Thread or Homekit or something eventually.