fix(auth): export IsAdmin, fix bearer token fallback chain

This commit is contained in:
Claus Lohmar 2026-06-14 14:58:02 +00:00
parent 7c0d5a7b91
commit 1780cea340
2 changed files with 20 additions and 19 deletions

View file

@ -25,7 +25,7 @@ func (rc *RoleChecker) RequireAdmin(next http.Handler) http.Handler {
return return
} }
isAdmin, err := rc.isAdmin(userID) isAdmin, err := rc.IsAdmin(userID)
if err != nil || !isAdmin { if err != nil || !isAdmin {
http.Error(w, `{"error":"forbidden"}`, http.StatusForbidden) http.Error(w, `{"error":"forbidden"}`, http.StatusForbidden)
return return
@ -35,8 +35,8 @@ func (rc *RoleChecker) RequireAdmin(next http.Handler) http.Handler {
}) })
} }
// isAdmin checks if a user has the admin role. // IsAdmin checks if a user has the admin role.
func (rc *RoleChecker) isAdmin(username string) (bool, error) { func (rc *RoleChecker) IsAdmin(username string) (bool, error) {
var role string var role string
err := rc.db.QueryRow("SELECT role FROM users WHERE username = ?", username).Scan(&role) err := rc.db.QueryRow("SELECT role FROM users WHERE username = ?", username).Scan(&role)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {

View file

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"flag" "flag"
"fmt" "fmt"
"log/slog" "log/slog"
@ -130,26 +131,26 @@ func main() {
} }
uiHandler.RegisterRoutes(mux, combinedAuth) uiHandler.RegisterRoutes(mux, combinedAuth)
// --- Admin routes: session+role OR bearer token --- // --- Admin auth: session (with admin role) OR bearer token ---
adminRoleAuth := func(next http.Handler) http.Handler {
return sessionStore.SessionMiddleware(roleChecker.RequireAdmin(next))
}
bearerAuth := admin.TokenAuthMiddleware(cfg.Admin.SecretToken) bearerAuth := admin.TokenAuthMiddleware(cfg.Admin.SecretToken)
// Combined: try session+role first, fall back to bearer token
adminAuth := func(next http.Handler) http.Handler { adminAuth := func(next http.Handler) http.Handler {
return adminRoleAuth(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Check if session user exists and has admin role // First, try session-based authentication
userID, ok := auth.GetUserID(r) cookie, err := r.Cookie("nextwks_session")
if ok { if err == nil && cookie != nil {
// Session is valid — already verified by RequireAdmin session, err := sessionStore.ValidateSession(cookie.Value)
_ = userID if err == nil && session != nil {
next.ServeHTTP(w, r) isAdmin, _ := roleChecker.IsAdmin(session.UserID)
if isAdmin {
ctx := context.WithValue(r.Context(), auth.ContextUserID, session.UserID)
next.ServeHTTP(w, r.WithContext(ctx))
return return
} }
// No valid session — try bearer token }
}
// Fall back to bearer token
bearerAuth(next).ServeHTTP(w, r) bearerAuth(next).ServeHTTP(w, r)
})) })
} }
adminHandler.RegisterRoutes(mux, adminAuth) adminHandler.RegisterRoutes(mux, adminAuth)