Security: authentication, roles and encryption

Turn on authentication before anything else, grant the narrowest role that works, encrypt the wire and the sensitive fields, and know what each layer does not protect.

Authentication

# start with authentication and TLS enforced
mongod --auth --tlsMode requireTLS \
       --tlsCertificateKeyFile /etc/ssl/mongo.pem \
       --bind_ip 10.0.0.11

mongosh "mongodb://localhost:27017/?authSource=admin"
MechanismWhere it fits
SCRAM-SHA-256Default username and password; always pair it with TLS
X.509 client certificatesService-to-service authentication with no shared secret
LDAP or KerberosEnterprise directory integration in Atlas or Enterprise
AWS IAMAtlas and DocumentDB, using credentials from the instance role
Localhost exceptionCreating the first administrative user; close it afterwards
  • Enable authentication before the instance is reachable from anywhere else. Adding it later means every client change is made under pressure.
  • With --auth and no users, the localhost exception lets you create exactly one user and nothing else. If you never create it, the exception stays open.
  • Credentials belong in a secret manager and in the environment, never in a repository, a connection string in a log line, or a screenshot.

Roles and least privilege

use shop

db.createUser({
  user: "app",
  pwd: passwordPrompt(),
  roles: [ { role: "readWrite", db: "shop" } ]
});

db.createRole({
  role: "orderReader",
  privileges: [
    { resource: { db: "shop", collection: "orders" },
      actions: [ "find" ] }
  ],
  roles: []
});

db.getUsers();
  • read, readWrite, dbAdmin and clusterMonitor cover most needs at database or cluster scope. root belongs on no application account, ever.
  • A custom role grants named actions on named resources, and is the correct answer when every built-in role is broader than the service needs.
  • The authSource in the connection string decides which database the user is looked up in. An application user defined in shop authenticates against shop, not admin.
  • Atlas database users and Atlas organisation users are different things: one has data access, the other administers the cluster.

Encryption, in transit and at rest

const schemaMap = {
  "shop.customers": {
    bsonType: "object",
    properties: {
      ssn: { encrypt: {
        keyId: [keyId],
        bsonType: "string",
        algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic"
      } }
    }
  }
};

const client = new MongoClient(uri, {
  autoEncryption: {
    keyVaultNamespace: "encryption.__keyVault",
    kmsProviders: kms,
    schemaMap
  }
});
  • TLS authenticates the server and encrypts the connection. Without it, SCRAM credentials are only as safe as the network they cross.
  • Encryption at rest protects a stolen disk or snapshot. It does nothing against a stolen credential, which is the more likely attack.
  • Deterministic field-level encryption still allows equality queries on the field; randomised encryption allows none. Choose per field, because it cannot be changed cheaply later.
  • Field-level encryption happens in the client, so the server stores ciphertext it cannot read — and cannot index or aggregate over that field usefully.
  • Atlas network rules, private endpoints and an IP access list are the first control. Treat the firewall as part of the design, not as an afterthought.
⚠️
A MongoDB server bound to a public interface with authentication disabled is not a rare misconfiguration — it is the standard story behind large public data exposures. Bind to private interfaces, enable authentication and require TLS before the instance is reachable by anything else.

FAQ

Do I need field-level encryption?
Only when a specific field must remain unreadable even by the database operator or someone holding a backup: regulated identifiers, health data, payment tokens. It costs query capability and key management effort, so apply it to the fields that require it rather than to whole documents.
Which role should an application use?
readWrite scoped to its own database, plus a custom role when it needs something narrower. Never root, and never the administrative account used to create the cluster.

Setting up MongoDB: Atlas, local install and mongosh Replica sets, failover and read preferences

Last refreshed 2026-09-18.