Files
nexarch/internal/auth/middleware.go

63 lines
2.0 KiB
Go

package auth
import (
"context"
"net/http"
)
const CookieName = "nexarch_session"
type contextKey int
const claimsContextKey contextKey = iota
// RequireAuth schuetzt eine Route: ohne gueltiges, nicht abgelaufenes UND
// nicht widerrufenes Token im Session-Cookie wird 401 zurueckgegeben und der
// Handler nicht aufgerufen (IAM-02 Akzeptanzkriterium 3, IAM-17
// Akzeptanzkriterium 3: Widerrufspruefung zusaetzlich zur Signatur).
//
// revocation ist bewusst variadisch (0 oder 1 Wert) statt eines Pflicht-
// parameters: mehrere andere Kacheln (RBAC, TOTP, OIDC, Benachrichtigungs-
// praeferenzen) rufen RequireAuth bereits mit der bisherigen 2-Parameter-
// Form auf, und ein Pflicht-Widerrufscheck ist ausdruecklich nicht Teil
// dieser Kachel fuer JENE Module — hier geht es nur um IAM-02/IAM-17. Ohne
// uebergebenen RevocationChecker entfaellt nur die zusaetzliche Pruefung,
// die Signaturpruefung bleibt unveraendert.
func RequireAuth(issuer *TokenIssuer, next http.HandlerFunc, revocation ...RevocationChecker) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
cookie, err := r.Cookie(CookieName)
if err != nil {
http.Error(w, "nicht angemeldet", http.StatusUnauthorized)
return
}
claims, err := issuer.Verify(cookie.Value)
if err != nil {
http.Error(w, "nicht angemeldet", http.StatusUnauthorized)
return
}
if len(revocation) > 0 && revocation[0] != nil {
revoked, err := revocation[0].IsRevoked(r.Context(), claims)
if err != nil {
http.Error(w, "interner fehler bei der widerrufspruefung", http.StatusInternalServerError)
return
}
if revoked {
http.Error(w, "nicht angemeldet", http.StatusUnauthorized)
return
}
}
ctx := context.WithValue(r.Context(), claimsContextKey, claims)
next(w, r.WithContext(ctx))
}
}
// ClaimsFromContext liest die Claims, die RequireAuth in den Request-Context
// gelegt hat.
func ClaimsFromContext(ctx context.Context) (*Claims, bool) {
c, ok := ctx.Value(claimsContextKey).(*Claims)
return c, ok
}