A guest login is a full account with a clock on it
Mitchell, on the read-only version built earlier today: scratch it. He hands these to people he trusts and revokes them otherwise, so a console with half its tabs missing solved a problem he doesn't have. So the allow-list, the middleware check and every "not for a guest" branch in the UI are gone. What is left is the part that was the point: a throwaway account that expires by itself, is checked on every request, swept once a minute, and can be ended in one tap. A guest now gets the whole console on every machine, terminal included. Said once, since it is his call and he has made it: that means a guest has a root-capable shell on every host, and can make an account or a token of its own that outlives the guest login. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
8a7167bf03
commit
179f342a2c
+5
-24
@@ -405,27 +405,17 @@ func (s *Server) setCookie(w http.ResponseWriter, r *http.Request, tok string, m
|
||||
})
|
||||
}
|
||||
|
||||
// signedIn reports whether a request carries a live browser session of a real account,
|
||||
// without the side effects of the auth middleware. A guest login is not one: this is what
|
||||
// lets a KVM's own assets through, and a KVM is a keyboard on a machine.
|
||||
// signedIn reports whether a request carries a live browser session, without the
|
||||
// side effects of the auth middleware.
|
||||
func (s *Server) signedIn(r *http.Request) bool {
|
||||
c, err := r.Cookie(cookieName)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
ses, ok := s.sessions.Lookup(c.Value, clientKey(r))
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
var u config.User
|
||||
var found bool
|
||||
s.cfg.View(func(cf *config.Config) { u, found = cf.User(ses.User) })
|
||||
return found && !u.Guest
|
||||
_, ok := s.sessions.Lookup(c.Value, clientKey(r))
|
||||
return ok
|
||||
}
|
||||
|
||||
// guestRefusal is what a guest login is told, wherever it reaches for something.
|
||||
const guestRefusal = "a guest login can only look around"
|
||||
|
||||
// cookieActor resolves the session cookie to who is calling. answered means the caller has
|
||||
// already been sent an error and the handler must not run: the account behind a live session
|
||||
// has gone away, or a guest login's time is up — so a console left open on a visitor's phone
|
||||
@@ -455,8 +445,7 @@ func (s *Server) cookieActor(w http.ResponseWriter, r *http.Request) (a actor, o
|
||||
return actor{User: ses.User, Session: ses.ID, token: c.Value, Guest: u.Guest, Expires: u.Expires}, true, false
|
||||
}
|
||||
|
||||
// auth accepts the browser session cookie or a bearer API token issued to a hub. A guest
|
||||
// login only reaches the handful of routes guestRoutes names (internal/api/guests.go).
|
||||
// auth accepts the browser session cookie or a bearer API token issued to a hub.
|
||||
func (s *Server) auth(next http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
a, ok, answered := s.cookieActor(w, r)
|
||||
@@ -464,10 +453,6 @@ func (s *Server) auth(next http.HandlerFunc) http.HandlerFunc {
|
||||
return
|
||||
}
|
||||
if ok {
|
||||
if a.Guest && !s.guestMay(r) {
|
||||
jsonErr(w, 403, guestRefusal)
|
||||
return
|
||||
}
|
||||
next(w, withActor(r, a))
|
||||
return
|
||||
}
|
||||
@@ -506,10 +491,6 @@ func (s *Server) sensorAuth(next http.HandlerFunc) http.HandlerFunc {
|
||||
if a, live, answered := s.cookieActor(w, r); answered {
|
||||
return
|
||||
} else if live {
|
||||
if a.Guest && !s.guestMay(r) {
|
||||
jsonErr(w, 403, guestRefusal)
|
||||
return
|
||||
}
|
||||
ok, trusted = true, true
|
||||
r = withActor(r, a)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user