Files
dance-lessons-coach/pkg/server/middleware.go
Gabriel Radureau 92e53a6801 ♻️ refactor(auth): move UserContextKey from pkg/greet to pkg/auth
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
2026-05-06 06:54:14 +02:00

64 lines
1.6 KiB
Go

package server
import (
"context"
"net/http"
"dance-lessons-coach/pkg/auth"
"dance-lessons-coach/pkg/user"
"github.com/rs/zerolog/log"
)
// AuthMiddleware handles JWT authentication and adds user to context
type AuthMiddleware struct {
authService user.AuthService
}
// NewAuthMiddleware creates a new authentication middleware
func NewAuthMiddleware(authService user.AuthService) *AuthMiddleware {
return &AuthMiddleware{
authService: authService,
}
}
// Middleware returns the authentication middleware function
func (m *AuthMiddleware) Middleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// Extract Authorization header
authHeader := r.Header.Get("Authorization")
if authHeader == "" {
// No authorization header, pass through with no user
next.ServeHTTP(w, r)
return
}
// Extract token from "Bearer <token>" format
const bearerPrefix = "Bearer "
if len(authHeader) < len(bearerPrefix) || authHeader[:len(bearerPrefix)] != bearerPrefix {
log.Trace().Ctx(ctx).Str("auth_header", authHeader).Msg("Invalid authorization header format")
next.ServeHTTP(w, r)
return
}
token := authHeader[len(bearerPrefix):]
// Validate JWT token
validatedUser, err := m.authService.ValidateJWT(ctx, token)
if err != nil {
log.Trace().Ctx(ctx).Err(err).Msg("JWT validation failed")
next.ServeHTTP(w, r)
return
}
// Add user to context
ctxWithUser := context.WithValue(ctx, auth.UserContextKey, validatedUser)
r = r.WithContext(ctxWithUser)
// Continue to next handler
next.ServeHTTP(w, r)
})
}