Feat: add models/cache/config
This commit is contained in:
		
							
								
								
									
										83
									
								
								handlers/middleware.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								handlers/middleware.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| package handlers | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/hmac" | ||||
| 	"crypto/sha256" | ||||
| 	"encoding/base64" | ||||
| 	"errors" | ||||
| 	"golias/config" | ||||
| 	"golias/pkg/cache" | ||||
| 	"log/slog" | ||||
| 	"net/http" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| 	cfg      config.Config | ||||
| 	memcache cache.Cache | ||||
| ) | ||||
|  | ||||
| func GetSession(next http.Handler) http.Handler { | ||||
| 	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||
| 		cookieName := "session_token" | ||||
| 		sessionCookie, err := r.Cookie(cookieName) | ||||
| 		if err != nil { | ||||
| 			msg := "auth failed; failed to get session token from cookies" | ||||
| 			slog.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" | ||||
| 			slog.Debug(msg, "error", err) | ||||
| 			next.ServeHTTP(w, r) | ||||
| 			return | ||||
| 		} | ||||
| 		cookieValue := string(cookieValueB) | ||||
| 		if len(cookieValue) < sha256.Size { | ||||
| 			slog.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(cookieName)) | ||||
| 		mac.Write([]byte(sessionToken)) | ||||
| 		expectedSignature := mac.Sum(nil) | ||||
| 		if !hmac.Equal([]byte(signature), expectedSignature) { | ||||
| 			slog.Debug("cookie with an invalid sign") | ||||
| 			next.ServeHTTP(w, r) | ||||
| 			return | ||||
| 		} | ||||
| 		userSession, err := cacheGetSession(sessionToken) | ||||
| 		if err != nil { | ||||
| 			msg := "auth failed; session does not exists" | ||||
| 			err = errors.New(msg) | ||||
| 			slog.Debug(msg, "error", err) | ||||
| 			next.ServeHTTP(w, r) | ||||
| 			return | ||||
| 		} | ||||
| 		if userSession.IsExpired() { | ||||
| 			memcache.RemoveKey(sessionToken) | ||||
| 			msg := "session is expired" | ||||
| 			slog.Debug(msg, "error", err, "token", sessionToken) | ||||
| 			next.ServeHTTP(w, r) | ||||
| 			return | ||||
| 		} | ||||
| 		ctx := context.WithValue(r.Context(), | ||||
| 			"username", userSession.Username) | ||||
| 		if err := cacheSetSession(sessionToken, | ||||
| 			userSession); err != nil { | ||||
| 			msg := "failed to marshal user session" | ||||
| 			slog.Warn(msg, "error", err) | ||||
| 			next.ServeHTTP(w, r) | ||||
| 			return | ||||
| 		} | ||||
| 		next.ServeHTTP(w, r.WithContext(ctx)) | ||||
| 	}) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Grail Finder
					Grail Finder