From 12e3694b7664a8e6cc11dd130cbb92e9b079f17e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20Erbsh=C3=A4u=C3=9Fer?= Date: Sun, 7 Jun 2026 14:36:39 +0200 Subject: [PATCH] allow multi auth --- backend/api.go | 39 +++++++++++++++++++++++++-------------- backend/main.go | 2 +- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/backend/api.go b/backend/api.go index 1b41266..ecb334b 100644 --- a/backend/api.go +++ b/backend/api.go @@ -8,13 +8,14 @@ import ( "io" "log" "net/http" + "slices" "sync" ) type ApiHandler struct { - db *Database - mutex sync.RWMutex - authToken *string + db *Database + mutex sync.RWMutex + authTokens []string } const authTokenCookieName = "auth-token" @@ -22,6 +23,14 @@ const isAuthorizedContextKey = "is-authorized" const contentTypeHeaderKey = "Content-Type" const JsonMimeType = "application/json" +func MakeApiHandler(db *Database) ApiHandler { + return ApiHandler{ + db: db, + mutex: sync.RWMutex{}, + authTokens: make([]string, 0), + } +} + func (h *ApiHandler) ServeLoginPost(writer http.ResponseWriter, request *http.Request) { if !HasContentType(request, JsonMimeType) { WriteError(writer, http.StatusBadRequest, "expected json body", nil) @@ -64,7 +73,7 @@ func (h *ApiHandler) ServeLoginPost(writer http.ResponseWriter, request *http.Re authToken := hex.EncodeToString(rawAuthToken) h.mutex.Lock() - h.authToken = &authToken + h.authTokens = append(h.authTokens, authToken) h.mutex.Unlock() cookie := http.Cookie{} @@ -81,19 +90,21 @@ func (h *ApiHandler) ServeLoginPost(writer http.ResponseWriter, request *http.Re func (h *ApiHandler) ServeLogoutPost(writer http.ResponseWriter, request *http.Request) { cookie, _ := request.Cookie(authTokenCookieName) - if cookie != nil { - cookie := http.Cookie{} - cookie.Name = authTokenCookieName - cookie.Value = "" - cookie.Secure = true - cookie.HttpOnly = true - http.SetCookie(writer, &cookie) - } h.mutex.Lock() - h.authToken = nil + index := slices.Index(h.authTokens, cookie.Value) + if index >= 0 { + slices.Delete(h.authTokens, index, index+1) + } h.mutex.Unlock() + newCookie := http.Cookie{} + newCookie.Name = authTokenCookieName + newCookie.Value = "" + newCookie.Secure = true + newCookie.HttpOnly = true + http.SetCookie(writer, &newCookie) + WriteResponse(writer, http.StatusOK, map[string]interface{}{}) log.Printf("successful logout from '%s'", request.RemoteAddr) @@ -105,7 +116,7 @@ func (h *ApiHandler) ProcessAuth(next http.Handler, required bool) http.Handler cookie, _ := request.Cookie(authTokenCookieName) if cookie != nil { h.mutex.RLock() - isAuthorized = h.authToken != nil && *h.authToken == cookie.Value + isAuthorized = slices.Contains(h.authTokens, cookie.Value) h.mutex.RUnlock() } diff --git a/backend/main.go b/backend/main.go index d63763b..e09c845 100644 --- a/backend/main.go +++ b/backend/main.go @@ -41,7 +41,7 @@ func main() { } defer db.Close() - apiHandler := &ApiHandler{db: db} + apiHandler := MakeApiHandler(db) mux := http.NewServeMux() mux.Handle("/", http.FileServer(HtmlDir{http.Dir(frontendPath)}))