rbacMiddleware

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 22, 2025 License: MIT Imports: 8 Imported by: 0

README

RBAC Middleware for Go

A robust Role-Based Access Control (RBAC) middleware for Go HTTP services, leveraging Casbin for authorization and JWT for authentication.

Features

  • JWT token-based authentication
  • Flexible role extraction from JWT claims
  • Casbin-powered authorization rules
  • Easy integration with standard net/http handlers
  • Support for multiple roles per user
  • Built-in uber-fx integration

Installation

go get github.com/towiron/rbac-middleware

Quick Start

package main

import (
    "net/http"
    rbacMiddleware "github.com/towiron/rbac-middleware"
)

func main() {
    // Initialize the middleware
    middleware, err := rbacMiddleware.New(rbacMiddleware.Options{
        ModelPath:  "path/to/model.conf",
        PolicyPath: "path/to/policy.csv",
    })
    if err != nil {
        panic(err)
    }

    // Create your handler
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("Protected resource"))
    })

    // Wrap your handler with the middleware
    protected := middleware.Inject(handler)

    // Start the server
    http.ListenAndServe(":8080", protected)
}

Configuration

Casbin Model File (model.conf)
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
Casbin Policy File (policy.csv)
p, admin, /api/users, GET
p, admin, /api/users, POST
p, user, /api/users, GET

JWT Token Format

The middleware expects JWT tokens in the Authorization header with the following format:

Authorization: Bearer <token>

The JWT token should contain a roles claim that can be either:

  • A single string: "roles": "admin"
  • An array of strings: "roles": ["admin", "user"]

Example token payload:

{
    "sub": "1234567890",
    "roles": ["admin", "user"],
    "iat": 1516239022
}

Integration with uber-fx

package main

import (
    "go.uber.org/fx"
    rbacMiddleware "github.com/towiron/rbac-middleware"
)

func main() {
    app := fx.New(
        rbacMiddleware.Module,
        fx.Provide(
            func() rbacMiddleware.Options {
                return rbacMiddleware.Options{
                    ModelPath:  "path/to/model.conf",
                    PolicyPath: "path/to/policy.csv",
                }
            },
        ),
        // ... other providers and invokes
    )
    app.Run()
}

Error Handling

The middleware returns the following HTTP status codes:

  • 401 Unauthorized: Missing or invalid JWT token
  • 403 Forbidden: Valid token but insufficient permissions
  • Original handler response: Successful authorization

Development Workflow

  1. Install dependencies:

    make install-deps
    
  2. Make your changes and run linter:

    make lint
    
  3. Run tests and check coverage:

    make test
    make test-cover
    
  4. Generate and review coverage visualization:

    make test-cover-svg
    # or
    make test-cover-html
    
  5. Check documentation locally:

    make doc
    # Open http://localhost:6060/pkg/github.com/towiron/rbac-middleware/
    

TODO: License

Security Considerations

  1. Token Verification: By default, the middleware doesn't verify JWT signatures. In production, implement proper token verification.

Example Use Cases

Basic API Protection
// Define your routes with different permission levels
middleware.enforcer.AddPolicy("admin", "/api/admin/*", "GET")
middleware.enforcer.AddPolicy("user", "/api/users/*", "GET")

// Protected admin endpoint
http.Handle("/api/admin/", middleware.Inject(adminHandler))

// Protected user endpoint
http.Handle("/api/users/", middleware.Inject(userHandler))
Multiple Roles
// Allow access if user has any of the required roles
middleware.enforcer.AddPolicy("editor", "/api/content", "POST")
middleware.enforcer.AddPolicy("admin", "/api/content", "POST")

Support

For bugs and feature requests, please open an issue in the GitHub repository.

Before starting development, install the required dependencies:

make install-deps

This will install:

  • golangci-lint - for code linting
  • go-cover-treemap - for coverage visualization
  • godoc - for documentation serving
Available Make Commands
# Run linter
make lint

# Serve documentation at http://localhost:6060/pkg/github.com/towiron/rbac-middleware/
make doc

# Run tests with race detection and generate coverage profile
make test

# Show total test coverage percentage
make test-cover

# Generate coverage visualization in SVG format
make test-cover-svg

# Open coverage report in browser
make test-cover-html

# Install development dependencies
make install-deps

Documentation

Overview

Package rbacMiddleware provides Role-Based Access Control (RBAC) middleware for HTTP services using Casbin as the authorization engine and JWT tokens for role information.

Index

Constants

This section is empty.

Variables

View Source
var Module = fx.Provide(New)

Module provides the RBAC middleware for uber-fx dependency injection. Usage:

fx.New(
    rbacMiddleware.Module,
    fx.Provide(func() rbacMiddleware.Options {
        return rbacMiddleware.Options{
            ModelPath:  "path/to/model.conf",
            PolicyPath: "path/to/policy.csv",
        }
    }),
)

Functions

This section is empty.

Types

type Options

type Options struct {
	// ModelPath is the path to the Casbin model file.
	// The model file defines the RBAC model structure and assertion rules.
	ModelPath string

	// PolicyPath is the path to the Casbin policy file.
	// The policy file contains the actual authorization rules.
	PolicyPath string
}

Options configures the RBAC middleware.

type RBACMiddleware

type RBACMiddleware struct {
	// contains filtered or unexported fields
}

RBACMiddleware implements HTTP middleware for role-based access control. It validates JWT tokens and enforces access policies using Casbin.

func New

func New(opts Options) (*RBACMiddleware, error)

New creates a new RBAC middleware instance with the given options. It initializes a Casbin enforcer using the provided model and policy paths. Returns an error if the enforcer cannot be created.

func (*RBACMiddleware) Inject

func (rm *RBACMiddleware) Inject(next http.Handler) http.Handler

Inject returns an http.Handler that performs RBAC checks before calling the next handler. It expects a JWT token in the Authorization header with the format "Bearer <token>". The token should contain a "roles" claim with either a string or array of strings.

The middleware will return:

  • 401 Unauthorized if the token is missing or invalid
  • 403 Forbidden if the user's roles don't have permission for the requested path and method
  • Forward to the next handler if authorization is successful

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL
JackTT - Gopher 🇻🇳