Cardata: display oauth user code (#25818)

This commit is contained in:
andig 2025-12-09 08:32:05 +01:00 • committed by GitHub
parent 157f9d207c
commit c5fc4b4f99
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 993 additions and 220 deletions

View file

@ -2,11 +2,13 @@ package auth
import (
"context"
"fmt"
"net/url"
"time"
"github.com/evcc-io/evcc/api"
"github.com/evcc-io/evcc/server/providerauth"
"github.com/evcc-io/evcc/util"
"golang.org/x/oauth2"
)
@ -15,22 +17,39 @@ func init() {
}
type demo struct {
token *oauth2.Token
token *oauth2.Token
region string
method string
}
var demoInstance *demo
func NewDemoFromConfig(_ context.Context, _ map[string]any) (oauth2.TokenSource, error) {
return NewDemo()
func NewDemoFromConfig(_ context.Context, other map[string]any) (oauth2.TokenSource, error) {
var cc struct {
Region string
Method string
}
if err := util.DecodeOther(other, &cc); err != nil {
return nil, err
}
return NewDemo(cc.Region, cc.Method)
}
func NewDemo() (oauth2.TokenSource, error) {
func NewDemo(region string, method string) (oauth2.TokenSource, error) {
// reuse instance (similar to oauth.go getInstance pattern)
if demoInstance != nil {
// update existing instance with new values
demoInstance.region = region
demoInstance.method = method
return demoInstance, nil
}
demoInstance = new(demo)
demoInstance = &demo{
region: region,
method: method,
}
if _, err := providerauth.Register("demo", demoInstance); err != nil {
return nil, err
@ -46,14 +65,32 @@ func (o *demo) Token() (*oauth2.Token, error) {
return o.token, nil
}
func (o *demo) Login(_ string) (string, error) {
// for demo, immediately authenticate without requiring external flow
func (o *demo) Login(_ string) (string, *oauth2.DeviceAuthResponse, error) {
// Simulate error for ERROR region
if o.region == "ERROR" {
return "", nil, fmt.Errorf("region not supported")
}
// For demo, immediately authenticate without requiring external flow
o.token = &oauth2.Token{
AccessToken: "demo-token",
Expiry: time.Now().Add(24 * time.Hour),
}
// TODO use network settings after https://github.com/evcc-io/evcc/pull/25141
return "http://localhost:7070/providerauth/callback", nil
uri := "http://localhost:7070/providerauth/callback"
if o.method == "device-code" {
// Device code flow: URI comes from DeviceAuthResponse
return "", &oauth2.DeviceAuthResponse{
UserCode: "12AB345",
VerificationURI: uri,
Expiry: time.Now().Add(10 * time.Minute),
}, nil
}
// Redirect flow: URI in first return value
return uri, nil, nil
}
func (o *demo) Logout() error {

View file

@ -220,7 +220,7 @@ func (o *OAuth) HandleCallback(params url.Values) error {
}
// Login implements api.AuthProvider.
func (o *OAuth) Login(state string) (string, error) {
func (o *OAuth) Login(state string) (string, *oauth2.DeviceAuthResponse, error) {
o.mu.Lock()
defer o.mu.Unlock()
@ -229,7 +229,7 @@ func (o *OAuth) Login(state string) (string, error) {
if o.deviceFlow {
da, err := o.oc.DeviceAuth(o.ctx, oauth2.S256ChallengeOption(o.cv))
if err != nil {
return "", err
return "", nil, err
}
go func() {
@ -248,14 +248,14 @@ func (o *OAuth) Login(state string) (string, error) {
o.updateToken(token)
}()
return da.VerificationURIComplete, nil
return "", da, nil
}
if o.oc.Endpoint.AuthURL == "" {
return "", errors.New("missing auth url")
return "", nil, errors.New("missing auth url")
}
return o.oc.AuthCodeURL(state, oauth2.S256ChallengeOption(o.cv)), nil
return o.oc.AuthCodeURL(state, oauth2.S256ChallengeOption(o.cv)), nil, nil
}
// Logout implements api.AuthProvider.