Skip to content

Commit

Permalink
Add custom header to specify fleetapi base url
Browse files Browse the repository at this point in the history
  • Loading branch information
tnsetting2023 committed Sep 23, 2024
1 parent e8634aa commit f18c79c
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 10 deletions.
2 changes: 1 addition & 1 deletion examples/unlock/unlock.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ func main() {

// This example program sends commands over the Internet, which requires a Tesla account login
// token. The protocol can also work over BLE; see other programs in the example directory.
acct, err := account.New(string(oauthToken), userAgent)
acct, err := account.New(string(oauthToken), userAgent, "")
if err != nil {
logger.Printf("Authentication error: %s", err)
return
Expand Down
13 changes: 9 additions & 4 deletions pkg/account/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func (p *oauthPayload) domain() string {

// New returns an [Account] that can be used to fetch a [vehicle.Vehicle].
// Optional userAgent can be passed in - otherwise it will be generated from code
func New(oauthToken, userAgent string) (*Account, error) {
func New(oauthToken, userAgent, fleetapiHost string) (*Account, error) {
parts := strings.Split(oauthToken, ".")
if len(parts) != 3 {
return nil, fmt.Errorf("client provided malformed OAuth token")
Expand All @@ -128,9 +128,14 @@ func New(oauthToken, userAgent string) (*Account, error) {
return nil, fmt.Errorf("client provided malformed OAuth token: %s", err)
}

domain := payload.domain()
if domain == "" {
return nil, fmt.Errorf("client provided OAuth token with invalid audiences")
domain := ""
if fleetapiHost != "" {
domain, _ = strings.CutPrefix(fleetapiHost, "https://")
} else {
domain = payload.domain()
if domain == "" {
return nil, fmt.Errorf("client provided OAuth token with invalid audiences")
}
}
return &Account{
UserAgent: buildUserAgent(userAgent),
Expand Down
27 changes: 24 additions & 3 deletions pkg/account/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestNewAccount(t *testing.T) {

for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
acct, err := New(test.jwt, "")
acct, err := New(test.jwt, "", "")
if (err != nil) != test.shouldError {
t.Errorf("Unexpected result: err = %v, shouldError = %v", err, test.shouldError)
}
Expand All @@ -50,7 +50,7 @@ func TestDomainDefault(t *testing.T) {
Audiences: []string{"https://auth.tesla.com/nts"},
}

acct, err := New(makeTestJWT(payload), "")
acct, err := New(makeTestJWT(payload), "", "")
if err != nil {
t.Fatalf("Returned error on valid JWT: %s", err)
}
Expand All @@ -70,7 +70,7 @@ func TestDomainExtraction(t *testing.T) {
OUCode: "EU",
}

acct, err := New(makeTestJWT(payload), "")
acct, err := New(makeTestJWT(payload), "", "")
if err != nil {
t.Fatalf("Returned error on valid JWT: %s", err)
}
Expand All @@ -80,6 +80,27 @@ func TestDomainExtraction(t *testing.T) {
}
}

// TestDomainExtraction tests the extraction of the correct domain based on OUCode.
func TestTargetHost(t *testing.T) {
payload := &oauthPayload{
Audiences: []string{
"https://auth.tesla.com/nts",
"https://fleet-api.prd.na.vn.cloud.tesla.com",
"https://fleet-api.prd.eu.vn.cloud.tesla.com",
},
OUCode: "EU",
}

acct, err := New(makeTestJWT(payload), "", "https://fleet-api.prd.na.vn.cloud.tesla.com")
if err != nil {
t.Fatalf("Returned error on valid JWT: %s", err)
}
expectedHost := "fleet-api.prd.na.vn.cloud.tesla.com"
if acct == nil || acct.Host != expectedHost {
t.Errorf("acct = %+v, expected Host = %s", acct, expectedHost)
}
}

// makeTestJWT creates a JWT string with the given payload.
func makeTestJWT(payload *oauthPayload) string {
jwtBody, _ := json.Marshal(payload)
Expand Down
2 changes: 1 addition & 1 deletion pkg/cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ func (c *Config) Account() (*account.Account, error) {
if err != nil {
return nil, err
}
return account.New(token, "")
return account.New(token, "", "")
}

// SavePrivateKey writes skey to the system keyring or file, depending on what options are
Expand Down
4 changes: 3 additions & 1 deletion pkg/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ func getAccount(req *http.Request) (*account.Account, error) {
if !ok {
return nil, fmt.Errorf("client did not provide an OAuth token")
}
return account.New(token, proxyProtocolVersion)
fleetapiHost := req.Header.Get("Fleetapi-Host")

return account.New(token, proxyProtocolVersion, fleetapiHost)
}

// Proxy exposes an HTTP API for sending vehicle commands.
Expand Down

0 comments on commit f18c79c

Please sign in to comment.