klanchman / homebridge-logi-circle-controls

Homebridge plugin for extended Logitech Circle camera controls
MIT License
21 stars 1 forks source link

Logitech is transitioning mobile app to SSO / OAuth #26

Closed klanchman closed 3 years ago

klanchman commented 3 years ago

Logitech pushed out version 3.5 of their iOS app recently, which now uses SSO / OAuth for authentication. This is notable because this plugin relies on the authentication method the mobile app used to use. My assumption is that Logitech will eventually force users to update the app and turn off the old auth mechanism. The plugin will probably need to move to the new auth flow.

I played around with the new app and managed to successfully complete the auth flow manually.

Auth Flow

The SSO flow uses OAuth with PKCE: https://datatracker.ietf.org/doc/html/rfc7636

  1. Generate a code verifier. The code is a random string that must be from 43 to 128 characters long, with only the characters [A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~". Create the SHA256 hash of the code, and then base64url encode the hash. The resulting value will be called the code challenge.

  2. Visit the login page in a browser.

    https://id.logi.com/?client_id=0499da51-621f-443f-84dc-5064f631f0d0&scope=circle:all&response_type=code&redirect_uri=com.logitech.Circle:%2F%2Flids&code_challenge_method=S256&code_challenge=<code challenge>
    • The client_id belongs to the iOS app
  3. Sign into your Logi account. Your browser will be unable to open the resulting page, which is fine. Copy the value of the code query parameter.

  4. Exchange the code from the previous step for an access and refresh token.

    • curl -X "POST" "https://accounts.logi.com/identity/oauth2/token" \
      -H 'Content-Type: application/x-www-form-urlencoded; charset=utf-8' \
      --data-urlencode "grant_type=authorization_code" \
      --data-urlencode "client_id=0499da51-621f-443f-84dc-5064f631f0d0" \
      --data-urlencode "code_verifier=<code verifier>" \
      --data-urlencode "code=<code>" \
      --data-urlencode "redirect_uri=com.logitech.Circle://lids"
  5. Use the access token in subsequent API requests to video.logi.com

    • Set the Authorization header to LIDS <access token>
  6. Eventually, the access token will expire. Use the refresh token to get new access and refresh tokens.

    • curl -X "POST" "https://accounts.logi.com/identity/oauth2/token" \
      -H 'Content-Type: application/x-www-form-urlencoded; charset=utf-8' \
      --data-urlencode "grant_type=refresh_token" \
      --data-urlencode "client_id=0499da51-621f-443f-84dc-5064f631f0d0" \
      --data-urlencode "code_verifier=<code verifier>" \
      --data-urlencode "refresh_token=<refresh token>" \

Other notes

Implications

There are a few implications about this flow:

shamoon commented 3 years ago

Hey, having a similar issue with my app, I see how you do it, kicking the user out to their browser. Did you look at implementing this within the Homebridge UI? I cant really see how it'd be done because you'd need to load the login UI in an iframe, I guess, and then you'd run into cross-domain restrictions?

klanchman commented 3 years ago

Hey! 👋 Homebridge UI is on my to do list, but I haven’t looked closely at how all that works yet. I hadn’t thought about using an iframe for the login flow. I haven’t used iframes extensively, but looking around it seems like you’re right: I’d be lucky if it worked initially, and Logitech could probably change a few options on their site at any time to stop it from working. 😞

Worst case, my plan was to do essentially the same flow the CLI tool does: open a new browser tab/window to Logitech’s login page, then the user logs in and copies the redirected URL back into the Homebridge UI.

This plugin may also be worth a look: https://github.com/Brandawg93/homebridge-nest-cam — that’s where I got the CLI tool idea from 😄

shamoon commented 3 years ago

Cheers, yea copy/pasting the URL seems like an acceptable fallback. And thanks for the nest-cam reference. Good luck to us all 😅

shamoon commented 3 years ago

Hey, have you noticed that Google Chrome doesnt actually forward to the auth URL (with the code) because of the com.logitech.circle:// iOS app handler e.g. throws error: Failed to launch 'xxx' because the scheme does not have a registered handler. And as noted, we cant just use an arbitrary redirect_uri

How are you handling that, just warning the user? Seems like they need to pull up the error console to get the code, ugh.

(my app has the same problem obviously)

klanchman commented 3 years ago

Oh boy, good catch 😓 My main browser is Safari, and I mistakenly assumed the rest would behave the same.

Safari actually follows the redirect and shows a "Safari can't open the specified address." page. The address bar has the callback URL in it, so the user can copy-paste back into the CLI tool.

I tested Firefox and Vivaldi and they both get stuck on a page with a button that throws warnings in the console like you saw. The URL isn't updated in the address bar. 😞

I'll need to update the CLI tool / docs to explain that the user needs to open the debug console and copy the URL from there. Worst case, that's all I'll be able to do.

I have a bit of a hack in mind to make this better for the user, but I'm not sure it'll work that well... Maybe I can register that URL scheme when the CLI tool runs, and deregister it when it's done. I found this package that could help do that. The thing is, even if this works, the user may be running the CLI tool on a machine other than the one with the browser (I'd be ssh-ing into my Homebridge virtual machine to run the CLI tool). This approach probably wouldn't work in that case.

(It occurs to me I need to check if how I open the URL from the CLI tool even works over ssh. Might need to print the URL to the terminal just in case.)

klanchman commented 3 years ago

Alright, the URL scheme hack isn't probably worth the hassle. And my hunch about opening the URL automatically over SSH was right, it doesn't work.

Here's a PR that shows the changes I'm making to the CLI tool to deal with all this.

I'm going to be filling out this wiki page with instructions and screenshots from multiple browsers to help users if they get stuck.

Not sure what else to do, unfortunately 😓

shamoon commented 3 years ago

Cool, thanks for sharing!

Yea I guess we just have to accept that its not going to be totally seamless. Annoying because this all boils down to the fact that auth0 (both logi and SS use) dont let you use an arbitrary redirect_uri. Other oauth implementations do, and those plugin devs do something cool where they spin up a tiny 'server' and redirect the authorization to that 'server', capture the code etc. all automagically.

Oh well 🙂