package web import ( "encoding/json" "net/http" ) // SSODetector maps an incoming HTTP request from an already-authenticated // portal session into a YAMA web identity (username + role). Implementations // are portal-specific: each one knows how to recognize its portal's session // credential (a cookie, a header, a JWT, ...) and translate the caller to // YAMA's two roles, "admin" and "viewer". // // Detect returns ok=false when the request carries no usable credential, or // the credential is invalid/expired; the caller then falls back to the // built-in login form. username is used only for audit/logging. Whether a // detected identity is actually bridged into a session is handleSSO's policy: // currently only "admin" is bridged, everyone else falls back to the login form. type SSODetector interface { Detect(r *http.Request) (username, role string, ok bool) } // handleSSO bridges a detected portal identity into a YAMA session token. // Only administrators are bridged: a valid portal session for any other role // (viewer, unknown) still returns 401 and the front-end falls back to the // built-in login form, so a low-privileged portal account cannot walk straight // into the remote-desktop console. When no detector is configured, or the // request is not recognized, it also returns 401. func (s *Server) handleSSO(w http.ResponseWriter, r *http.Request) { if s.sso == nil { s.unauthorized(w) return } username, role, ok := s.sso.Detect(r) if !ok { s.unauthorized(w) return } // Only the "admin" role may skip the login form via SSO. Every other role // (viewer, unknown) must authenticate against YAMA's own login, even with // a valid portal session. if role != "admin" { s.unauthorized(w) return } token, err := s.auth.IssueToken(username, role) if err != nil { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) _, _ = w.Write([]byte(`{"error":"internal error"}`)) return } s.log.Info("sso: user=%s role=%s", username, role) w.Header().Set("Content-Type", "application/json; charset=utf-8") w.Header().Set("Cache-Control", "no-store") _ = json.NewEncoder(w).Encode(map[string]string{ "token": token, "role": role, "username": username, }) }