70 lines
1.7 KiB
Go
70 lines
1.7 KiB
Go
package middleware
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/rede5/gohorsejobs/backend/internal/utils"
|
|
)
|
|
|
|
type contextKey string
|
|
|
|
const (
|
|
UserKey contextKey = "user"
|
|
)
|
|
|
|
// AuthMiddleware verifies the JWT token and adds user claims to the context
|
|
func AuthMiddleware(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
authHeader := r.Header.Get("Authorization")
|
|
if authHeader == "" {
|
|
http.Error(w, "Authorization header required", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
parts := strings.Split(authHeader, " ")
|
|
if len(parts) != 2 || parts[0] != "Bearer" {
|
|
http.Error(w, "Invalid authorization header format", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
tokenString := parts[1]
|
|
claims, err := utils.ValidateJWT(tokenString)
|
|
if err != nil {
|
|
http.Error(w, "Invalid or expired token", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
ctx := context.WithValue(r.Context(), UserKey, claims)
|
|
next.ServeHTTP(w, r.WithContext(ctx))
|
|
})
|
|
}
|
|
|
|
// RequireRole checks if the authenticated user has the required role
|
|
func RequireRole(roles ...string) func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
claims, ok := r.Context().Value(UserKey).(*utils.Claims)
|
|
if !ok {
|
|
http.Error(w, "Unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
// SuperAdmin has access to everything
|
|
if claims.Role == "superadmin" {
|
|
next.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
|
|
for _, role := range roles {
|
|
if claims.Role == role {
|
|
next.ServeHTTP(w, r)
|
|
return
|
|
}
|
|
}
|
|
|
|
http.Error(w, "Forbidden: insufficient permissions", http.StatusForbidden)
|
|
})
|
|
}
|
|
}
|