Skip to content

Middleware

Middleware in CoreAPI lives in pkg/middleware and is applied per route in routes/routes.go.


What's available

// pkg/middleware/auth_middleware.go

middleware.Protected(jwtService)          // validates JWT, rejects if missing or invalid
middleware.HasRole("ADMIN")               // exact role match
middleware.HasAnyRole("ADMIN", "MEMBER")  // matches any of the listed roles

Claims are set on c.Locals after Protected runs — accessible in handlers:

userID   := c.Locals("userId").(string)
role     := c.Locals("role").(string)
userType := c.Locals("userType").(string)

Adding middleware to a domain

Three files change — main.go, wire.go, routes.go. Handlers don't change.

main.go — create jwtService and pass it to Setup:

jwtService := jwt.NewJWTService(jwt.JWTConfig{
    SecretKey:       cfg.JWT.SecretKey,
    AccessTokenTTL:  int(cfg.JWT.AccessTokenTTL),
    RefreshTokenTTL: int(cfg.JWT.RefreshTokenTTL),
})

yourdomainroutes.Setup(v1, db.GetDB(), jwtService)

routes/wire.go — accept and forward it:

func Setup(r fiber.Router, db *gorm.DB, jwtService jwt.JWTService) {
    cfg := yourdomain.ConfigFromEnv()
    h   := handlers.NewHandler(db, cfg)
    registerRoutes(r, h, jwtService)
}

routes/routes.go — apply per route:

func registerRoutes(r fiber.Router, h *handlers.Handler, jwtService jwt.JWTService) {
    g := r.Group("/your-domain")
    g.Get("/:id", h.GetByID)                                                           // public
    g.Get("/",    middleware.Protected(jwtService), h.List)                            // auth required
    g.Post("/",   middleware.Protected(jwtService), middleware.HasAnyRole("ADMIN"), h.Create) // auth + role
}

Tips

Not all routes need middleware — apply it only where needed. Public read endpoints often don't need auth.

Order mattersProtected must come before HasAnyRole. Role check depends on claims that Protected sets.

jwtService is currently wired in setup.go for ticketing domains. New CoreAPI domains wire it from main.go directly as shown above.