alandtse / tesla

Tesla custom integration for Home Assistant. This requires a refresh token be generated by third-party apps to login.
Apache License 2.0
554 stars 99 forks source link

[Docs] Update Tesla Refresh Token Generator list #879

Open baylanger opened 4 months ago

baylanger commented 4 months ago

Quickly documenting some findings related to this topic.

Tesla Tokens for Android is dead, currently not available on Google Play. Tesla v3 API Tokens link in info.md is dead. With some keywords tried to search for an updated link, couldn't find.

Github has the following recent/active projects: TeslaApiTokenGenerator . Python script . first/last commit 6m . runs local

fetch-tesla-token . server written in node.js . last commit 4m, 5y old . runs local . do we need another add-on ;)

Over the Web tesla-info.com . good for dummies . URL sent to web service, use at own risk

Zappo-II commented 3 months ago

Mentioned first python script works good enough for me https://github.com/sebmatton/TeslaApiTokenGenerator THX...

maruel commented 3 months ago

I was thinking about updating the prompt to link to https://chromewebstore.google.com/detail/access-token-generator-fo/kokkedfblmfbngojkeaepekpidghjgag. It would only work on desktop but for desktop users that's be nicer to click through. As a matter of fact the mobile apps references should be converted to links to their corresponding store.

madsdyd commented 3 months ago

Like @Zappo-II it would appear the first linked python script works for me.

However, the first time I updated the info in the dialog box, I actually made a copy-paste error, and the Tesla integration still claimed to succeed. However, it did not. Is there a chance that the config process does not catch an error (might be higher that I made a mistake.).

llamafilm commented 3 months ago

I like the approach of TeslaApiTokenGenerator. Has anyone tried using a token from there with the Fleet API Proxy? I'm guessing it won't work because it needs your Client ID to be part of the request. Maybe I should remove the OAuth flow from the addon and improve this copy/paste method instead.

llamafilm commented 3 months ago

None of these apps work with Fleet API, although they could be modified quite easily. This one does support both the old and the new API: Tesla Auth app on macOS and iOS. They've done something clever to intercept the HTTP request and grab the code even if your callback URL doesn't really work.

I haven't found one for Android.

zSeriesGuy commented 2 weeks ago

I am not a iPhone user. So I struggled with getting the refresh token. I took the TeslaApiTokenGenerator code and modified it to work with the client ID and Client Secret. It works. Modified code below.

import secrets
import hashlib
import base64
import string
import requests
import webbrowser
from urllib.parse import urlparse, urlencode, parse_qs

import json

# Print header
print(header)

# Get user email address
login_email = input("> Enter your email address: ")
client_id = input("> Enter your client-id: ")
client_secret = input("> Enter your client-secret: ")
redirect_uri = input("> Enter your Allowed Redirect URI: ")

# Generate an 86-character random string
characters = string.ascii_letters + string.digits
code_verifier = ''.join(secrets.choice(characters) for x in range(86))

# Calculate the SHA-256 hash of the code_verifier
sha256 = hashlib.sha256()
sha256.update(code_verifier.encode('utf-8'))
digest = sha256.digest()

# Generate an other 15-character random string
oauth_random = ''.join(secrets.choice(characters) for x in range(15))

# Encode the SHA-256 hash using base64
code_challenge = base64.urlsafe_b64encode(digest).rstrip(b'=').decode('utf-8')

base_url = "https://auth.tesla.com/oauth2/v3/authorize"
params = {
    'response_type': 'code',
    'client_id': client_id,
    'redirect_uri': redirect_uri,
    'scope': 'openid offline_access',
    'state': oauth_random,
    'code_challenge': code_challenge,
    'code_challenge_method': 'S256',
    'login_hint': login_email
}

url_with_params = base_url + '?' + urlencode(params)

print("\nAfter successfully authenticating your Tesla account, copy the url of the \"Page Not Found\" page (Should be in the form \"https://auth.tesla.com/void/callback?code=...\").")
input("\nType ENTER to proceed...")

# Open web browser
webbrowser.open(url_with_params)

# Retrieve final url
response_url = input("\n> Paste the url you obtained after login: ")

# Parse the URL
parsed_url = urlparse(response_url)

# Retrieve the "code" parameter
query_parameters = parse_qs(parsed_url.query)
code_parameter = query_parameters.get('code', [''])[0]

# -- STEP 3 -- 

response = requests.post("https://auth.tesla.com/oauth2/v3/token",
        headers={
            'Content-Type': 'application/x-www-form-urlencoded'},
        data={
            "grant_type": "authorization_code",
            "client_id": client_id,
            "client_secret": client_secret,
            "code": code_parameter,
            "code_verifier": code_verifier,
            "redirect_uri": redirect_uri
        }
    )

# Send the POST request with the parameters
response_json = json.loads(response.text)

# Check the response status code and content
if response.status_code == 200:
    print("\nToken request successful!")
    print("\n=> Access token: ", response_json["access_token"])
    print("\n=> Refresh token: ", response_json["refresh_token"])
else:
    print("\nToken request failed with status code: ", response.status_code)
    print(response_json["error"])
    print(response_json["error_description"])

print("\n\nDone!")
llamafilm commented 2 weeks ago

I think we could change the docs to recommend the "fake callback" feature built into the proxy addon. @zSeriesGuy I'm curious why that approach didn't work for you?

P.S. I originally built it with a real callback handler, but most users could not figure out how to set it up properly, so I changed it for simplicity. The new way feels hacky but it turns out it's easier for most people to use.

zSeriesGuy commented 2 weeks ago

I am running Home Assistant OS in a VM on TrueNAS scale. My reverse proxy is Traefik. I searched the net to try to find info on how to set up the Tesla HTTP Proxy under this scenario. I ended up installing the external IP TrueNAS app to point to my HA VM on port 80. In HA, I installed the Apache minimal app with the config that routes the Tesla cert request to the /share/tesla location of the certs. I had found this configuration on the internet somewhere. This got me past the Tesla HTTP Proxy setup and I was able to enroll the public certs to the vehicles. I then went to configure the Tesla custom integration. I selected to use the HTTP proxy, It then wanted an email address and a refresh token, It says to use the IOS app to get the refresh token. I don't have Apple phone. And it appears that the other options for android are no longer available. Hence the code above to get the refresh token. Is this not the correct method?

llamafilm commented 2 weeks ago

The addon docs explain how to get a token using the Web UI. That should work on any web browser, not just iPhone.