51 lines
1.4 KiB
Go
51 lines
1.4 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
|
|
"logjensticks/internal/db"
|
|
)
|
|
|
|
const CookieName = "session_token"
|
|
|
|
type contextKey string
|
|
|
|
const sessionContextKey contextKey = "session"
|
|
|
|
// Middleware validates the session cookie on every request. Attach this to
|
|
// any route that requires authentication.
|
|
func Middleware(dbc *db.Client) 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(CookieName)
|
|
if err != nil {
|
|
writeUnauthorized(w)
|
|
return
|
|
}
|
|
|
|
session, err := ValidateSession(r.Context(), dbc, cookie.Value)
|
|
if err != nil {
|
|
writeUnauthorized(w)
|
|
return
|
|
}
|
|
|
|
ctx := context.WithValue(r.Context(), sessionContextKey, session)
|
|
next.ServeHTTP(w, r.WithContext(ctx))
|
|
})
|
|
}
|
|
}
|
|
|
|
// SessionFromContext retrieves the validated session attached by Middleware.
|
|
// Returns nil if called outside an authenticated route.
|
|
func SessionFromContext(ctx context.Context) *Session {
|
|
s, _ := ctx.Value(sessionContextKey).(*Session)
|
|
return s
|
|
}
|
|
|
|
func writeUnauthorized(w http.ResponseWriter) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
w.Write([]byte(`{"success":false,"data":null,"error":{"code":"UNAUTHORIZED","message":"authentication required"}}`))
|
|
}
|