Authorization & Role-Based Access Control
Authentication answers "who are you?" — authorization answers "what are you allowed to do?" MongoDB implements authorization through Role-Based Access Control (RBAC): every user has one or more roles, and every role is a bundle of specific privileges.
Built-in Roles
Role | Grants |
|---|---|
| Read data on a specific database |
| Read and write data on a specific database |
| Schema/index management, stats — no data read/write |
| Create and manage users and roles on a database — no data access |
| Combination of readWrite + dbAdmin + userAdmin on a database |
| Read access across every database in the cluster |
| Read/write access across every database in the cluster |
| Cluster-wide administrative actions (replication, sharding config) |
| Read-only access to monitoring/diagnostic data cluster-wide |
| Privileges needed to run backup/restore tooling |
| Superuser — combines the most powerful built-in roles; avoid for application users |
Granting and Revoking Roles
use shop
db.grantRolesToUser("appUser", [{ role: "readWrite", db: "shop" }])
db.revokeRolesFromUser("appUser", [{ role: "dbAdmin", db: "shop" }])
// Inspect a user's current roles and privileges
db.getUser("appUser")Custom Roles — Resource + Actions
When built-in roles are too broad, define a custom role as a set of privileges — each privilege pairs a resource (database + collection) with a list of allowed actions.
Custom role: write orders, read-only everywhere else
db.createRole({
role: "orderServiceRole",
privileges: [
{
resource: { db: "shop", collection: "orders" },
actions: ["find", "insert", "update"]
},
{
resource: { db: "shop", collection: "products" },
actions: ["find"]
}
],
roles: [] // can also compose from existing roles instead of raw privileges
})
db.grantRolesToUser("orderService", [{ role: "orderServiceRole", db: "shop" }])Least-Privilege Examples
A concrete pattern: give every distinct workload its own user with only the privileges that workload needs.
Application user — readWrite on its own database only
db.createUser({
user: "appUser",
pwd: passwordPrompt(),
roles: [{ role: "readWrite", db: "shop" }]
})Analytics user — read-only, across a couple of databases
db.createUser({
user: "analyticsUser",
pwd: passwordPrompt(),
roles: [
{ role: "read", db: "shop" },
{ role: "read", db: "billing" }
]
})Backup user — the built-in backup role only, nothing else
db.createUser({
user: "backupAgent",
pwd: passwordPrompt(),
roles: [{ role: "backup", db: "admin" }]
})backup role can run mongodump across the deployment, but cannot read individual document contents through normal queries or modify any data — exactly the access a backup job needs and nothing more.Viewing Effective Privileges
db.getUser("appUser", { showPrivileges: true })
db.getRole("orderServiceRole", { showPrivileges: true })Common Actions Reference
Action | Covers |
|---|---|
| Read documents |
| Insert documents |
| Modify existing documents |
| Delete documents |
| Manage indexes |
| Manage collections |
| Open change streams on the resource |
| Introspect schema/index metadata |
root or dbOwner to application service accounts. If a service is compromised, its blast radius should be limited to what that specific service actually needs to touch — least privilege is the single biggest lever you have against a credential leak turning into a full data breach.Summary
RBAC bundles specific privileges (resource + action) into roles, which are then assigned to users.
Built-in roles cover most common needs (read, readWrite, dbAdmin, cluster roles) — reach for custom roles when you need finer-grained control.
Design one user per workload (application, analytics, backup) scoped to exactly what that workload needs.
Regularly audit
db.getUser(..., { showPrivileges: true })output for accounts holding more access than they use.