Porsche: update identity api (#10533)

This commit is contained in:
andig 2023-10-28 17:27:52 +02:00 • committed by GitHub
parent f318ed618a
commit c05de636d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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 {