go-kit/kit · error · ErrUnauthorized

Unauthorized Access

Error message

Unauthorized Access

What it means

Returned by go-kit's casbin.NewEnforcer middleware when enforcer.Enforce(subject, object, action) completed without error but returned false. Unlike the context errors, this is the policy itself deciding the subject may not perform the action on the object under the configured model. It is the expected denial path, not a malfunction.

Source

Thrown at auth/casbin/middleware.go:40

	CasbinPolicyContextKey contextKey = "CasbinPolicy"

	// CasbinEnforcerContextKey holds the key to retrieve the active casbin
	// Enforcer.
	CasbinEnforcerContextKey contextKey = "CasbinEnforcer"
)

var (
	// ErrModelContextMissing denotes a casbin model was not passed into
	// the parsing of middleware's context.
	ErrModelContextMissing = errors.New("CasbinModel is required in context")

	// ErrPolicyContextMissing denotes a casbin policy was not passed into
	// the parsing of middleware's context.
	ErrPolicyContextMissing = errors.New("CasbinPolicy is required in context")

	// ErrUnauthorized denotes the subject is not authorized to do the action
	// intended on the given object, based on the context model and policy.
	ErrUnauthorized = errors.New("Unauthorized Access")
)

// NewEnforcer checks whether the subject is authorized to do the specified
// action on the given object. If a valid access control model and policy
// is given, then the generated casbin Enforcer is stored in the context
// with CasbinEnforcer as the key.
func NewEnforcer(
	subject string, object interface{}, action string,
) endpoint.Middleware {
	return func(next endpoint.Endpoint) endpoint.Endpoint {
		return func(ctx context.Context, request interface{}) (response interface{}, err error) {
			casbinModel := ctx.Value(CasbinModelContextKey)
			casbinPolicy := ctx.Value(CasbinPolicyContextKey)
			enforcer, err := stdcasbin.NewEnforcer(casbinModel, casbinPolicy)
			if err != nil {
				return nil, err
			}

View on GitHub (pinned to 78fbbceece)

Solutions

  1. Add the missing rule to the policy: p, <subject>, <object>, <action> (and the g grouping rule for RBAC roles)
  2. Verify the subject passed to NewEnforcer matches the identity in the policy — derive it from the JWT claims stored under jwt.JWTClaimsContextKey, not a hardcoded string
  3. Test the triple directly with a standalone casbin.Enforcer (enforcer.Enforce(sub, obj, act)) to confirm the model+policy behave as expected
  4. Check the policy_effect section of model.conf if rules exist but everything is still denied

Example fix

// before: hardcoded subject matches no policy rule
e := casbin.NewEnforcer("user", "data1", "read")(myEndpoint)
// policy.csv: p, alice, data1, read  -> everyone else denied

// after: use the authenticated subject from JWT claims
var e endpoint.Endpoint = endpoint.Chain(
	func(next endpoint.Endpoint) endpoint.Endpoint {
		return func(ctx context.Context, req interface{}) (interface{}, error) {
			claims := ctx.Value(jwt.JWTClaimsContextKey).(jwt.MapClaims)
			sub, _ := claims["sub"].(string)
			return next(context.WithValue(ctx, subKey, sub), req)
		}
	},
)(myEndpoint)
// and ensure policy.csv contains: p, <that-sub>, data1, read
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

resp, err := ep(ctx, req)
if err != nil {
	if errors.Is(err, casbin.ErrUnauthorized) {
		// map to 403 Forbidden; do NOT retry — the policy denied it
		return nil, httptransport.ErrorOnlyEncoder // or your error encoder returning 403
	}
	return nil, err
}

Prevention

When it happens

Trigger: The policy file/adapter has no rule matching the (subject, object, action) triple, e.g. policy.csv lacks 'p, alice, data1, read'; the subject string doesn't match what's in the policy (hardcoded placeholder instead of the JWT claim subject); object/action typos; RBAC role not assigned ('g' grouping rules missing); policy_effect definition in model.conf evaluates to deny.

Common situations: New endpoint protected before policy rules are written; subject taken from a different identity field than the one used when issuing rules; role assignments lost after policy reload; ABAC model where attribute matching silently fails; environment whose policy file is an old version.

Understand the failure class

Related errors


AI-assisted analysis of go-kit/kit@78fbbceece (2026-08-15). Data as JSON: /api/errors/6e4290648ed0e98c. Report an issue: GitHub.