diff --git a/vehicle/bluelink.go b/vehicle/bluelink.go index 0b4850fe2..2883e4c92 100644 --- a/vehicle/bluelink.go +++ b/vehicle/bluelink.go @@ -30,8 +30,9 @@ func NewHyundaiFromConfig(other map[string]interface{}) (api.Vehicle, error) { CCSPServiceID: "6d477c38-3ca4-4cf3-9557-2a1929a94654", CCSPApplicationID: bluelink.HyundaiAppID, AuthClientID: "64621b96-0f0d-11ec-82a8-0242ac130003", - BrandAuthUrl: "https://eu-account.hyundai.com/auth/realms/euhyundaiidm/protocol/openid-connect/auth?client_id=%s&scope=openid%%20profile%%20email%%20phone&response_type=code&hkid_session_reset=true&redirect_uri=%s/api/v1/user/integration/redirect/login&ui_locales=%s&state=%s:%s", + BrandAuthUrl: "https://eu-account.hyundai.com/auth/realms/euhyundaiidm/protocol/openid-connect/auth?client_id=%s&scope=openid+profile+email+phone&response_type=code&hkid_session_reset=true&redirect_uri=%s/api/v1/user/integration/redirect/login&ui_locales=%s&state=%s:%s", PushType: "GCM", + Cfb: "RFtoRq/vDXJmRndoZaZQyfOot7OrIqGVFj96iY2WL3yyH5Z/pUvlUhqmCxD2t+D65SQ=", } return newBluelinkFromConfig("hyundai", other, settings) @@ -45,8 +46,9 @@ func NewKiaFromConfig(other map[string]interface{}) (api.Vehicle, error) { CCSPServiceID: "fdc85c00-0a2f-4c64-bcb4-2cfb1500730a", CCSPApplicationID: bluelink.KiaAppID, AuthClientID: "572e0304-5f8d-4b4c-9dd5-41aa84eed160", - BrandAuthUrl: "https://eu-account.kia.com/auth/realms/eukiaidm/protocol/openid-connect/auth?client_id=%s&scope=openid%%20profile%%20email%%20phone&response_type=code&hkid_session_reset=true&redirect_uri=%s/api/v1/user/integration/redirect/login&ui_locales=%s&state=%s:%s", + BrandAuthUrl: "https://eu-account.kia.com/auth/realms/eukiaidm/protocol/openid-connect/auth?client_id=%s&scope=openid+profile+email+phone&response_type=code&hkid_session_reset=true&redirect_uri=%s/api/v1/user/integration/redirect/login&ui_locales=%s&state=%s:%s", PushType: "APNS", + Cfb: "wLTVxwidmH8CfJYBWSnHD6E0huk0ozdiuygB4hLkM5XCgzAL1Dk5sE36d/bx5PFMbZs=", } return newBluelinkFromConfig("kia", other, settings) @@ -78,7 +80,7 @@ func newBluelinkFromConfig(brand string, other map[string]interface{}, settings return nil, err } - api := bluelink.NewAPI(log, settings.URI, identity) + api := bluelink.NewAPI(log, settings.URI, identity.Request) vehicle, err := ensureVehicleEx( cc.VIN, api.Vehicles, diff --git a/vehicle/bluelink/api.go b/vehicle/bluelink/api.go index 663c21e95..5d9b102f3 100644 --- a/vehicle/bluelink/api.go +++ b/vehicle/bluelink/api.go @@ -31,12 +31,8 @@ type API struct { baseURI string } -type Requester interface { - Request(*http.Request) error -} - // New creates a new BlueLink API -func NewAPI(log *util.Logger, baseURI string, identity Requester) *API { +func NewAPI(log *util.Logger, baseURI string, decorator func(*http.Request) error) *API { v := &API{ Helper: request.NewHelper(log), baseURI: strings.TrimSuffix(baseURI, "/api/v1/spa") + "/api/v1/spa", @@ -46,7 +42,7 @@ func NewAPI(log *util.Logger, baseURI string, identity Requester) *API { v.Client.Timeout = 120 * time.Second v.Client.Transport = &transport.Decorator{ - Decorator: identity.Request, + Decorator: decorator, Base: v.Client.Transport, } diff --git a/vehicle/bluelink/identity.go b/vehicle/bluelink/identity.go index b3653bfea..b8c976c70 100644 --- a/vehicle/bluelink/identity.go +++ b/vehicle/bluelink/identity.go @@ -1,12 +1,15 @@ package bluelink import ( + "encoding/base64" "errors" "fmt" "net/http" "net/http/cookiejar" "net/url" + "strconv" "strings" + "time" "github.com/PuerkitoBio/goquery" "github.com/evcc-io/evcc/api" @@ -37,6 +40,7 @@ type Config struct { CCSPServiceID string CCSPApplicationID string PushType string + Cfb string } // Identity implements the Kia/Hyundai bluelink identity. @@ -61,7 +65,8 @@ func NewIdentity(log *util.Logger, config Config) *Identity { } func (v *Identity) getDeviceID() (string, error) { - stamp, err := Stamps[v.config.CCSPApplicationID].Get() + // stamp, err := Stamps[v.config.CCSPApplicationID].Get() + stamp, err := v.stamp() if err != nil { return "", err } @@ -359,7 +364,8 @@ func (v *Identity) Login(user, password, language string) (err error) { // Request decorates requests with authorization headers func (v *Identity) Request(req *http.Request) error { - stamp, err := Stamps[v.config.CCSPApplicationID].Get() + // stamp, err := Stamps[v.config.CCSPApplicationID].Get() + stamp, err := v.stamp() if err != nil { return err } @@ -382,3 +388,24 @@ func (v *Identity) Request(req *http.Request) error { return nil } + +// stamp creates a stamp locally according to https://github.com/Hyundai-Kia-Connect/hyundai_kia_connect_api/pull/371 +func (v *Identity) stamp() (string, error) { + cfb, err := base64.StdEncoding.DecodeString(v.config.Cfb) + if err != nil { + return "", err + } + + raw := v.config.CCSPApplicationID + ":" + strconv.FormatInt(time.Now().UnixMilli(), 10) + + if len(cfb) != len(raw) { + return "", fmt.Errorf("cfb and raw length not equal") + } + + enc := make([]byte, 0, 50) + for i := 0; i < len(cfb); i++ { + enc = append(enc, cfb[i]^raw[i]) + } + + return base64.StdEncoding.EncodeToString(enc), nil +}