From c05de636d90288f8769801d810562e05e4165a77 Mon Sep 17 00:00:00 2001 From: andig Date: Sat, 28 Oct 2023 17:27:52 +0200 Subject: [PATCH] Porsche: update identity api (#10533) --- vehicle/porsche/identity.go | 69 ++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/vehicle/porsche/identity.go b/vehicle/porsche/identity.go index 47f24c1b8..8b037dece 100644 --- a/vehicle/porsche/identity.go +++ b/vehicle/porsche/identity.go @@ -2,14 +2,11 @@ package porsche import ( "context" - "encoding/json" - "errors" "fmt" "net/http" "net/http/cookiejar" "net/url" - "github.com/PuerkitoBio/goquery" "github.com/evcc-io/evcc/util" "github.com/evcc-io/evcc/util/oauth" "github.com/evcc-io/evcc/util/request" @@ -36,6 +33,8 @@ var ( } ) +// https://github.com/CJNE/pyporscheconnectapi + // Identity is the Porsche Identity client type Identity struct { *request.Helper @@ -77,65 +76,65 @@ func (v *Identity) login() (*oauth2.Token, error) { } defer resp.Body.Close() + // username u, err := url.Parse(resp.Header.Get("Location")) if err != nil { return nil, err } query := u.Query() - for _, p := range []string{"client_id", "code_challenge", "scope", "protocol"} { - query.Del(p) - } - for k, v := range map[string]string{ - "connection": "Username-Password-Authentication", - "tenant": "porsche-production", - "sec": "high", - } { - query.Set(k, v) - } - query.Set("client_id", OAuth2Config.ClientID) query.Set("username", v.user) - query.Set("password", v.password) + query.Set("js-available", "true") + query.Set("webauthn-available", "false") + query.Set("is-brave", "false") + query.Set("webauthn-platform-available", "false") + query.Set("action", "default") - uri = fmt.Sprintf("%s/usernamepassword/login", OAuthURI) - resp, err = v.PostForm(uri, query) + resp, err = v.PostForm(OAuthURI+u.String(), query) if err != nil { return nil, err } defer resp.Body.Close() - if resp.StatusCode != http.StatusOK { - var res struct { - Description string `json:"description"` - } - if err := json.NewDecoder(resp.Body).Decode(&res); err == nil && res.Description != "" { - return nil, errors.New(res.Description) - } + if resp.StatusCode != http.StatusFound { return nil, fmt.Errorf("unexpected status %d", resp.StatusCode) } - doc, err := goquery.NewDocumentFromReader(resp.Body) + // password + u, err = url.Parse(resp.Header.Get("Location")) if err != nil { return nil, err } - query = make(url.Values) - doc.Find("input[type=hidden]").Each(func(_ int, el *goquery.Selection) { - if name, ok := el.Attr("name"); ok { - val, _ := el.Attr("value") - query.Set(name, val) - } - }) + query = u.Query() + query.Set("username", v.user) + query.Set("password", v.password) + query.Set("action", "default") + + resp, err = v.PostForm(OAuthURI+u.String(), query) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusFound { + return nil, fmt.Errorf("unexpected status %d", resp.StatusCode) + } var param request.InterceptResult v.Client.CheckRedirect, param = request.InterceptRedirect("code", true) - uri = fmt.Sprintf("%s/login/callback", OAuthURI) - resp, err = v.PostForm(uri, query) + // resume + u, err = url.Parse(resp.Header.Get("Location")) if err != nil { return nil, err } - resp.Body.Close() + + resp, err = v.Get(OAuthURI + u.String()) + if err != nil { + return nil, err + } + defer resp.Body.Close() code, err := param() if err != nil {