Authsome
1.x
Docs/Authsome/Warden Bridge
Open

Reading4 min
Updated31 Jul 2026
Sourcev1/bridges/warden.mdx

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 admin in the requesting tenant AND is in the EMEA region"

Interface01

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"`
}

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 interface03

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 Authorizer04

Authsome calls the Authorizer bridge for:

  1. RBAC permission checks — Before allowing any HasPermission evaluation on the RBAC service, the authorizer is called if Warden is configured.

  2. API endpoint access control — Auth-protected management routes (user ban/unban, RBAC management) check the authorizer.

  3. 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 NoopAuthorizer05

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()),
)
Warning

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 example06

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", _) = true

Refer to the Warden documentation for the full policy language reference.