VW: split token refresh and re-login into separate components (#2924)
This commit is contained in:
parent
82d26f513d
commit
c8a741a3e2
3 changed files with 57 additions and 18 deletions
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
46
vehicle/vw/tokenrefresher.go
Normal file
46
vehicle/vw/tokenrefresher.go
Normal 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
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue