tdorssers / TeslaPy

A Python module to use the Tesla Motors Owner API
MIT License
374 stars 83 forks source link

Asynchronous authenticator? #45

Closed morpheus65535 closed 3 years ago

morpheus65535 commented 3 years ago

It would be nice to be able in a web application to show the auth url then wait for the user to provide the url including the code through a form submission. Any idea how I could achieve that?

tdorssers commented 3 years ago

By using an authenticator function, which is a callback, you get some async functionality. TeslaPy is a synchronous library. Which framework are you planning to use?

morpheus65535 commented 3 years ago

Currently I'm running some test with Flask and Threading.Event. Looks promising and I'll update this issue when I get it working for the benefit of others.

tdorssers commented 3 years ago

I am working on splitting fetch_token() in two methods. If you don't supply an argument to fetch_token, then it will behave the same as before. A new method will generate the auth url and you can supply the redirected url as an argument to fetch_token. Will that help/make life easier?

morpheus65535 commented 3 years ago

Will those two method be independant? Is it gonna be possible to call the first method to get the auth_url then, from a different Falsk route, call the fetch_token method with only the auth_url and (let's call it) the code_url as argument? How will the Tesla class will behave on init if there's no token?

tdorssers commented 3 years ago

Yes the methods are independent and will behave like you described. On init, the class will try to read the token from the cache file. If there is no token in the cache file or no file at all, then nothing will happen. The first API call that you try to make, will call fetch_token() without arguments automatically, meaning it will use the authenticator function to get the code. So in your Flask app, you need to make sure not to call an API before you are authenticated using the 'two step' way.

morpheus65535 commented 3 years ago

It sounds really good! I look forward to this new release! :-)

tdorssers commented 3 years ago

Please check out 333c114. You can use it like this:

import teslapy

with teslapy.Tesla('elon@tesla.com') as tesla:
    print(tesla.authorization_url())
    tesla.fetch_token(authorization_response=input('URL: '))
    vehicles = tesla.vehicle_list()
    print(vehicles[0])

tesla.authorization_url() will generate the auth url. you pass the redirected url to fetch_token() using keyword argument authorization_response.

morpheus65535 commented 3 years ago

Does it need to be call inside a context manager or can I simply instantiate the tesla object and reuse it?

tdorssers commented 3 years ago

Context manager is optional. You can instantiate a tesla object and close it when done.

tesla = Tesla('elon@tesla.com')
# do stuff
tesla.close()

authorization_url() and fetch_token() must be called on the same instance. But I can change that, the state and code_verifier are needed between those calls, so I can make authorization_url() provide a 3-tuple with url, state and code_verifier and make fetch_token() take those as keyword arguments.

morpheus65535 commented 3 years ago

It works perfectly fine the way you did it! Thank you very much! 👍

morpheus65535 commented 3 years ago

Would it be too much if I ask for a logout method that would set authorized to False and delete the cached token?

tdorssers commented 3 years ago

No not really, please give 917f6af a try.

morpheus65535 commented 3 years ago

@tdorssers as expected, it just works! Any way to show my gratitude? Maybe a beer or other kind of donation?

tdorssers commented 3 years ago

Thanks! How are you managing with vehicle wake up and other calls from your web app?

morpheus65535 commented 3 years ago

Basically my web app is an evolution from my headless shceduled preheating app that was configured using environment variables. I'm refactoring it to use a config file instead and the frontend will be used to generate the token and edit the config file.

So, until the token is valid and teslapy autorized is True, the schedule task isn't able to start. Once the user as authenticated and we have a valid token, the scheduled task will run based on user requirement (ex.: every weekday at 7am). I also have a maximum preheating length that stop the preheating after a specified delay to prevent preheating to be left enabled for 4 hours if not required.

morpheus65535 commented 3 years ago

@tdorssers any ETA for releasing master to a new version on pypi? For now I'm linking to this repo in my requirements.txt but making it more "official" would be great ;-)

thanks!

tdorssers commented 3 years ago

Just released 2.2.0 a few minutes ago!

morpheus65535 commented 3 years ago

Thank you very much! Really appreciated. :-)

I'll close this issue now.