// Package authmw provides provider-agnostic HTTP authentication and authorization // middleware for the Einherjar framework. // // The middleware chain follows a three-step pattern: // // 1. A provider-specific AuthMiddleware (from auth-jwt or auth-firebase) verifies // the token and calls [SetTokenData] to store uid and claims in the request context. // // 2. [EnrichmentMiddleware] reads uid+claims, calls the application-provided // [IdentityEnricher] to build a [security.Identity], wraps it in a // [security.SecurityBag], runs any registered [BagEnricher] functions to attach // extra attributes (tenant ID, hardware IDs, grant codes), and stores the bag // in context via [security.SetBagInContext]. // // 3. [AuthzMiddleware] — mounted per route — reads the identity from context and // checks the required permission against a [security.PermissionProvider]. // // # Typical wiring // // enricher := userservice.NewIdentityEnricher(userRepo) // // // Provider AuthMiddleware is added first (from auth-jwt or auth-firebase). // // Then, globally: // srv.Use(authmw.EnrichmentMiddleware(logger, enricher)) // // // Per route: // const Read = security.Permission(0) // srv.With(authmw.AuthzMiddleware(logger, permProvider, "orders", Read)). // Get("/orders", ordersHandler) // // # Multi-tenant // // srv.Use(authmw.EnrichmentMiddleware(logger, enricher, authmw.WithTenantHeader("X-Tenant-ID"))) // // # Custom bag enrichment // // const KeyHardwareID = "hardware_id" // // hwEnricher := authmw.BagEnricher(func(bag security.SecurityBag, r *http.Request) security.SecurityBag { // return bag.With(KeyHardwareID, r.Header.Get("X-Hardware-ID")) // }) // // srv.Use(authmw.EnrichmentMiddleware(logger, enricher, authmw.WithBagEnricher(hwEnricher))) package authmw