skip to content

What is authorizer.class.name, and how do the authorizer implementations differ between ZooKeeper and KRaft modes?

level: seniorimportance: should knowfreq 45%

answer

  1. unset = no authz = allow all
  2. KRaft → StandardAuthorizer (metadata log)
  3. ZK → AclAuthorizer (znodes)
  4. same deny-wins semantics, different store
  5. pluggable → OPA/LDAP/RBAC custom class

basics

~10 s

authorizer.class.name selects the pluggable Authorizer the broker uses. If unset, no authorization runs (allow all). KRaft clusters use StandardAuthorizer; legacy ZooKeeper clusters used AclAuthorizer.

solid answer

~40 s

authorizer.class.name is the broker config that names the class implementing Kafka's Authorizer interface. If you leave it unset, the broker performs no authorization at all — every authenticated request is allowed, so enabling authorization means setting this property. For KRaft-mode clusters the implementation is org.apache.kafka.metadata.authorizer.StandardAuthorizer, which stores ACLs in the KRaft metadata log. For legacy ZooKeeper-based clusters it was kafka.security.authorizer.AclAuthorizer (which replaced the even older SimpleAclAuthorizer), storing ACLs as znodes in ZooKeeper. Both honor super.users and allow.everyone.if.no.acl.found and implement the same deny-wins evaluation semantics, so operationally they behave identically; the difference is where ACLs are persisted. You can also supply a custom class implementing the Authorizer (formerly Authorizer/old kafka.security.auth.Authorizer) interface to integrate external systems like OPA or LDAP-backed policy.

go deeper

for a junior

Know that authorizer.class.name turns authorization on by naming the authorizer class; unset means no authorization.

for a middle

Name StandardAuthorizer (KRaft) vs AclAuthorizer (ZooKeeper) and that both share semantics.

for a senior

Explain ACL storage differences, the unset=allow-all gotcha, and migration implications.

for a principal

Design pluggable authorization (OPA/LDAP/RBAC) via the Authorizer interface and reason about centralized policy governance.

## What the property does `authorizer.class.name` tells the broker which class — implementing Kafka's `org.apache.kafka.server.authorizer.Authorizer` interface — to load and call on every request. The `Authorizer` interface defines `authorize(...)` plus ACL CRUD (`createAcls`, `deleteAcls`, `acls`). **If the property is empty/unset, there is no authorizer** and the broker allows every *authenticated* request. So 'turning on authorization' = setting this property. (Authentication is configured separately via listeners/SASL/SSL.) ## The two built-in implementations | Aspect | AclAuthorizer (ZooKeeper) | StandardAuthorizer (KRaft) | |---|---|---| | Class | `kafka.security.authorizer.AclAuthorizer` | `org.apache.kafka.metadata.authorizer.StandardAuthorizer` | | ACL storage | znodes in ZooKeeper | KRaft `__cluster_metadata` log | | Mode | legacy ZK clusters | KRaft (ZK-less) clusters | | Semantics | deny-wins, super.users, fallback | identical | `AclAuthorizer` superseded the original `SimpleAclAuthorizer`. With KRaft now the default and ZooKeeper removed in Kafka 4.0, `StandardAuthorizer` is what you'll use going forward. ## Shared semantics Both honor: - `super.users` (bypass), - `allow.everyone.if.no.acl.found` (fallback), - **deny-wins** ordering: DENY beats ALLOW. So a migration from ZK to KRaft doesn't change authorization *behavior*, only where ACLs live (and you must migrate the ACL data). ## Custom authorizers Because it's pluggable, you can point `authorizer.class.name` at your own class to delegate decisions to an external policy engine — e.g. Open Policy Agent (OPA), an LDAP/RBAC service, or Confluent's RBAC authorizer. Your class implements `Authorizer` and decides ALLOWED/DENIED per `Action`. This is how organizations get centralized, attribute-based, or role-based authorization beyond Kafka's native ACLs. ## Edge cases - Misconfiguring the class name (typo, wrong mode's class) prevents broker startup or fails ACL operations. - In KRaft, ACL writes go through the controller/metadata log; on ZK they go to ZooKeeper — tooling (`kafka-acls`) abstracts this but the underlying store differs. - A cluster with **no** authorizer set still authenticates clients but authorizes nothing — a common 'why are my ACLs ignored?' cause (ACLs created via tooling but no authorizer loaded to enforce them).

  • A team created ACLs with kafka-acls but they seem ignored. What's a likely root cause?
    authorizer.class.name is unset, so no authorizer is loaded. ACLs may be stored, but with no authorizer the broker authorizes nothing and allows all authenticated requests. They must set the authorizer class and restart.
  • How would you integrate Open Policy Agent for Kafka authorization?
    Implement (or use an off-the-shelf) class that satisfies the Authorizer interface, set authorizer.class.name to it, and have its authorize() call out to / embed OPA to evaluate Rego policies for each Action, returning ALLOWED/DENIED.

saying these in an interview costs you the question

  • Saying an unset authorizer means default-deny — it actually means no authorization (allow all authenticated).
  • Claiming KRaft and ZK authorizers have different evaluation semantics — only the ACL storage differs.
  • Naming SimpleAclAuthorizer as the current ZK class (it was superseded by AclAuthorizer).
  • Thinking you can't use external/RBAC policy engines — the authorizer is pluggable.

context