Skip to main content

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.