client/web: skip check mode for non-tailscale.com control servers (#10413)

client/web: skip check mode for non-tailscale.com control servers

Only enforce check mode if the control server URL ends in
".tailscale.com".  This allows the web client to be used with headscale
(or other) control servers while we work with the project to add check
mode support (tracked in juanfont/headscale#1623).

Updates #10261

Co-authored-by: Sonia Appasamy <sonia@tailscale.com>
Signed-off-by: Sonia Appasamy <sonia@tailscale.com>
Signed-off-by: Will Norris <will@tailscale.com>
This commit is contained in:
Will Norris
2023-11-29 08:44:48 -08:00
committed by GitHub
parent ab0e25beaa
commit 26db9775f8
3 changed files with 87 additions and 27 deletions

View File

@@ -9,6 +9,8 @@ import (
"encoding/base64"
"errors"
"net/http"
"net/url"
"strings"
"time"
"tailscale.com/client/tailscale/apitype"
@@ -148,10 +150,6 @@ func (s *Server) getSession(r *http.Request) (*browserSession, *apitype.WhoIsRes
// and stores it back to the session cache. Creating of a new session includes
// generating a new auth URL from the control server.
func (s *Server) newSession(ctx context.Context, src *apitype.WhoIsResponse) (*browserSession, error) {
a, err := s.newAuthURL(ctx, src.Node.ID)
if err != nil {
return nil, err
}
sid, err := s.newSessionID()
if err != nil {
return nil, err
@@ -160,14 +158,44 @@ func (s *Server) newSession(ctx context.Context, src *apitype.WhoIsResponse) (*b
ID: sid,
SrcNode: src.Node.ID,
SrcUser: src.UserProfile.ID,
AuthID: a.ID,
AuthURL: a.URL,
Created: s.timeNow(),
}
if s.controlSupportsCheckMode(ctx) {
// control supports check mode, so get a new auth URL and return.
a, err := s.newAuthURL(ctx, src.Node.ID)
if err != nil {
return nil, err
}
session.AuthID = a.ID
session.AuthURL = a.URL
} else {
// control does not support check mode, so there is no additional auth we can do.
session.Authenticated = true
}
s.browserSessions.Store(sid, session)
return session, nil
}
// controlSupportsCheckMode returns whether the current control server supports web client check mode, to verify a user's identity.
// We assume that only "tailscale.com" control servers support check mode.
// This allows the web client to be used with non-standard control servers.
// If an error occurs getting the control URL, this method returns true to fail closed.
//
// TODO(juanfont/headscale#1623): adjust or remove this when headscale supports check mode.
func (s *Server) controlSupportsCheckMode(ctx context.Context) bool {
prefs, err := s.lc.GetPrefs(ctx)
if err != nil {
return true
}
controlURL, err := url.Parse(prefs.ControlURL)
if err != nil {
return true
}
return strings.HasSuffix(controlURL.Host, ".tailscale.com")
}
// awaitUserAuth blocks until the given session auth has been completed
// by the user on the control server, then updates the session cache upon
// completion. An error is returned if control auth failed for any reason.