package main import ( "context" "fmt" // "log" "net/http" "os" // "strconv" "strings" "github.com/golang-jwt/jwt" ) // Define a custom context key for storing user information var userCtxKey = &contextKey{"user"} type contextKey struct { name string } // TODO: Provide user with JWT for login/guest // AuthMiddleware is our JWT verification middleware func auth_middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 1. Extract the JWT from the request (e.g., Authorization header) authHeader := r.Header.Get("Authorization") if authHeader == "" { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } tokenString := "" parts := strings.Split(authHeader, " ") if len(parts) == 2 && strings.ToLower(parts[0]) == "bearer" { tokenString = parts[1] } else { http.Error(w, "Invalid Authorization header format", http.StatusUnauthorized) return } // 2. Verify the JWT token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { // Validate the signing method if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("invalid signing method: %v", token.Header["alg"]) } // Replace "your-secret-key" with your actual secret key return []byte(os.Getenv("API_SECRET_KEY")), nil }) if err != nil { http.Error(w, "Invalid token", http.StatusUnauthorized) return } if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { // 3. Optionally, extract user information from the claims and add it to the request context user_id_raw, ok := claims["user_id"].(float64) if !ok { http.Error(w, "Invalid user ID in token", http.StatusInternalServerError) return } user_id := int(user_id_raw) // Create a new context with the user information ctx := context.WithValue(r.Context(), userCtxKey, user_id) // Call the next handler in the chain, passing the new context next.ServeHTTP(w, r.WithContext(ctx)) } else { http.Error(w, "Invalid token claims", http.StatusUnauthorized) return } }) } // Helper function to extract user information from the context in your handlers func user_id_from_context(ctx context.Context) (int, bool) { userID, ok := ctx.Value(userCtxKey).(int) return userID, ok }