package httpapi import ( "net/http" "strings" "watch-party-backend/internal/auth" fbauth "firebase.google.com/go/v4/auth" "github.com/gin-gonic/gin" ) // AuthMiddleware validates Bearer tokens with the provided verifier. func AuthMiddleware(verifier auth.TokenVerifier) gin.HandlerFunc { return func(c *gin.Context) { header := c.GetHeader("Authorization") if header == "" || !strings.HasPrefix(header, "Bearer ") { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing or invalid authorization header"}) return } raw := strings.TrimSpace(strings.TrimPrefix(header, "Bearer")) if raw == "" { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing token"}) return } token, err := verifier.Verify(c.Request.Context(), raw) if err != nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"}) return } c.Set("firebaseToken", token) c.Next() } } // AdminOnly ensures the firebaseToken context value has admin=true claim. func AdminOnly() gin.HandlerFunc { return func(c *gin.Context) { val, ok := c.Get("firebaseToken") if !ok { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing token"}) return } token, ok := val.(*fbauth.Token) if !ok || token == nil { c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "missing token"}) return } admin, _ := token.Claims["admin"].(bool) if !admin { c.AbortWithStatusJSON(http.StatusForbidden, gin.H{"error": "admin only"}) return } c.Next() } }