Cardata: fix id token not refreshed (#24196)
Some checks failed
Release / call-build-workflow (push) Has been cancelled
Release / Publish Docker :release (push) Has been cancelled
Release / Github & APT (push) Has been cancelled
Release / Demo (push) Has been cancelled
Release / Hassio Addon (push) Has been cancelled

This commit is contained in:
andig 2025-10-07 13:15:13 +02:00 • committed by GitHub
parent 34968a8c3b
commit 27b2edfb39
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -15,16 +15,15 @@ import (
"github.com/evcc-io/evcc/server/db/settings"
"github.com/evcc-io/evcc/server/providerauth"
"github.com/evcc-io/evcc/util"
"github.com/evcc-io/evcc/util/oauth"
"github.com/evcc-io/evcc/util/request"
"golang.org/x/oauth2"
)
type OAuth struct {
oauth2.TokenSource
mu sync.Mutex
log *util.Logger
oc *oauth2.Config
token *oauth2.Token
subject string
cv string
ctx context.Context
@ -85,10 +84,7 @@ func NewOauthFromConfig(ctx context.Context, other map[string]any) (oauth2.Token
return NewOauth(ctx, cc.Name, &cc.Config)
}
var (
_ oauth.TokenRefresher = (*OAuth)(nil)
_ api.AuthProvider = (*OAuth)(nil)
)
var _ api.AuthProvider = (*OAuth)(nil)
func NewOauth(ctx context.Context, name string, oc *oauth2.Config, opts ...oauthOption) (oauth2.TokenSource, error) {
if name == "" {
@ -146,7 +142,9 @@ func NewOauth(ctx context.Context, name string, oc *oauth2.Config, opts ...oauth
}
}
o.TokenSource = oauth.RefreshTokenSource(&token, o)
if token.RefreshToken != "" {
o.token = &token
}
// register auth redirect
onlineC, err := providerauth.Register(subject, o)
@ -163,17 +161,22 @@ func NewOauth(ctx context.Context, name string, oc *oauth2.Config, opts ...oauth
return o, nil
}
// RefreshToken implements oauth.TokenRefresher.
func (o *OAuth) RefreshToken(token *oauth2.Token) (*oauth2.Token, error) {
if token.RefreshToken == "" {
// Token
func (o *OAuth) Token() (*oauth2.Token, error) {
o.mu.Lock()
defer o.mu.Unlock()
if o.token == nil {
return nil, api.ErrMissingToken
}
o.log.DEBUG.Printf("refreshing token for %s", o.subject)
if o.token.Valid() {
return o.token, nil
}
// refresh token source
token, err := o.oc.TokenSource(o.ctx, token).Token()
token, err := o.oc.TokenSource(o.ctx, o.token).Token()
if err != nil {
// force logout
if strings.Contains(err.Error(), "invalid_grant") && settings.Exists(o.subject) {
o.onlineC <- false
settings.Delete(o.subject)
@ -182,15 +185,13 @@ func (o *OAuth) RefreshToken(token *oauth2.Token) (*oauth2.Token, error) {
return nil, err
}
err = o.updateToken(token)
o.updateToken(token)
o.onlineC <- token.Valid()
return token, err
return token, nil
}
// updateToken must only be called when lock is held
func (o *OAuth) updateToken(token *oauth2.Token) error {
func (o *OAuth) updateToken(token *oauth2.Token) {
var store any = token
// tokenStorer allows persisting the token together with it's extra properties
@ -198,17 +199,11 @@ func (o *OAuth) updateToken(token *oauth2.Token) error {
store = o.tokenStorer(token)
}
return settings.SetJson(o.subject, store)
}
// updateTokenSource must only be called when lock is held
func (o *OAuth) updateTokenSource(token *oauth2.Token) {
if err := o.updateToken(token); err != nil {
if err := settings.SetJson(o.subject, store); err != nil {
o.log.ERROR.Printf("error saving token: %v", err)
return
}
o.TokenSource = oauth.RefreshTokenSource(token, o)
o.token = token
o.onlineC <- token.Valid()
}
@ -225,7 +220,7 @@ func (o *OAuth) HandleCallback(params url.Values) error {
return err
}
o.updateTokenSource(token)
o.updateToken(token)
return nil
}
@ -256,7 +251,7 @@ func (o *OAuth) Login(state string) (string, error) {
o.mu.Lock()
defer o.mu.Unlock()
o.updateTokenSource(token)
o.updateToken(token)
}()
return da.VerificationURIComplete, nil
@ -282,7 +277,7 @@ func (o *OAuth) Logout() error {
o.mu.Lock()
defer o.mu.Unlock()
o.TokenSource = oauth.RefreshTokenSource(nil, o)
o.token = nil
o.onlineC <- false
@ -296,9 +291,6 @@ func (o *OAuth) DisplayName() string {
// Authenticated implements api.AuthProvider.
func (o *OAuth) Authenticated() bool {
o.mu.Lock()
defer o.mu.Unlock()
token, err := o.Token()
return err == nil && token.Valid()
}