middleware.go

 1package auth
 2
 3import (
 4	"net/http"
 5
 6	"github.com/git-bug/git-bug/entity"
 7)
 8
 9// Middleware injects a fixed identity into every request context.
10// Used in local single-user mode where auth is implicit (identity comes from
11// git config at server startup rather than per-request login).
12func Middleware(fixedUserId entity.Id) func(http.Handler) http.Handler {
13	return func(next http.Handler) http.Handler {
14		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
15			ctx := CtxWithUser(r.Context(), fixedUserId)
16			next.ServeHTTP(w, r.WithContext(ctx))
17		})
18	}
19}
20
21// RequireAuth is middleware that rejects unauthenticated requests with 401.
22// Use this on subrouters that must never be accessible without a valid session
23// (e.g. the REST API in oauth mode when the server is publicly deployed).
24func RequireAuth(next http.Handler) http.Handler {
25	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
26		if _, ok := r.Context().Value(identityCtxKey).(entity.Id); !ok {
27			http.Error(w, "authentication required", http.StatusUnauthorized)
28			return
29		}
30		next.ServeHTTP(w, r)
31	})
32}
33
34// SessionMiddleware reads the session cookie on every request and, when a
35// valid session exists, injects the corresponding identity ID into the context.
36//
37// Requests without a valid session are served as unauthenticated rather than
38// rejected: GraphQL's userIdentity field returns null and mutations fail with
39// ErrNotAuthenticated. This allows the frontend to gracefully degrade rather
40// than receiving hard HTTP errors for every unauthenticated page load.
41func SessionMiddleware(store *SessionStore) func(http.Handler) http.Handler {
42	return func(next http.Handler) http.Handler {
43		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
44			if cookie, err := r.Cookie(SessionCookie); err == nil {
45				if id, ok := store.Get(cookie.Value); ok {
46					r = r.WithContext(CtxWithUser(r.Context(), id))
47				}
48			}
49			next.ServeHTTP(w, r)
50		})
51	}
52}