Skip to content

Admin API

Workers Auth includes a built-in admin API for user management. It ships as auth.admin — a standalone Hono app you mount wherever you want, protected however you see fit. List users, ban accounts, assign roles, and revoke sessions over HTTP without writing any of the plumbing yourself.

auth.admin is a separate Hono app. Mount it on any path and layer your own auth middleware in front of it:

const auth = WorkersAuth({ ... })
const app = new Hono()
// Mount auth and admin as separate route trees
app.route('/auth', auth.handler)
app.route('/admin', auth.admin)
// Protect admin routes — require a valid session and admin role
app.use('/admin/*', auth.authenticate)
app.use('/admin/*', auth.authorize('role', 'admin'))

You control the path, and you control who gets in. There is no hidden access — if you don’t mount it, it doesn’t exist.

All paths are relative to wherever you mount auth.admin.

MethodPathDescription
GET/usersList users (paginated)
GET/users/:idGet user with roles
POST/users/:id/banBan user, revoke sessions
POST/users/:id/unbanUnban user
POST/users/:id/rolesAssign role
DELETE/users/:id/roles/:roleRemove role

GET /users

Returns a paginated list of all users.

Query parameters:

ParameterTypeDefaultDescription
limitnumber50Maximum number of users to return
offsetnumber0Number of users to skip

Request:

Terminal window
curl https://your-app.workers.dev/admin/users?limit=10&offset=0 \
-H "Cookie: session=<session_token>"

Response:

{
"users": [
{
"id": "usr_abc123",
"email": "alice@example.com",
"status": "active",
"createdAt": 1706140800,
"updatedAt": 1706140800
},
{
"id": "usr_def456",
"email": "bob@example.com",
"status": "banned",
"createdAt": 1706054400,
"updatedAt": 1706227200
}
],
"total": 42,
"limit": 10,
"offset": 0
}

GET /users/:id

Returns a single user along with their assigned roles.

Request:

Terminal window
curl https://your-app.workers.dev/admin/users/usr_abc123 \
-H "Cookie: session=<session_token>"

Response:

{
"user": {
"id": "usr_abc123",
"email": "alice@example.com",
"status": "active",
"createdAt": 1706140800,
"updatedAt": 1706140800
},
"roles": ["admin", "editor"]
}

POST /users/:id/ban

Sets the user’s status to banned and revokes all of their active sessions immediately. The user is logged out everywhere, with no grace period.

Request:

Terminal window
curl -X POST https://your-app.workers.dev/admin/users/usr_def456/ban \
-H "Cookie: session=<session_token>"

Response:

{
"success": true
}

POST /users/:id/unban

Sets the user’s status back to active. The user can log in again, but previous sessions remain revoked — they will need to authenticate fresh.

Request:

Terminal window
curl -X POST https://your-app.workers.dev/admin/users/usr_def456/unban \
-H "Cookie: session=<session_token>"

Response:

{
"success": true
}

POST /users/:id/roles

Assigns a role to the user. The role must be defined in your RBAC policy.

Request:

Terminal window
curl -X POST https://your-app.workers.dev/admin/users/usr_abc123/roles \
-H "Cookie: session=<session_token>" \
-H "Content-Type: application/json" \
-d '{ "role": "admin" }'

Response:

{
"success": true
}

Returns 400 if the role field is missing from the request body:

{
"error": "role is required"
}

DELETE /users/:id/roles/:role

Removes a role from the user.

Request:

Terminal window
curl -X DELETE https://your-app.workers.dev/admin/users/usr_abc123/roles/admin \
-H "Cookie: session=<session_token>"

Response:

{
"success": true
}

Banning a user does two things:

  1. Sets the user’s status to banned in the database.
  2. Revokes all active sessions immediately. Every session token for that user is deleted from both D1 and KV. Any request carrying one of those tokens will fail authentication on the next call.

This is not eventual — the user is locked out the moment the ban endpoint returns.

The authenticate middleware also enforces bans at the edge. If a banned user makes a request with a stale session cookie that hasn’t been cleaned up yet, authenticate will check the user’s status, reject the request with a 403, and revoke the stale session on the spot. There is no window where a banned user can sneak through.