VW/Seat/Skoda: re-login when refresh token expires (#1110)

This commit is contained in:
andig 2021-06-03 19:12:45 +02:00 • committed by GitHub
parent ae035be94d
commit adb67a9277
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 56 deletions

View file

@ -11,11 +11,13 @@ import (
type tokenRefresher struct {
*request.Helper
login func() (Token, error)
}
func Refresher(log *util.Logger) oauth.TokenRefresher {
func Refresher(log *util.Logger, login func() (Token, error)) oauth.TokenRefresher {
return &tokenRefresher{
Helper: request.NewHelper(log),
login: login,
}
}
@ -33,5 +35,9 @@ func (tr *tokenRefresher) RefreshToken(token *oauth2.Token) (*oauth2.Token, erro
err = tr.DoJSON(req, &res)
}
if se, ok := err.(request.StatusError); ok && se.HasStatus(http.StatusBadRequest, http.StatusUnauthorized, http.StatusForbidden) {
res, err = tr.login()
}
return (*oauth2.Token)(&res), err
}

View file

@ -13,11 +13,13 @@ import (
type tokenRefresher struct {
*request.Helper
login func() (oauth.Token, error)
}
func Refresher(log *util.Logger) oauth.TokenRefresher {
func Refresher(log *util.Logger, login func() (oauth.Token, error)) oauth.TokenRefresher {
return &tokenRefresher{
Helper: request.NewHelper(log),
login: login,
}
}
@ -38,5 +40,9 @@ func (tr *tokenRefresher) RefreshToken(token *oauth2.Token) (*oauth2.Token, erro
err = tr.DoJSON(req, &res)
}
if se, ok := err.(request.StatusError); ok && se.HasStatus(http.StatusBadRequest, http.StatusUnauthorized, http.StatusForbidden) {
res, err = tr.login()
}
return (*oauth2.Token)(&res), err
}

View file

@ -163,28 +163,35 @@ func (v *Identity) postTos(uri string) (*http.Response, error) {
// LoginVAG performs VAG login and finally exchanges id token for access and refresh tokens
func (v *Identity) LoginVAG(clientID string, query url.Values, user, password string) error {
uri := fmt.Sprintf("%s/oidc/v1/authorize?%s", IdentityURI, query.Encode())
q, err := v.login(uri, user, password)
if err == nil {
data := url.Values(map[string][]string{
"grant_type": {"id_token"},
"scope": {"sc2:fal"},
"token": {q.Get("id_token")},
})
var req *http.Request
req, err = request.New(http.MethodPost, OauthTokenURI, strings.NewReader(data.Encode()), map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
"X-Client-Id": clientID,
})
login := func() (oauth.Token, error) {
var token oauth.Token
uri := fmt.Sprintf("%s/oidc/v1/authorize?%s", IdentityURI, query.Encode())
q, err := v.login(uri, user, password)
if err == nil {
var token oauth.Token
if err = v.DoJSON(req, &token); err == nil {
v.TokenSource = oauth.RefreshTokenSource((*oauth2.Token)(&token), Refresher(v.log, clientID))
data := url.Values(map[string][]string{
"grant_type": {"id_token"},
"scope": {"sc2:fal"},
"token": {q.Get("id_token")},
})
var req *http.Request
req, err = request.New(http.MethodPost, OauthTokenURI, strings.NewReader(data.Encode()), map[string]string{
"Content-Type": "application/x-www-form-urlencoded",
"X-Client-Id": clientID,
})
if err == nil {
err = v.DoJSON(req, &token)
}
}
return token, err
}
token, err := login()
if err == nil {
v.TokenSource = oauth.RefreshTokenSource((*oauth2.Token)(&token), Refresher(v.log, login, clientID))
}
return err
@ -192,26 +199,33 @@ func (v *Identity) LoginVAG(clientID string, query url.Values, user, password st
// LoginSkoda performs Skoda login and finally exchanges code and id token for access and refresh tokens
func (v *Identity) LoginSkoda(query url.Values, user, password string) error {
uri := fmt.Sprintf("%s/oidc/v1/authorize?%s", IdentityURI, query.Encode())
q, err := v.login(uri, user, password)
if err == nil {
data := url.Values(map[string][]string{
"auth_code": {q.Get("code")},
"id_token": {q.Get("id_token")},
"brand": {"skoda"},
})
var req *http.Request
uri = fmt.Sprintf("%s/exchangeAuthCode", TokenServiceURI)
req, err = request.New(http.MethodPost, uri, strings.NewReader(data.Encode()), request.URLEncoding)
login := func() (oauth.Token, error) {
var token oauth.Token
uri := fmt.Sprintf("%s/oidc/v1/authorize?%s", IdentityURI, query.Encode())
q, err := v.login(uri, user, password)
if err == nil {
var token oauth.Token
if err = v.DoJSON(req, &token); err == nil {
v.TokenSource = oauth.RefreshTokenSource((*oauth2.Token)(&token), skoda.Refresher(v.log))
data := url.Values(map[string][]string{
"auth_code": {q.Get("code")},
"id_token": {q.Get("id_token")},
"brand": {"skoda"},
})
var req *http.Request
uri = fmt.Sprintf("%s/exchangeAuthCode", TokenServiceURI)
req, err = request.New(http.MethodPost, uri, strings.NewReader(data.Encode()), request.URLEncoding)
if err == nil {
err = v.DoJSON(req, &token)
}
}
return token, err
}
token, err := login()
if err == nil {
v.TokenSource = oauth.RefreshTokenSource((*oauth2.Token)(&token), skoda.Refresher(v.log, login))
}
return err
@ -219,29 +233,36 @@ func (v *Identity) LoginSkoda(query url.Values, user, password string) error {
// LoginID performs ID login and finally exchanges state and id token for access and refresh tokens
func (v *Identity) LoginID(query url.Values, user, password string) error {
uri := fmt.Sprintf("%s/authorize?%s", AppsURI, query.Encode())
q, err := v.login(uri, user, password)
if err == nil {
data := map[string]string{
"state": q.Get("state"),
"id_token": q.Get("id_token"),
"redirect_uri": "weconnect://authenticated",
"region": "emea",
"access_token": q.Get("access_token"),
"authorizationCode": q.Get("code"),
}
var req *http.Request
uri = fmt.Sprintf("%s/login/v1", AppsURI)
req, err = request.New(http.MethodPost, uri, request.MarshalJSON(data), request.JSONEncoding)
login := func() (id.Token, error) {
var token id.Token
uri := fmt.Sprintf("%s/authorize?%s", AppsURI, query.Encode())
q, err := v.login(uri, user, password)
if err == nil {
var token id.Token
if err = v.DoJSON(req, &token); err == nil {
v.TokenSource = oauth.RefreshTokenSource((*oauth2.Token)(&token), id.Refresher(v.log))
data := map[string]string{
"state": q.Get("state"),
"id_token": q.Get("id_token"),
"redirect_uri": "weconnect://authenticated",
"region": "emea",
"access_token": q.Get("access_token"),
"authorizationCode": q.Get("code"),
}
var req *http.Request
uri = fmt.Sprintf("%s/login/v1", AppsURI)
req, err = request.New(http.MethodPost, uri, request.MarshalJSON(data), request.JSONEncoding)
if err == nil {
err = v.DoJSON(req, &token)
}
}
return token, err
}
token, err := login()
if err == nil {
v.TokenSource = oauth.RefreshTokenSource((*oauth2.Token)(&token), id.Refresher(v.log, login))
}
return err

View file

@ -13,12 +13,14 @@ import (
type tokenRefresher struct {
*request.Helper
login func() (oauth.Token, error)
clientID string
}
func Refresher(log *util.Logger, clientID string) oauth.TokenRefresher {
func Refresher(log *util.Logger, login func() (oauth.Token, error), clientID string) oauth.TokenRefresher {
return &tokenRefresher{
Helper: request.NewHelper(log),
login: login,
clientID: clientID,
}
}
@ -41,5 +43,9 @@ func (tr *tokenRefresher) RefreshToken(token *oauth2.Token) (*oauth2.Token, erro
err = tr.DoJSON(req, &res)
}
if se, ok := err.(request.StatusError); ok && se.HasStatus(http.StatusBadRequest, http.StatusUnauthorized, http.StatusForbidden) {
res, err = tr.login()
}
return (*oauth2.Token)(&res), err
}