Porsche: fix token refresh after refactoring (#2152)
Some checks failed
Default / Build (push) Failing after 1m35s
Default / Build UI (push) Failing after 14m12s
Release / call-build-workflow (push) Has been cancelled
Release / Publish Docker :release (push) Has been cancelled
Release / Publish Github & APT release (push) Has been cancelled

This commit is contained in:
andig 2021-12-29 22:13:24 +01:00 • committed by GitHub
parent da1ed07b9c
commit 07c559b4c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 17 deletions

View file

@ -40,9 +40,9 @@ func NewPorscheFromConfig(other map[string]interface{}) (api.Vehicle, error) {
}
log := util.NewLogger("porsche").Redact(cc.User, cc.Password, cc.VIN)
identity := porsche.NewIdentity(log)
identity := porsche.NewIdentity(log, cc.User, cc.Password)
err := identity.Login(cc.User, cc.Password)
err := identity.Login()
if err != nil {
return nil, fmt.Errorf("login failed: %w", err)
}

View file

@ -10,6 +10,7 @@ import (
"strings"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/oauth"
"github.com/evcc-io/evcc/util/request"
cv "github.com/nirasan/go-oauth-pkce-code-verifier"
"golang.org/x/net/publicsuffix"
@ -42,27 +43,41 @@ var (
// Identity is the Porsche Identity client
type Identity struct {
log *util.Logger
*request.Helper
user, password string
defaultToken, emobilityToken *oauth2.Token
DefaultSource, EmobilitySource oauth2.TokenSource
}
// NewIdentity creates Porsche identity
func NewIdentity(log *util.Logger) *Identity {
func NewIdentity(log *util.Logger, user, password string) *Identity {
v := &Identity{
log: log,
Helper: request.NewHelper(log),
Helper: request.NewHelper(log),
user: user,
password: password,
}
return v
}
func (v *Identity) Login(user, password string) error {
func (v *Identity) Login() error {
_, err := v.RefreshToken(nil)
if err == nil {
v.DefaultSource = oauth.RefreshTokenSource(v.defaultToken, v)
v.EmobilitySource = oauth.RefreshTokenSource(v.emobilityToken, &emobilityAdapter{v})
}
return err
}
// RefreshToken performs new login and creates default and emobility tokens
func (v *Identity) RefreshToken(_ *oauth2.Token) (*oauth2.Token, error) {
jar, err := cookiejar.New(&cookiejar.Options{
PublicSuffixList: publicsuffix.List,
})
if err != nil {
return err
return nil, err
}
// track cookies and follow all (>10) redirects
@ -79,13 +94,13 @@ func (v *Identity) Login(user, password string) error {
uri := fmt.Sprintf("%s/auth/api/v1/de/de_DE/public/login", OAuthURI)
resp, err := v.Get(uri)
if err != nil {
return err
return nil, err
}
resp.Body.Close()
query, err := url.ParseQuery(resp.Request.URL.RawQuery)
if err != nil {
return err
return nil, err
}
sec := query.Get("sec")
@ -98,33 +113,33 @@ func (v *Identity) Login(user, password string) error {
"resume": []string{resume},
"thirdPartyId": []string{thirdPartyID},
"state": []string{state},
"username": []string{user},
"password": []string{password},
"username": []string{v.user},
"password": []string{v.password},
"keeploggedin": []string{"false"},
}
req, err := request.New(http.MethodPost, uri, strings.NewReader(dataLoginAuth.Encode()), request.URLEncoding)
if err != nil {
return err
return nil, err
}
// process the auth so the session is authenticated
if resp, err = v.Client.Do(req); err != nil {
return err
return nil, err
}
resp.Body.Close()
// get the token for the generic API
token, err := v.fetchToken(OAuth2Config)
if err == nil {
v.DefaultSource = OAuth2Config.TokenSource(context.Background(), token)
v.defaultToken = token
if token, err = v.fetchToken(EmobilityOAuth2Config); err == nil {
v.EmobilitySource = EmobilityOAuth2Config.TokenSource(context.Background(), token)
v.emobilityToken = token
}
}
return err
return v.defaultToken, err
}
func (v *Identity) fetchToken(oc *oauth2.Config) (*oauth2.Token, error) {
@ -168,3 +183,15 @@ func (v *Identity) fetchToken(oc *oauth2.Config) (*oauth2.Token, error) {
return token, err
}
type emobilityAdapter struct {
tr *Identity
}
func (v *emobilityAdapter) RefreshToken(_ *oauth2.Token) (*oauth2.Token, error) {
token, err := v.tr.RefreshToken(nil)
if err == nil {
token = v.tr.emobilityToken
}
return token, err
}