teslamotors / vehicle-command

Apache License 2.0
445 stars 102 forks source link

Unable to call /api/1/users/me as user_data scope missing from access token #49

Open drnic opened 12 months ago

drnic commented 12 months ago

When I generate an access token I am asking for the user_data scope, which is required for /api/1/users/me and other endpoints. But this scope is not being included in the access token, and so I cannot get the details of the authenticated/authorized user. Any seen this and have ideas what I might be missing?

The error I get accessing these endpoints is:

{"response":null,"error":"Unauthorized missing scopes","error_description":""}

To reproduce:

#!/bin/bash

# scopes we want, which includes user_data
# unrelated: offline_access is provided here, which is mentioned in docs, but it too is not in access token
scope="openid user_data offline_access vehicle_device_data vehicle_cmds vehicle_charging_cmds"
state=${state:-123456781234}
: ${TESLA_CLIENT_ID:?required}
: ${TESLA_CLIENT_SECRET:?required}
AUDIENCE=${AUDIENCE:-https://fleet-api.prd.na.vn.cloud.tesla.com}

# if access_token.txt doesn't exist then:
if [[ -f access_token.txt ]]; then
  echo "access_token.txt exists so using it"
  echo
else

  echo "Visit this URL:"
  echo "https://auth.tesla.com/oauth2/v3/authorize?client_id=${TESLA_CLIENT_ID}&redirect_uri=https%3A%2F%2Fmyapp.com%2Fauth%2Ftesla%2Fcallback&response_type=code&scope=openid%20user_data%20offline_access%20vehicle_device_data%20vehicle_cmds%20vehicle_charging_cmds&state=${state}"
  echo
  echo "When the auth sequence is finished and it fails to redirect to the callback URL"
  echo "since the app is not running, copy the code=XYZ from the URL and paste it here:"
  read code

  token_response=$(
    curl -sS 'https://auth.tesla.com/oauth2/v3/token' \
      -H 'Content-Type: application/json' \
      -d "$(jq -n \
        --arg client_id "$TESLA_CLIENT_ID" \
        --arg client_secret "$TESLA_CLIENT_SECRET" \
        --arg code "${code:?required}" \
        --arg scope "$scope" \
        '{
            grant_type: "authorization_code",
            client_id: $client_id,
            client_secret: $client_secret,
            code: $code,
            scope: $scope,
            audience: "https://fleet-api.prd.na.vn.cloud.tesla.com",
            redirect_uri: "https://myapp.com/auth/tesla/callback"
          }')"
  )
  access_token=$(echo "$token_response" | jq -r .access_token)
  # id_token=$(echo "$token_response" | jq -r .id_token)

  echo "access_token: ${access_token}"
  echo $access_token | jwt decode -
  echo

  echo "Saving access_token to access_token.txt"
  echo "$access_token" >access_token.txt
fi

# the following fails because access token does not have `user_data` scope, even though we asked for it:
curl "${AUDIENCE}/api/1/users/me" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $(cat access_token.txt)"

The jwt decode command outputs my access token's claims:

{
  "amr": [
    "pwd",
    "mfa",
    "otp"
  ],
  "aud": [
    "https://fleet-api.prd.na.vn.cloud.tesla.com",
    "https://fleet-api.prd.eu.vn.cloud.tesla.com",
    "https://auth.tesla.com/oauth2/v3/userinfo"
  ],
  "auth_time": 1700345533,
  "azp": "42faaff2d33a-xxx",
  "exp": 1700374340,
  "iat": 1700345540,
  "iss": "https://auth.tesla.com/oauth2/v3/nts",
  "locale": "en-AU",
  "ou_code": "NA",
  "scp": [
    "openid",
    "vehicle_device_data",
    "vehicle_cmds",
    "vehicle_charging_cmds"
  ],
  "sub": "6c81818d-xxx"
}

I asked for scopes: openid user_data offline_access vehicle_device_data vehicle_cmds vehicle_charging_cmds But token only includes: openid vehicle_device_data vehicle_cmds vehicle_charging_cmds

And so I cannot call /api/1/users/me or similar user_data endpoints.

Anyone seen this and have a solution?

drnic commented 12 months ago

Also odd: when logging into developer.tesla.com we do the oauth2 dance, but they use an older auth endpoint https://auth.tesla.com/en_au/oauth2/v1/authorize instead of https://auth.tesla.com/oauth2/v3/authorize which we're asked to use.

Interestingly they pass through a request for some different scopes: user profile ou_code email

I tried these on v3/authorize and user is dropped/not included in the access token, but profile ou_code email are present. Sadly, I still cannot call /api/1/users/me or other user_data endpoints

{
  "amr": [
    "pwd",
    "mfa",
    "otp"
  ],
  "aud": [
    "https://fleet-api.prd.na.vn.cloud.tesla.com",
    "https://fleet-api.prd.eu.vn.cloud.tesla.com",
    "https://auth.tesla.com/oauth2/v3/userinfo"
  ],
  "auth_time": 1700356136,
  "azp": "42faaff2d33a-xxx",
  "exp": 1700384941,
  "iat": 1700356141,
  "iss": "https://auth.tesla.com/oauth2/v3/nts",
  "locale": "en-AU",
  "ou_code": "NA",
  "scp": [
    "openid",
    "offline_access",
    "vehicle_device_data",
    "vehicle_cmds",
    "vehicle_charging_cmds",
    "profile",
    "ou_code",
    "email"
  ],
  "sub": "6c81818d-xxx"
}

Update: I think I posted a refresh token above. But that's still interesting - the refresh token ejects the user_data scope (and user scope request) upfront; whilst keeping the other scopes.

But the other scopes all disappear in the access token payload:

{
    "amr": [],
    "aud": [
      "https://fleet-api.prd.na.vn.cloud.tesla.com",
      "https://fleet-api.prd.eu.vn.cloud.tesla.com",
      "https://auth.tesla.com/oauth2/v3/userinfo"
    ],
    "azp": "42faaff2d33a-xxx",
    "exp": 1700728050,
    "iat": 1700699250,
    "iss": "https://auth.tesla.com/oauth2/v3/nts",
    "locale": "en-AU",
    "ou_code": "NA",
    "scp": [
      "offline_access",
      "openid",
      "vehicle_device_data",
      "vehicle_cmds",
      "vehicle_charging_cmds"
    ],
    "sub": "6c81818d-xxx"
  }
drnic commented 12 months ago

@ThomasAlxDmy @sethterashima @fabianhu Can you help spot or suggest why user_data scope might not be appearing in refresh token nor access token? Any help or ideas is greatly appreciated.

Urkman commented 11 months ago

I have exactly the same problem. Any help on this?

And one question: Why is Tesla already disabling cars, when the new API is still not working 100% (vehicle_command for EU cars was fixes today). How should we third party developers update our app without this?

Urkman commented 11 months ago

I tried every endpoint that needs the user_data scope. None of them are working. Every endpoint returns Unauthorized missing scopes

@sethterashima can you help us with this? Or name someone who can help. I already wrote an email to the support over one week ago, but no answer.

fanhaipeng0403 commented 11 months ago

@drnic When users log in, the authorization scope used is "scope=openid profile email offline_access user_data vehicle_device_data vehicle_cmds vehicle_charging_cmd," which works successfully.

image
fanhaipeng0403 commented 11 months ago

However, accessing the API endpoint "/api/1/users/orders" is still not possible, and the documentation does not specify which authorization scope it belongs to. The error persists.

image
Urkman commented 11 months ago

@fanhaipeng0403 Where did you found information about adding " profile email " to the scopes?

Urkman commented 11 months ago

For me this ist still not working :(

I use this scope: openid offline_access vehicle_device_data vehicle_cmds vehicle_charging_cmds user_data profile email

And here is the full URL to authorize: https://auth.tesla.com/oauth2/v3/authorize?response_type=code&client_id=CLIENT_ID&state=STATE&scope=openid%20offline_access%20vehicle_device_data%20vehicle_cmds%20vehicle_charging_cmds%20user_data%20profile%20email&redirect_uri=REDIRECT_URL

But I see, that you are using a cn host...

drnic commented 11 months ago

I was not able/allowed to authorized via the .cn audience https://fleet-api.prd.cn.vn.cloud.tesla.com; and as above the .na audience route does allow me to authorize but we are missing the user_data scope in our tokens :/

Urkman commented 11 months ago

I tried with .eu audience.

Urkman commented 11 months ago

@sethterashima This is still not working :( Can you pleas help us, as we need to update our apps?

Urkman commented 11 months ago

I nobody interested in fixing this?

NikhilTank35 commented 10 months ago

fyi. https://github.com/teslamotors/vehicle-command/issues/123

supleshg commented 10 months ago

@drnic @Urkman Try revoking previously granted access, and then attempt to obtain an access token. This time, you will be prompted with checkboxes for the required scopes. you can refer to this to revoke an access.

aaronpkahn commented 6 months ago

FYI all, we now support user scope updates from within accounts.tesla.com. This is documented on #5 in the https://developer.tesla.com/docs/fleet-api#third-party-token authentication section. Applications can direct users to https://auth.tesla.com/user/revoke/consent?revoke_client_id=$CLIENT_ID&back_url=$RETURN_URL to request additional scopes or revocation.