26.04.2021, 07:02
This is due to outdated libraries in your firmware. Unfortunately it's not possible to update these libraries separately.
See if this works for you:
See if this works for you:
Code:
username = 'user@domain.com'
password = 'password'
client_id = 'ID'
client_secret = 'SECRET'
encdec = require('encdec')
http = require('socket.http')
mime = require('mime')
ltn12 = require('ltn12')
json = require('json')
function mt()
local ts, tu = os.microtime()
return ts .. '.' .. tu
end
function b64url(str)
return mime.b64(str):gsub('.', {
['+'] = '-',
['/'] = '_',
['='] = '',
})
end
function encodeargs(t)
local res = {}
local esc = require('socket.url').escape
for k, v in pairs(t) do
res[ #res + 1 ] = esc(k) .. '=' .. esc(v)
end
return table.concat(res, '&')
end
rnd = encdec.sha256(mt())
code_verifier = (rnd .. rnd):sub(1, 86)
state = b64url(rnd:sub(1, 12))
code_challenge = b64url(code_verifier)
args = encodeargs({
client_id = 'ownerapi',
code_challenge = code_challenge,
code_challenge_method = 'S256',
redirect_uri = 'https://auth.tesla.com/void/callback',
response_type = 'code',
scope = 'openid email offline_access',
state = state,
})
resp = {}
url = 'https://auth.tesla.com/oauth2/v3/authorize?' .. args
res, code, headers = http.request({
url = url,
sink = ltn12.sink.table(resp),
protocol = 'tlsv12',
})
if not res or code ~= 200 then
log('request 1 failed', res, code)
return
end
postdata = {}
regexp = '<input type="hidden" name="([^"]+)" value="([^"]*)"'
resp = table.concat(resp)
for name, value in resp:gmatch(regexp) do
postdata[ name ] = value
end
postdata.identity = username
postdata.credential = password
cookie = headers['Set-Cookie'] or headers['set-cookie'] or ''
body = encodeargs(postdata)
res, code, headers = http.request({
url = url,
method = 'POST',
source = ltn12.source.string(body),
protocol = 'tlsv12',
headers = {
['Content-Type'] = 'application/x-www-form-urlencoded',
['Content-Length'] = #body,
['Cookie'] = cookie,
}
})
if not res or code ~= 302 then
log('request 2 failed', res, code)
return
end
hdr = headers.Location or headers.location
resp_code = hdr:match('code=([^&]+)')
body = json.encode({
grant_type = 'authorization_code',
client_id = 'ownerapi',
code = resp_code,
code_verifier = code_verifier,
redirect_uri = 'https://auth.tesla.com/void/callback',
})
resp = {}
res, code, headers = http.request({
url = 'https://auth.tesla.com/oauth2/v3/token',
method = 'POST',
source = ltn12.source.string(body),
sink = ltn12.sink.table(resp),
protocol = 'tlsv12',
headers = {
['Content-Type'] = 'application/json',
['Accept'] = 'application/json',
['Content-Length'] = #body,
['User-Agent'] = 'Mozilla/5.0 (Linux; Android 9.0.0; VS985 4G Build/LRX21Y; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/58.0.3029.83 Mobile Safari/537.36',
['X-Tesla-User-Agent'] = 'TeslaApp/3.4.4-350/fad4a582e/android/9.0.0',
}
})
if not res or code ~= 200 then
log('request 3 failed', res, code)
return
end
resp = table.concat(resp)
resp = json.pdecode(resp)
bearer_token = resp.access_token
refresh_token = resp.refresh_token
body = json.encode({
grant_type = 'urn:ietf:params:oauth:grant-type:jwt-bearer',
client_id = client_id,
client_secret = client_secret,
})
resp = {}
res, code, headers = http.request({
url = 'https://owner-api.teslamotors.com/oauth/token',
method = 'POST',
source = ltn12.source.string(body),
sink = ltn12.sink.table(resp),
protocol = 'tlsv12',
headers = {
['Content-Type'] = 'application/json',
['Authorization'] = 'Bearer ' .. bearer_token,
['Content-Length'] = #body,
}
})
print(res, code)
if not res or code ~= 200 then
log('request 4 failed', res, code)
return
end
resp = table.concat(resp)
resp = json.pdecode(resp)
access_token = resp.access_token
log(access_token)