ACL runs after authentication and checks the identified consumer's group membership. It is how one authenticated caller reaches an admin route and another does not.
# put consumers in groups
curl -X POST http://localhost:8001/consumers/acme/acls --data group=partners
curl -X POST http://localhost:8001/consumers/ops/acls --data group=internal
# allow only internal on the admin route
curl -X POST http://localhost:8001/routes/admin-route/plugins \
--data name=acl \
--data 'config.allow[]=internal'
# an auth plugin is required on the same route, or there is no consumer
ops calling /admin -> 200
acme calling /admin -> 403 {"message":"You cannot consume this service"}
no credential -> 401 (from key-auth, before ACL runs)
# allow and deny are mutually exclusive on one plugin instance.
# hide_groups_header=true stops Kong sending X-Consumer-Groups upstream.
Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.
Published 2026-08-25