AuthzX + Fiber
Add authorization to your Fiber API in 5 minutes.
Install
go get github.com/authzx/authzx-go
Set up the client
package main
import (
"os"
authzx "github.com/authzx/authzx-go"
"github.com/gofiber/fiber/v2"
)
var client = authzx.NewClient(os.Getenv("AUTHZX_API_KEY"))
Create middleware
func AuthzMiddleware(resourceType, action string) fiber.Handler {
return func(c *fiber.Ctx) error {
userID := c.Get("X-User-ID")
if userID == "" {
return c.Status(401).JSON(fiber.Map{"error": "unauthorized"})
}
allowed, err := client.Check(c.Context(),
authzx.Subject{ID: userID, Type: "user"},
action,
authzx.Resource{ID: c.Params("id"), Type: resourceType},
)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": "authorization check failed"})
}
if !allowed {
return c.Status(403).JSON(fiber.Map{"error": "forbidden"})
}
return c.Next()
}
}
Apply to routes
app := fiber.New()
app.Get("/documents/:id", AuthzMiddleware("document", "read"), getDocument)
app.Put("/documents/:id", AuthzMiddleware("document", "write"), updateDocument)
app.Delete("/documents/:id", AuthzMiddleware("document", "delete"), deleteDocument)
With roles
func AuthzMiddleware(resourceType, action string) fiber.Handler {
return func(c *fiber.Ctx) error {
userID := c.Locals("user_id").(string)
roles := c.Locals("roles").([]string)
allowed, err := client.Check(c.Context(),
authzx.Subject{ID: userID, Type: "user", Roles: roles},
action,
authzx.Resource{ID: c.Params("id"), Type: resourceType},
)
if err != nil || !allowed {
return c.Status(403).JSON(fiber.Map{"error": "forbidden"})
}
return c.Next()
}
}
Full response with reason
func getDocument(c *fiber.Ctx) error {
resp, err := client.Authorize(c.Context(), &authzx.AuthorizeRequest{
Subject: authzx.Subject{ID: c.Get("X-User-ID")},
Resource: authzx.Resource{ID: c.Params("id"), Type: "document"},
Action: "read",
})
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": "authorization failed"})
}
if !resp.Allowed {
return c.Status(403).JSON(fiber.Map{"error": "forbidden", "reason": resp.Reason})
}
return c.JSON(fiber.Map{
"id": c.Params("id"),
"policy": resp.PolicyID,
"path": resp.AccessPath,
})
}
Using the local agent
var client = authzx.NewClient("", authzx.WithBaseURL("http://localhost:8181"))
No API key needed. Same middleware, sub-millisecond responses.