dgraph-io/dgraph · error

ACL is disabled

Error message

ACL is disabled

What it means

ParseJWT's key-function returns this error when the worker's ACL configuration has no signing algorithm set (WorkerConfig.AclJwtAlg == nil). It means JWT verification cannot proceed because ACLs are disabled or not initialized, so no key/algorithm is available to validate the token. It is a configuration-state guard, not a problem with the token itself.

Source

Thrown at x/jwt_helper.go:33

var (
	errTokenExpired = errors.New("Token is expired")
)

// MaybeKeyToBytes converts the x.Sensitive type into []byte if the type of interface really
// is x.Sensitive. We keep the type x.Sensitive for private and public keys so that it
// doesn't get printed into the logs but the type the JWT library needs is []byte.
func MaybeKeyToBytes(k interface{}) interface{} {
	if kb, ok := k.(Sensitive); ok {
		return []byte(kb)
	}
	return k
}

func ParseJWT(jwtStr string) (jwt.MapClaims, error) {
	token, err := jwt.Parse(jwtStr, func(token *jwt.Token) (interface{}, error) {
		if WorkerConfig.AclJwtAlg == nil {
			return nil, errors.Errorf("ACL is disabled")
		}
		if token.Method.Alg() != WorkerConfig.AclJwtAlg.Alg() {
			return nil, errors.Errorf("unexpected signing method in token: %v", token.Header["alg"])
		}
		return MaybeKeyToBytes(WorkerConfig.AclPublicKey), nil
	})
	if err != nil {
		// This is for backward compatibility in clients
		if errors.Is(err, jwt.ErrTokenExpired) {
			err = errors.Wrap(errTokenExpired, jwt.ErrTokenInvalidClaims.Error())
		}
		return nil, errors.Wrapf(err, "unable to parse jwt token")
	}

	claims, ok := token.Claims.(jwt.MapClaims)
	if !ok || !token.Valid {
		return nil, errors.Errorf("claims in jwt token is not map claims")
	}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Enable and configure ACL on the node so WorkerConfig.AclJwtAlg is set (supply the ACL algorithm/key config at startup).
  2. Verify the startup config actually populates AclJwtAlg before serving requests; add a startup check that fails fast if ACL is expected but unset.
  3. If ACL is intentionally disabled, stop sending access JWTs to this node; treat any JWT as unauthenticated.
  4. Guard callers: check WorkerConfig.AclJwtAlg != nil before calling ParseJWT and return a clear 'ACL disabled' error to clients.

Example fix

// before (server started without ACL)
WorkerConfig.AclJwtAlg == nil -> ParseJWT returns "ACL is disabled"
// after (start with ACL enabled, e.g.)
dgraph zero --acl "access-ttl=24h; jwt-acl-alg=HS256" ...
// or guard:
if WorkerConfig.AclJwtAlg == nil { return errors.New("ACL is disabled") }
Defensive patterns

Strategy: validation

Validate before calling

if WorkerConfig.AclJwtAlg == nil || WorkerConfig.AclPublicKey == nil {
    return nil, errors.New("ACL is disabled: configure AclJwtAlg/AclPublicKey before authenticating")
}
_, err := x.ParseJWT(token)

Type guard

func aclEnabled() bool { return WorkerConfig.AclJwtAlg != nil && WorkerConfig.AclPublicKey != nil }

Prevention

When it happens

Trigger: Calling ParseJWT (directly or via validateToken, ExtractUserName, ExtractNamespaceFromJwt) when WorkerConfig.AclJwtAlg was never populated — i.e. the server was started without ACL enabled or the config load step that sets AclJwtAlg/AclPublicKey was skipped.

Common situations: Starting Dgraph without --acl directives (ACL disabled) while clients still send access JWTs; a config/flag parsing bug leaving AclJwtAlg unset; upgrading and renaming config fields so the algorithm is no longer loaded.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/3999d445dd164820. Report an issue: GitHub.