87 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package handlers
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"crypto/hmac"
 | |
| 	"crypto/sha256"
 | |
| 	"encoding/base64"
 | |
| 	"gralias/models"
 | |
| 	"net/http"
 | |
| )
 | |
| 
 | |
| // LogRequests logs all HTTP requests with method, path and duration
 | |
| func LogRequests(next http.Handler) http.Handler {
 | |
| 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | |
| 		// start := time.Now()
 | |
| 		// Wrap response writer to capture status code
 | |
| 		next.ServeHTTP(w, r)
 | |
| 		// duration := time.Since(start)
 | |
| 		// log.Debug("request completed",
 | |
| 		// 	"method", r.Method,
 | |
| 		// 	"path", r.URL.RequestURI(),
 | |
| 		// 	"duration", duration.String(),
 | |
| 		// )
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func GetSession(next http.Handler) http.Handler {
 | |
| 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | |
| 		sessionCookie, err := r.Cookie(models.AuthCookie)
 | |
| 		if err != nil {
 | |
| 			// msg := "auth failed; failed to get session token from cookies"
 | |
| 			// log.Debug(msg, "error", err)
 | |
| 			next.ServeHTTP(w, r)
 | |
| 			return
 | |
| 		}
 | |
| 		cookieValueB, err := base64.URLEncoding.
 | |
| 			DecodeString(sessionCookie.Value)
 | |
| 		if err != nil {
 | |
| 			msg := "auth failed; failed to decode b64 cookie"
 | |
| 			log.Debug(msg, "error", err)
 | |
| 			next.ServeHTTP(w, r)
 | |
| 			return
 | |
| 		}
 | |
| 		cookieValue := string(cookieValueB)
 | |
| 		if len(cookieValue) < sha256.Size {
 | |
| 			log.Warn("small cookie", "size", len(cookieValue))
 | |
| 			next.ServeHTTP(w, r)
 | |
| 			return
 | |
| 		}
 | |
| 		// Split apart the signature and original cookie value.
 | |
| 		signature := cookieValue[:sha256.Size]
 | |
| 		sessionToken := cookieValue[sha256.Size:]
 | |
| 		//verify signature
 | |
| 		mac := hmac.New(sha256.New, []byte(cfg.CookieSecret))
 | |
| 		mac.Write([]byte(models.AuthCookie))
 | |
| 		mac.Write([]byte(sessionToken))
 | |
| 		expectedSignature := mac.Sum(nil)
 | |
| 		if !hmac.Equal([]byte(signature), expectedSignature) {
 | |
| 			log.Debug("cookie with an invalid sign")
 | |
| 			next.ServeHTTP(w, r)
 | |
| 			return
 | |
| 		}
 | |
| 		userSession, err := repo.SessionByToken(r.Context(), sessionToken)
 | |
| 		if err != nil {
 | |
| 			msg := "auth failed; session does not exist"
 | |
| 			log.Debug(msg, "error", err, "key", sessionToken)
 | |
| 			next.ServeHTTP(w, r)
 | |
| 			return
 | |
| 		}
 | |
| 		if userSession.IsExpired() {
 | |
| 			if err := repo.SessionDelete(r.Context(), sessionToken); err != nil {
 | |
| 				log.Error("failed to delete session", "error", err)
 | |
| 			}
 | |
| 			// cache.MemCache.RemoveKey(sessionToken)
 | |
| 			msg := "session is expired"
 | |
| 			log.Debug(msg, "error", err, "token", sessionToken)
 | |
| 			next.ServeHTTP(w, r)
 | |
| 			return
 | |
| 		}
 | |
| 		ctx := context.WithValue(r.Context(),
 | |
| 			models.CtxUsernameKey, userSession.Username)
 | |
| 		ctx = context.WithValue(ctx,
 | |
| 			models.CtxSessionKey, userSession)
 | |
| 		next.ServeHTTP(w, r.WithContext(ctx))
 | |
| 	})
 | |
| }
 | 
