Welcome to Tesla Motors Club
Discuss Tesla's Model S, Model 3, Model X, Model Y, Cybertruck, Roadster and More.
Register

Tesla Owners API v3 enabled

This site may earn commission on affiliate links.
Automated script setup to autogen token when it expires reported error to my email.

Thx for the info. Trying to sort through. Initial call to /oauth2/v3/authorize is showing Bad Request with no hidden fields. Is the GET supposed to be sent with any params? Using curl.

Yeah I'm not 100% sure how you recreate the CURL call.
To be successful , you really need a couple of items, and if you go to this form, you could capture network traffic and see it all happening:
Tesla SSO – Login

But the first piece is to first generate a URL, which the challenge etc:
Those URLs looking something like:

Tesla SSO - Sign In

Authentication
-first step is to generate URL parameters:

https://auth.tesla.com/oauth2/v3/authorize , then add ? and these URL params:

Prerequisites:
  • Use a HTTP client with a cookie jar.
  • Generate 86 random bytes to act as the challenge, encode as base 64 (URL variant). Let's call this challenge
  • Create a sha256 sum of those 86 bytes, encode as base 64 (URL variant). Let's call this sum.
  • Generate a random string, it can be anything at all. Let's call this state.
Steps
Note: Any values surrounded by { and } are variables. Such {sum} is a reference to a variable we declared earlier.

Authenticate
Send a request where code_challenge is equal to sum.

GET https://auth.tesla.com/oauth2/v3/authorize

With paramters below the sample call looks like:
https://auth.tesla.com/oauth2/v3/authorize?client_id=ownerapi&code_challenge={sum} and son on.



client_id = ownerapi

code_challenge = {sum}

code_challenge_method = S256

redirect_uri = Tesla SSO – Page Not Found

response_type = code

scope = openid email offline_access

state = {state}


Build a new map of URL values and pre-populate with two fields, identity and credential which are the username and password respectively.

{

identity: [{username}],

credential: [{password}]

}
Using the response from our last request, find all input[type=hidden] tags and add their respective name and value attributes to the map. The map should eventually look like:

{

identity: [{username}],

credential: [{password}],

_csrf: ['yj3XoCPV-rubeQEjoc8J9zDCihRFzAj21h6k'],

_phase: ['authenticate'],

_process: ['1'],

cancel: [],

transaction_id: ['iCeMaQlX'],

]
Now we can make another request. Encode the map to the request body as a URL encoded form.

POST https://auth.tesla.com/oauth2/v3/authorize

Content-Type: application/x-www-form-urlencoded



client_id = ownerapi

code_challenge = {sum}

code_challenge_method = S256

redirect_uri = Tesla SSO – Page Not Found

response_type = code

scope = openid email offline_access

state = {state}


This request will return status 302 (Found). Do not follow it. Parse the location of the redirect, and get the URL value called code.

Access token
Now we have a code, we can get an access token. We need to make another JSON request.

{

grant_type: 'authorization_code',

client_id: 'ownerap',

code_verifier: {challenge},

code: {code},

redirect_uri: 'Tesla SSO – Page Not Found',

}
POST https://auth.tesla.com/oauth2/v3/token

Content-Type: application/json


We'll then get back a response body with three tokens.

{

access_token: '...'

refresh_token: '...',

id_token: '...',

expires_in: 300,

state: {state},

token_type: 'Bearer'

}
Exchange token
We can now exchange our access token for a long-lived token.

{

grant_type: 'urn:ietf:params:eek:auth:grant-type:jwt-bearer',

client_id: '81527cff06843c8634fdc09e8ac0abefb46ac849f38fe1e431c2ef2106796384',

client_secret: 'c7257eb71a564034f9419ee651c7d0e5f7aa6bfbd18bafb5c5c033b093bb2fa3'

}
POST https://owner-api.teslamotors.com/oauth/token

Authorization: Bearer {access_token}

Content-Type: application/json


The response will contain your long-lived access token.

{

access_token: '...'

}
 
  • Like
Reactions: Heretic
@MrTemple – how long are these tokens good for? Or is a new token required each time the API is accessed?

If the third party uses the Refresh Token correctly, it will autogenerate a new token as needed. Most will do this, so you don't have to worry.

Also, is the pastebin URL something generic used by everyone, or should it be specific to each client?

Those are generic auth codes for accessing the Tesla authentication service. Same for all users. You can manually enter those values into the script and eliminate that extra call to pastebin if you like.

It's not my script (I did fix a bug in it to make it work), but I've reviewed all the calls and I'm confident that my credentials are only sent to Tesla.com from my personal computer as part of the proper token generation procedure.
 
  • Informative
Reactions: zƬesla
For the PHP'ers, note that the code referenced above worked fine on one system however set-cookie had to be changed to Set-Cookie on another (with a newer version of PHP).

Huh.

“Set-Cookie” didn’t work on my system but finally figured out that “set-cookie” did.

I had assumed the headers coming back were actually lower-case. Are you saying that the headers are different depending on the phone version? That’s odd.
 
Last edited: