VW: split token refresh and re-login into separate components (#2924)

This commit is contained in:
andig 2022-03-22 11:35:58 +01:00 • committed by GitHub
parent 82d26f513d
commit c8a741a3e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 57 additions and 18 deletions

View file

@ -28,18 +28,20 @@ const (
type Identity struct {
*request.Helper
idtp *IDTokenProvider
clientID string
oauth2.TokenSource
idtp *IDTokenProvider
clientID string
refresher oauth.TokenRefresher
}
func NewIdentity(log *util.Logger, clientID string, query url.Values, user, password string) *Identity {
uri := fmt.Sprintf("%s/oidc/v1/authorize?%s", IdentityURI, query.Encode())
return &Identity{
Helper: request.NewHelper(log),
idtp: NewIDTokenProvider(log, uri, user, password),
clientID: clientID,
Helper: request.NewHelper(log),
clientID: clientID,
idtp: NewIDTokenProvider(log, uri, user, password),
refresher: NewTokenRefresher(log, clientID),
}
}
@ -92,22 +94,13 @@ func (v *Identity) login() (Token, error) {
// RefreshToken implements oauth.TokenRefresher
func (v *Identity) RefreshToken(token *oauth2.Token) (*oauth2.Token, error) {
data := url.Values(map[string][]string{
"grant_type": {"refresh_token"},
"refresh_token": {token.RefreshToken},
"scope": {"sc2:fal"},
})
req, err := request.New(http.MethodPost, OauthTokenURI, strings.NewReader(data.Encode()), map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
"X-Client-Id": v.clientID,
})
var res Token
token, err := v.refresher.RefreshToken(token)
if err == nil {
err = v.DoJSON(req, &res)
return token, nil
}
// re-login
var res Token
if se, ok := err.(request.StatusError); ok && se.HasStatus(http.StatusBadRequest, http.StatusUnauthorized, http.StatusForbidden) {
res, err = v.login()
}

View file

@ -0,0 +1,46 @@
package vw
import (
"net/http"
"net/url"
"strings"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/request"
"golang.org/x/oauth2"
)
// TokenRefresher performs the MBBOauth token refresh without re-login
type TokenRefresher struct {
*request.Helper
clientID string
}
// NewTokenRefresher creates an MBBOauth token refresher
func NewTokenRefresher(log *util.Logger, clientID string) *TokenRefresher {
return &TokenRefresher{
Helper: request.NewHelper(log),
clientID: clientID,
}
}
// RefreshToken implements oauth.TokenRefresher
func (v *TokenRefresher) RefreshToken(token *oauth2.Token) (*oauth2.Token, error) {
data := url.Values(map[string][]string{
"grant_type": {"refresh_token"},
"refresh_token": {token.RefreshToken},
"scope": {"sc2:fal"},
})
req, err := request.New(http.MethodPost, OauthTokenURI, strings.NewReader(data.Encode()), map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
"X-Client-Id": v.clientID,
})
var res Token
if err == nil {
err = v.DoJSON(req, &res)
}
return &res.Token, err
}