Files
imap-copier/internal/httpapi/auth.go
T

68 lines
2.0 KiB
Go

package httpapi
import (
"crypto/subtle"
"encoding/json"
"net/http"
"time"
"github.com/vasyansk/imap-copier/internal/config"
"github.com/vasyansk/imap-copier/internal/crypto"
"github.com/vasyansk/imap-copier/internal/orchestrator"
"github.com/vasyansk/imap-copier/internal/store"
"github.com/vasyansk/imap-copier/internal/wshub"
)
const cookieName = "session"
type Server struct {
cfg config.Config
store *store.Store
orch *orchestrator.Orchestrator
hub *wshub.Hub
}
func NewServer(cfg config.Config, s *store.Store, orch *orchestrator.Orchestrator, hub *wshub.Hub) *Server {
return &Server{cfg: cfg, store: s, orch: orch, hub: hub}
}
func (s *Server) handleLogin(w http.ResponseWriter, r *http.Request) {
var body struct{ User, Pass string }
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
http.Error(w, "bad json", http.StatusBadRequest)
return
}
uOK := subtle.ConstantTimeCompare([]byte(body.User), []byte(s.cfg.AuthUser)) == 1
pOK := subtle.ConstantTimeCompare([]byte(body.Pass), []byte(s.cfg.AuthPass)) == 1
if !uOK || !pOK {
http.Error(w, "invalid credentials", http.StatusUnauthorized)
return
}
tok := crypto.SignSession(s.cfg.SessionSecret, body.User, time.Now().Add(24*time.Hour))
http.SetCookie(w, &http.Cookie{
Name: cookieName, Value: tok, Path: "/",
HttpOnly: true, SameSite: http.SameSiteLaxMode, MaxAge: 86400,
})
w.WriteHeader(http.StatusOK)
}
func (s *Server) handleLogout(w http.ResponseWriter, r *http.Request) {
http.SetCookie(w, &http.Cookie{Name: cookieName, Value: "", Path: "/", MaxAge: -1})
w.WriteHeader(http.StatusOK)
}
func (s *Server) requireAuth(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c, err := r.Cookie(cookieName)
if err != nil {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
if _, ok := crypto.VerifySession(s.cfg.SessionSecret, c.Value, time.Now()); !ok {
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
next.ServeHTTP(w, r)
})
}