Warden Bridge
Advanced RBAC engine — delegates permission checks to Warden for richer RBAC, ReBAC, and ABAC policy evaluation.
The Warden bridge connects Authsome to the Warden authorization engine. When configured, Authsome's RBAC permission checks are delegated to Warden, which supports more expressive authorization models: full RBAC with inheritance, Relationship-Based Access Control (ReBAC), and Attribute-Based Access Control (ABAC) — all in a single policy engine.
Without Warden, Authsome evaluates permissions using its built-in RBAC store (rbac.Store), which supports role-permission assignments and a single level of role hierarchy. Warden unlocks policies like:
- "Allow access if the user owns the resource"
- "Allow access if the user is a member of the resource's parent organisation"
- "Deny access during weekends regardless of role"
- "Allow if user has role
adminin the requesting tenant AND is in the EMEA region"
Interface
The bridge.Authorizer interface is defined in github.com/xraph/authsome/bridge:
type Authorizer interface {
Check(ctx context.Context, req *AuthzRequest) (*AuthzResult, error)
}
type AuthzRequest struct {
Subject string `json:"subject"` // User ID
Action string `json:"action"` // e.g. "read", "write", "delete"
Resource string `json:"resource"` // e.g. "document", "api:v1/users"
Tenant string `json:"tenant,omitempty"`
}
type AuthzResult struct {
Allowed bool `json:"allowed"`
Reason string `json:"reason,omitempty"`
}Setup with the Warden engine (recommended)
Authsome provides a first-class WithWarden option that accepts the concrete *warden.Engine directly. This is the recommended approach — it provides Warden's full RBAC/ReBAC/ABAC evaluation and also satisfies the bridge.Authorizer interface for backward compatibility:
import (
"github.com/xraph/authsome"
"github.com/xraph/warden"
"github.com/xraph/authsome/store/postgres"
)
// Build the Warden engine.
wardenEng, err := warden.New(
warden.WithStore(wardenStore),
warden.WithPolicy(warden.PolicyOPA), // or PolicyCasbin, PolicyCEL
)
if err != nil {
log.Fatal(err)
}
// Register with Authsome using the first-class option.
eng, err := authsome.New(
authsome.WithStore(pgStore),
authsome.WithWarden(wardenEng),
)Internally, WithWarden calls:
e.warden_ = wardenEng
e.authorizer = wardenadapter.New(wardenEng)Setup with the generic Authorizer interface
If you want to integrate a different authorization engine, implement bridge.Authorizer directly:
import (
"github.com/xraph/authsome"
"github.com/xraph/authsome/bridge/wardenadapter"
)
eng, err := authsome.New(
authsome.WithStore(pgStore),
authsome.WithAuthorizer(wardenadapter.New(wardenEng)),
)How Authsome uses the Authorizer
Authsome calls the Authorizer bridge for:
- RBAC permission checks — Before allowing any
HasPermissionevaluation on the RBAC service, the authorizer is called if Warden is configured. - API endpoint access control — Auth-protected management routes (user ban/unban, RBAC management) check the authorizer.
- Plugin-level checks — Plugins that perform sensitive operations (e.g., the organization plugin before allowing member removal) can call the authorizer.
When the Authorizer is not configured (nil), Authsome falls back to its built-in RBAC store evaluation.
The NoopAuthorizer
During development, use the built-in NoopAuthorizer that always allows all requests:
import "github.com/xraph/authsome/bridge"
eng, err := authsome.New(
authsome.WithStore(memory.New()),
authsome.WithAuthorizer(bridge.NewNoopAuthorizer()),
)The NoopAuthorizer always returns allowed: true with the reason "standalone mode: always allowed". Never use it in production. In production, either configure Warden or rely on Authsome's built-in RBAC (which evaluates real role and permission assignments from the database).
Warden policy example
With Warden's OPA backend, you can write policies that express complex authorization logic:
package authsome
import future.keywords.if
default allow = false
# Allow if user has the required role in the tenant.
allow if {
role := data.roles[input.subject][input.tenant]
action_allowed(role, input.action, input.resource)
}
# Allow admins everything.
action_allowed("admin", _, _) = true
# Allow editors to write but not delete.
action_allowed("editor", "read", _) = true
action_allowed("editor", "write", _) = trueRefer to the Warden documentation for the full policy language reference.