auth: add RequireSession chi-compatible middleware
Implements HTTP middleware that enforces session authentication by validating session cookies and making claims available via ClaimsFromContext. Rejects requests without valid session cookies with 401 Unauthorized. Tested via four test cases: - Missing session cookie rejection - Valid cookie acceptance with claims extraction - Expired cookie rejection - Tampered cookie rejection Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
38
backend/internal/auth/middleware.go
Normal file
38
backend/internal/auth/middleware.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type contextKey int
|
||||
|
||||
const claimsContextKey contextKey = iota
|
||||
|
||||
// RequireSession returns middleware that rejects a request with 401 unless
|
||||
// it carries a valid SessionCookieName cookie signed with secret, and
|
||||
// otherwise makes the session's Claims available via ClaimsFromContext.
|
||||
func RequireSession(secret []byte) func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
cookie, err := r.Cookie(SessionCookieName)
|
||||
if err != nil {
|
||||
http.Error(w, "not authenticated", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
claims, err := ParseSessionCookie(cookie, secret)
|
||||
if err != nil {
|
||||
http.Error(w, "not authenticated", http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
next.ServeHTTP(w, r.WithContext(context.WithValue(r.Context(), claimsContextKey, claims)))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// ClaimsFromContext returns the authenticated user's Claims, as populated by
|
||||
// RequireSession.
|
||||
func ClaimsFromContext(ctx context.Context) (Claims, bool) {
|
||||
c, ok := ctx.Value(claimsContextKey).(Claims)
|
||||
return c, ok
|
||||
}
|
||||
Reference in New Issue
Block a user