diff --git a/control/controlclient/direct.go b/control/controlclient/direct.go index f5d1f0410..cd8e123d3 100644 --- a/control/controlclient/direct.go +++ b/control/controlclient/direct.go @@ -6,6 +6,7 @@ package controlclient import ( "bufio" "bytes" + "cmp" "context" "crypto/ed25519" "encoding/base64" @@ -586,10 +587,14 @@ func (c *Direct) doLogin(ctx context.Context, opt loginOpt) (mustRegen bool, new c.logf("RegisterReq: onode=%v node=%v fup=%v nks=%v", request.OldNodeKey.ShortString(), request.NodeKey.ShortString(), opt.URL != "", len(nodeKeySignature) > 0) - request.Auth.Oauth2Token = opt.Token - request.Auth.Provider = persist.Provider - request.Auth.LoginName = persist.UserProfile.LoginName - request.Auth.AuthKey = authKey + if opt.Token != nil || cmp.Or(persist.Provider, persist.UserProfile.LoginName, authKey) != "" { + request.Auth = &tailcfg.RegisterResponseAuth{ + Oauth2Token: opt.Token, + Provider: persist.Provider, + LoginName: persist.UserProfile.LoginName, + AuthKey: authKey, + } + } err = signRegisterRequest(&request, c.serverURL, c.serverLegacyKey, machinePrivKey.Public()) if err != nil { // If signing failed, clear all related fields diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index 4f9c25f3e..6121f90dc 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -1069,10 +1069,13 @@ func (st SignatureType) String() string { // in response to a RegisterRequest. type RegisterResponseAuth struct { _ structs.Incomparable + // One of Provider/LoginName, Oauth2Token, or AuthKey is set. - Provider, LoginName string - Oauth2Token *Oauth2Token - AuthKey string + + Provider string `json:",omitempty"` + LoginName string `json:",omitempty"` + Oauth2Token *Oauth2Token `json:",omitempty"` + AuthKey string `json:",omitempty"` } // RegisterRequest is sent by a client to register the key for a node. @@ -1093,7 +1096,7 @@ type RegisterRequest struct { NodeKey key.NodePublic OldNodeKey key.NodePublic NLKey key.NLPublic - Auth RegisterResponseAuth + Auth *RegisterResponseAuth `json:",omitempty"` // Expiry optionally specifies the requested key expiry. // The server policy may override. // As a special case, if Expiry is in the past and NodeKey is diff --git a/tailcfg/tailcfg_clone.go b/tailcfg/tailcfg_clone.go index 8013d4bcb..26ea72f70 100644 --- a/tailcfg/tailcfg_clone.go +++ b/tailcfg/tailcfg_clone.go @@ -335,7 +335,7 @@ func (src *RegisterRequest) Clone() *RegisterRequest { } dst := new(RegisterRequest) *dst = *src - dst.Auth = *src.Auth.Clone() + dst.Auth = src.Auth.Clone() dst.Hostinfo = src.Hostinfo.Clone() dst.NodeKeySignature = append(src.NodeKeySignature[:0:0], src.NodeKeySignature...) if dst.Timestamp != nil { @@ -353,7 +353,7 @@ var _RegisterRequestCloneNeedsRegeneration = RegisterRequest(struct { NodeKey key.NodePublic OldNodeKey key.NodePublic NLKey key.NLPublic - Auth RegisterResponseAuth + Auth *RegisterResponseAuth Expiry time.Time Followup string Hostinfo *Hostinfo diff --git a/tailcfg/tailcfg_view.go b/tailcfg/tailcfg_view.go index 56ed136f5..ea90bab6d 100644 --- a/tailcfg/tailcfg_view.go +++ b/tailcfg/tailcfg_view.go @@ -803,7 +803,7 @@ var _RegisterRequestViewNeedsRegeneration = RegisterRequest(struct { NodeKey key.NodePublic OldNodeKey key.NodePublic NLKey key.NLPublic - Auth RegisterResponseAuth + Auth *RegisterResponseAuth Expiry time.Time Followup string Hostinfo *Hostinfo diff --git a/tstest/integration/testcontrol/testcontrol.go b/tstest/integration/testcontrol/testcontrol.go index 817af53d7..74caaec64 100644 --- a/tstest/integration/testcontrol/testcontrol.go +++ b/tstest/integration/testcontrol/testcontrol.go @@ -585,7 +585,7 @@ func (s *Server) serveRegister(w http.ResponseWriter, r *http.Request, mkey key. j, _ := json.MarshalIndent(req, "", "\t") log.Printf("Got %T: %s", req, j) } - if s.RequireAuthKey != "" && req.Auth.AuthKey != s.RequireAuthKey { + if s.RequireAuthKey != "" && (req.Auth == nil || req.Auth.AuthKey != s.RequireAuthKey) { res := must.Get(s.encode(false, tailcfg.RegisterResponse{ Error: "invalid authkey", }))