Authentication, Users and Role-Based Access Control

Advanced
13 min

Authentication, Users and Role-Based Access Control

A freshly installed MongoDB server accepts any connection from localhost with full privileges. That is convenient for a laptop and disastrous for anything reachable over a network. Production deployments must authenticate every client, grant each one only the privileges it needs, and encrypt data in transit and at rest. After this lesson you will be able to enable access control, create users with built-in and custom roles, choose an authentication mechanism, and configure TLS.

Enabling Access Control

Authentication is off by default on self-managed servers and always on in Atlas. Turn it on in mongod.conf (or with --auth), then create the first administrator through the localhost exception: until the first user exists, a connection from the same machine may create one.

yaml
# mongod.conf security: authorization: enabled net: bindIp: 127.0.0.1,10.0.0.12 # never 0.0.0.0 without auth and a firewall

The default mechanism is SCRAM-SHA-256, a challenge-response protocol in which the password never travels in clear text. Users are stored in the database where they are created, and clients must name it as the authSource.

Built-in Roles

| Role | Scope | Grants | |---|---|---| | read | database | find, listCollections, listIndexes | | readWrite | database | read plus insert, update, remove, createIndex | | dbAdmin | database | schema and index administration, profiling, stats | | dbOwner | database | readWrite + dbAdmin + userAdmin | | userAdmin | database | create and modify users and roles | | backup / restore | cluster | what mongodump and mongorestore need | | readAnyDatabase, readWriteAnyDatabase, userAdminAnyDatabase | all databases | cross-database variants, granted in admin | | root | cluster | everything; reserve for break-glass accounts |

An API service normally needs readWrite on its own database and nothing else. Manage users with a small set of commands:

javascript
db.getUsers() db.grantRolesToUser("orders_api", [{ role: "read", db: "analytics" }]) db.revokeRolesFromUser("orders_api", [{ role: "read", db: "analytics" }]) db.runCommand({ connectionStatus: 1 }) // who am I, and which roles apply

Custom Roles

When built-in roles are too broad, define privileges as actions on resources:

javascript
use shop db.createRole({ role: "orderReader", privileges: [ { resource: { db: "shop", collection: "orders" }, actions: ["find"] }, { resource: { db: "shop", collection: "products" }, actions: ["find"] } ], roles: [] // roles this role inherits from }) db.createUser({ user: "reporting", pwd: passwordPrompt(), roles: ["orderReader"] })

A resource can be a collection, a whole database or the cluster, and roles can inherit other roles, so build a hierarchy instead of repeating privilege lists.

Other Mechanisms and Atlas

| Mechanism | Use case | |---|---| | SCRAM-SHA-256 | default username/password | | x.509 certificates | machine-to-machine and replica set member authentication | | LDAP, Kerberos | enterprise directories (Enterprise Advanced) | | OpenID Connect | single sign-on with identity providers (7.0+, Enterprise and Atlas) | | AWS IAM | Atlas clusters accessed from AWS workloads without stored passwords |

Atlas adds network controls on top: an IP access list, VPC peering or private endpoints, and per-cluster database users managed in the UI, API or Terraform.

Encryption in Transit and at Rest

yaml
net: tls: mode: requireTLS certificateKeyFile: /etc/ssl/mongodb.pem CAFile: /etc/ssl/ca.pem

Clients then connect with tls=true in the connection string. Atlas enforces TLS on every connection. For data at rest, Enterprise and Atlas offer WiredTiger encryption with keys held in a KMS; on Community Edition use encrypted volumes. Client-Side Field Level Encryption and Queryable Encryption go further: the driver encrypts chosen fields before they leave the application, so the server, backups and database administrators never see the plaintext, while equality (and, since 8.0, range) queries still work on the encrypted values.

Common Mistakes

  • Running the application as root or dbOwner. A compromised API key should not be able to drop the database.
  • Binding to all interfaces without authentication. Exposed instances are found and wiped within hours.
  • Wrong authSource in the connection string, producing "Authentication failed" for a correct password.
  • Committing connection strings with passwords to repositories; rotate immediately if it happens.
Quick Quiz
Question 1 of 3

What is the localhost exception?

Key Takeaways

  • Enable security.authorization, bind to specific interfaces, and bootstrap the first admin through the localhost exception.
  • Users live in a database and authenticate with SCRAM-SHA-256 by default; specify authSource when connecting.
  • Assign built-in roles by least privilege — usually readWrite on one database — and create custom roles for finer control.
  • x.509, LDAP, Kerberos, OIDC and AWS IAM cover machine, enterprise and cloud identity needs; Atlas adds IP access lists and private networking.
  • Require TLS in transit, encrypt storage at rest, and use Queryable Encryption for the most sensitive fields.

Next lesson: MongoDB Best Practices and Security — a consolidated checklist for running MongoDB safely and efficiently.

Authentication, Users and Role-Based Access Control - MongoDB | CodeYourCraft | CodeYourCraft