Check for single user token

This commit is contained in:
Chen-I Lim 2021-02-09 12:27:34 -08:00
parent c62e587c85
commit 0fe96ad7ed
7 changed files with 54 additions and 35 deletions

View File

@ -9,6 +9,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
private var serverProcess: Process?
var serverPort = 8088
var sessionToken: String = ""
func applicationDidFinishLaunching(_ aNotification: Notification) {
copyResources()
@ -69,6 +70,8 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
private func startServer() {
sessionToken = UUID().uuidString
let cwdUrl = webFolder()
let executablePath = Bundle.main.path(forResource: "resources/bin/focalboard-server", ofType: "")
@ -76,7 +79,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
NSLog("pid: \(pid)")
let serverProcess = Process()
serverProcess.currentDirectoryPath = cwdUrl.path
serverProcess.arguments = ["-monitorpid", "\(pid)", "-port", "\(serverPort)", "--single-user"]
serverProcess.arguments = ["-monitorpid", "\(pid)", "-port", "\(serverPort)", "-single-user", sessionToken]
serverProcess.launchPath = executablePath
serverProcess.launch()
self.serverProcess = serverProcess

View File

@ -19,7 +19,6 @@ class ViewController:
webView.uiDelegate = self
clearWebViewCache()
loadHomepage()
// Do any additional setup after loading the view.
NotificationCenter.default.addObserver(self, selector: #selector(onServerStarted), name: AppDelegate.serverStartedNotification, object: nil)
@ -40,10 +39,22 @@ class ViewController:
@objc func onServerStarted() {
NSLog("onServerStarted")
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.updateSessionToken()
self.loadHomepage()
}
}
private func updateSessionToken() {
let appDelegate = NSApplication.shared.delegate as! AppDelegate
let script = WKUserScript(
source: "localStorage.setItem('sessionId', '\(appDelegate.sessionToken)');",
injectionTime: .atDocumentStart,
forMainFrameOnly: true
)
webView.configuration.userContentController.removeAllUserScripts()
webView.configuration.userContentController.addUserScript(script)
}
private func loadHomepage() {
let appDelegate = NSApplication.shared.delegate as! AppDelegate
let port = appDelegate.serverPort

View File

@ -27,12 +27,15 @@ const (
// REST APIs
type API struct {
appBuilder func() *app.App
singleUser bool
appBuilder func() *app.App
singleUserToken string
}
func NewAPI(appBuilder func() *app.App, singleUser bool) *API {
return &API{appBuilder: appBuilder, singleUser: singleUser}
func NewAPI(appBuilder func() *app.App, singleUserToken string) *API {
return &API{
appBuilder: appBuilder,
singleUserToken: singleUserToken,
}
}
func (a *API) app() *app.App {

View File

@ -198,12 +198,19 @@ func (a *API) sessionRequired(handler func(w http.ResponseWriter, r *http.Reques
func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request), required bool) func(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
log.Printf(`Single User: %v`, a.singleUser)
if a.singleUser {
token, _ := auth.ParseAuthTokenFromRequest(r)
log.Printf(`Single User: %v`, len(a.singleUserToken) > 0)
if len(a.singleUserToken) > 0 {
if required && (token != a.singleUserToken) {
errorResponse(w, http.StatusUnauthorized, nil, nil)
return
}
now := time.Now().Unix()
session := &model.Session{
ID: "single-user",
Token: "single-user",
Token: token,
UserID: "single-user",
CreateAt: now,
UpdateAt: now,
@ -213,11 +220,10 @@ func (a *API) attachSession(handler func(w http.ResponseWriter, r *http.Request)
return
}
token, _ := auth.ParseAuthTokenFromRequest(r)
session, err := a.app().GetSession(token)
if err != nil {
if required {
errorResponse(w, http.StatusUnauthorized, map[string]string{"error": err.Error()}, err)
errorResponse(w, http.StatusUnauthorized, nil, err)
return
}

View File

@ -63,12 +63,12 @@ func main() {
// Command line args
pMonitorPid := flag.Int("monitorpid", -1, "a process ID")
pPort := flag.Int("port", config.Port, "the port number")
pSingleUser := flag.Bool("single-user", false, "single user mode")
pSingleUserToken := flag.String("single-user", "", "single user token")
flag.Parse()
singleUser := false
if pSingleUser != nil {
singleUser = *pSingleUser
singleUserToken := ""
if pSingleUserToken != nil {
singleUserToken = *pSingleUserToken
}
if pMonitorPid != nil && *pMonitorPid > 0 {
@ -81,7 +81,7 @@ func main() {
config.Port = *pPort
}
server, err := server.New(config, singleUser)
server, err := server.New(config, singleUserToken)
if err != nil {
log.Fatal("server.New ERROR: ", err)
}

View File

@ -49,7 +49,7 @@ type Server struct {
localModeServer *http.Server
}
func New(cfg *config.Configuration, singleUser bool) (*Server, error) {
func New(cfg *config.Configuration, singleUserToken string) (*Server, error) {
logger, err := zap.NewProduction()
if err != nil {
return nil, err
@ -63,7 +63,7 @@ func New(cfg *config.Configuration, singleUser bool) (*Server, error) {
auth := auth.New(cfg, store)
wsServer := ws.NewServer(auth, singleUser)
wsServer := ws.NewServer(auth, singleUserToken)
filesBackendSettings := model.FileSettings{}
filesBackendSettings.SetDefaults(false)
@ -78,7 +78,7 @@ func New(cfg *config.Configuration, singleUser bool) (*Server, error) {
webhookClient := webhook.NewClient(cfg)
appBuilder := func() *app.App { return app.New(cfg, store, auth, wsServer, filesBackend, webhookClient) }
api := api.NewAPI(appBuilder, singleUser)
api := api.NewAPI(appBuilder, singleUserToken)
// Local router for admin APIs
localRouter := mux.NewRouter()
@ -157,7 +157,7 @@ func New(cfg *config.Configuration, singleUser bool) (*Server, error) {
"port": cfg.Port == config.DefaultPort,
"useSSL": cfg.UseSSL,
"dbType": cfg.DBType,
"single_user": singleUser,
"single_user": len(singleUserToken) > 0,
}
})
telemetryService.RegisterTracker("activity", func() map[string]interface{} {

View File

@ -18,11 +18,11 @@ type IsValidSessionToken func(token string) bool
// Server is a WebSocket server.
type Server struct {
upgrader websocket.Upgrader
listeners map[string][]*websocket.Conn
mu sync.RWMutex
auth *auth.Auth
singleUser bool
upgrader websocket.Upgrader
listeners map[string][]*websocket.Conn
mu sync.RWMutex
auth *auth.Auth
singleUserToken string
}
// UpdateMsg is sent on block updates
@ -50,7 +50,7 @@ type websocketSession struct {
}
// NewServer creates a new Server.
func NewServer(auth *auth.Auth, singleUser bool) *Server {
func NewServer(auth *auth.Auth, singleUserToken string) *Server {
return &Server{
listeners: make(map[string][]*websocket.Conn),
upgrader: websocket.Upgrader{
@ -58,8 +58,8 @@ func NewServer(auth *auth.Auth, singleUser bool) *Server {
return true
},
},
auth: auth,
singleUser: singleUser,
auth: auth,
singleUserToken: singleUserToken,
}
}
@ -91,7 +91,7 @@ func (ws *Server) handleWebSocketOnChange(w http.ResponseWriter, r *http.Request
wsSession := websocketSession{
client: client,
isAuthenticated: ws.singleUser,
isAuthenticated: false,
}
// Simple message handling loop
@ -134,8 +134,8 @@ func (ws *Server) handleWebSocketOnChange(w http.ResponseWriter, r *http.Request
}
func (ws *Server) isValidSessionToken(token string) bool {
if ws.singleUser {
return true
if len(ws.singleUserToken) > 0 {
return token == ws.singleUserToken
}
session, err := ws.auth.GetSession(token)
@ -160,10 +160,6 @@ func (ws *Server) authenticateListener(wsSession *websocketSession, token string
}
func (ws *Server) checkAuthentication(wsSession *websocketSession, command *WebsocketCommand) bool {
if ws.singleUser {
return true
}
if wsSession.isAuthenticated {
return true
}