From 21682e7619d7b4a1784c7841f82d88f6c97441fa Mon Sep 17 00:00:00 2001 From: andig Date: Thu, 9 Oct 2025 09:36:10 +0200 Subject: [PATCH] Refactor provider authorization (#24264) --- plugin/auth/oauth.go | 25 ++++++++++++++++----- plugin/auth/viessmann.go | 3 ++- templates/definition/charger/viessmann.yaml | 3 +++ vehicle/cardata.go | 2 +- vehicle/volvo-connected.go | 2 +- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/plugin/auth/oauth.go b/plugin/auth/oauth.go index 43cebb22b..962b81798 100644 --- a/plugin/auth/oauth.go +++ b/plugin/auth/oauth.go @@ -24,6 +24,8 @@ type OAuth struct { log *util.Logger oc *oauth2.Config token *oauth2.Token + name string + devices []string subject string cv string ctx context.Context @@ -73,7 +75,7 @@ func init() { func NewOauthFromConfig(ctx context.Context, other map[string]any) (oauth2.TokenSource, error) { var cc struct { - Name string + Name, Device string oauth2.Config `mapstructure:",squash"` } @@ -81,12 +83,12 @@ func NewOauthFromConfig(ctx context.Context, other map[string]any) (oauth2.Token return nil, err } - return NewOauth(ctx, cc.Name, &cc.Config) + return NewOauth(ctx, cc.Name, cc.Device, &cc.Config) } var _ api.AuthProvider = (*OAuth)(nil) -func NewOauth(ctx context.Context, name string, oc *oauth2.Config, opts ...oauthOption) (oauth2.TokenSource, error) { +func NewOauth(ctx context.Context, name, device string, oc *oauth2.Config, opts ...oauthOption) (oauth2.TokenSource, error) { if name == "" { return nil, errors.New("instance name must not be empty") } @@ -97,10 +99,13 @@ func NewOauth(ctx context.Context, name string, oc *oauth2.Config, opts ...oauth // hash oauth2 config h := sha256.Sum256(fmt.Append(nil, oc)) hash := hex.EncodeToString(h[:])[:8] - subject := name + " (" + hash + ")" + subject := oc.ClientID + "-" + hash // reuse instance if instance := getInstance(subject); instance != nil { + if device != "" { + instance.devices = append(instance.devices, device) + } return instance, nil } @@ -111,10 +116,15 @@ func NewOauth(ctx context.Context, name string, oc *oauth2.Config, opts ...oauth } o := &OAuth{ - subject: subject, oc: oc, log: log, ctx: ctx, + subject: subject, + name: name, + } + + if device != "" { + o.devices = append(o.devices, device) } for _, opt := range opts { @@ -287,7 +297,10 @@ func (o *OAuth) Logout() error { // DisplayName implements api.AuthProvider. func (o *OAuth) DisplayName() string { - return o.subject + if len(o.devices) > 0 { + return fmt.Sprintf("%s (%s)", o.name, strings.Join(o.devices, ", ")) + } + return o.name } // Authenticated implements api.AuthProvider. diff --git a/plugin/auth/viessmann.go b/plugin/auth/viessmann.go index a900c4911..5de4143df 100644 --- a/plugin/auth/viessmann.go +++ b/plugin/auth/viessmann.go @@ -34,6 +34,7 @@ func init() { func NewViessmannFromConfig(ctx context.Context, other map[string]any) (oauth2.TokenSource, error) { var cc struct { ClientID string + Gateway string } if err := util.DecodeOther(other, &cc); err != nil { @@ -43,5 +44,5 @@ func NewViessmannFromConfig(ctx context.Context, other map[string]any) (oauth2.T log := util.NewLogger("viessmann").Redact(cc.ClientID) ctx = context.WithValue(ctx, oauth2.HTTPClient, request.NewClient(log)) - return NewOauth(ctx, "Viessmann", oauth2Config(cc.ClientID)) + return NewOauth(ctx, "Viessmann", cc.Gateway, oauth2Config(cc.ClientID)) } diff --git a/templates/definition/charger/viessmann.yaml b/templates/definition/charger/viessmann.yaml index 099058425..e8c6e78ea 100644 --- a/templates/definition/charger/viessmann.yaml +++ b/templates/definition/charger/viessmann.yaml @@ -150,6 +150,7 @@ render: | auth: source: viessmann clientid: {{ .clientid }} + gateway: {{ .gateway_serial }} jq: '.data.properties.active.value | if . == false then 2 elif . == true then 3 else . end' # false -> oneTimeCharge is disabled -> normal mode -> 2 # true -> oneTimeCharge is enabled -> boost mode -> 3 @@ -170,6 +171,7 @@ render: | auth: source: viessmann clientid: {{ .clientid }} + gateway: {{ .gateway_serial }} body: > { } - case: 3 # boost @@ -182,6 +184,7 @@ render: | auth: source: viessmann clientid: {{ .clientid }} + gateway: {{ .gateway_serial }} body: > { } - case: 1 # dimm diff --git a/vehicle/cardata.go b/vehicle/cardata.go index 480dfe018..766f7ec5d 100644 --- a/vehicle/cardata.go +++ b/vehicle/cardata.go @@ -54,7 +54,7 @@ func NewCardataFromConfig(ctx context.Context, other map[string]interface{}) (ap log := util.NewLogger("cardata").Redact(cc.ClientID, cc.VIN) - ts, err := auth.NewOauth(context.Background(), "BMW/Mini", &oc, + ts, err := auth.NewOauth(context.Background(), "BMW/Mini", cc.embed.GetTitle(), &oc, auth.WithOauthDeviceFlowOption(), auth.WithTokenRetrieverOption(func(data string, res *oauth2.Token) error { var token cardata.Token diff --git a/vehicle/volvo-connected.go b/vehicle/volvo-connected.go index f49cf984c..955a030b1 100644 --- a/vehicle/volvo-connected.go +++ b/vehicle/volvo-connected.go @@ -53,7 +53,7 @@ func NewVolvoConnectedFromConfig(ctx context.Context, other map[string]interface log := util.NewLogger("volvo-connected").Redact(cc.VIN, cc.Credentials.ID, cc.Credentials.Secret, cc.VccApiKey) oc := connected.Oauth2Config(cc.Credentials.ID, cc.Credentials.Secret, cc.RedirectUri) - ts, err := auth.NewOauth(ctx, "Volvo", oc) + ts, err := auth.NewOauth(ctx, "Volvo", cc.embed.GetTitle(), oc) if err != nil { return nil, err }