Close Menu
  • Home
  • Oracle
    • ASM
    • Data Guard
    • OEM
    • RAC
  • MongoDB
  • Performance
  • Python
  • Shell Script
  • Tools
  • Troubleshooting
Search

Rolling Upgrade: Percona Server for MongoDB 8.0.23-10 to 8.0.26-11

2026-06-26 MongoDB By Henrique

Clone a MongoDB User and Preserve the Password Hash

2026-06-26 MongoDB By Henrique

ORA-06553: DBCA Fails on catalog.sql with PLS-213

2026-06-25 Oracle By Henrique
YouTube LinkedIn RSS
  • Home
  • About
  • Contact
  • Legal
    • Cookie Policy
    • Disclaimer
    • Privacy Policy
    • Terms of Use
  • RSS
  • English
    • Portuguese (Brazil)
Execute StepExecute Step
YouTube LinkedIn RSS
  • Home
  • Oracle
    • ASM
    • Data Guard
    • OEM
    • RAC
  • MongoDB
  • Performance
  • Python
  • Shell Script
  • Tools
  • Troubleshooting
Execute StepExecute Step
Home » Clone a MongoDB User and Preserve the Password Hash
MongoDB

Clone a MongoDB User and Preserve the Password Hash

HenriqueBy Henrique2026-06-265 Mins Read
Share
Facebook Twitter LinkedIn Pinterest Email Telegram WhatsApp

This post is also available in: Português (Portuguese (Brazil))

When you need to copy a user from one MongoDB instance to another and keep the exact same credentials, db.createUser() won’t work. It always generates a new password hash. The only way to preserve credentials is through a direct insert into the system.users collection. This approach works on any topology: single instance, replica set, or shard.

This post documents the full process, tested in a production environment.

Why db.createUser() doesn’t work here

db.createUser() always derives new SCRAM-SHA-1 and SCRAM-SHA-256 hashes from a plaintext password. If you don’t have the original password, there’s no way to recreate the same credentials through the standard method.

The alternative is to extract the full document from system.users on the source and insert it directly on the destination.

Step 0: Extract the user on the source

Connect to the source instance and run:

db.getSiblingDB("admin").system.users.find(
  { user: "db_app_view", db: "admin" }
).toArray()

Expected output:

[
  {
    "_id": "admin.db_app_view",
    "user": "db_app_view",
    "db": "admin",
    "credentials": {
      "SCRAM-SHA-1": {
        "iterationCount": 10000,
        "salt": "<SALT_SHA1>",
        "storedKey": "<STORED_KEY_SHA1>",
        "serverKey": "<SERVER_KEY_SHA1>"
      },
      "SCRAM-SHA-256": {
        "iterationCount": 15000,
        "salt": "<SALT_SHA256>",
        "storedKey": "<STORED_KEY_SHA256>",
        "serverKey": "<SERVER_KEY_SHA256>"
      }
    },
    "roles": [
      { "role": "IPsPermitidos_users", "db": "admin" },
      { "role": "readAnyDatabase", "db": "admin" }
    ]
  }
]

Save all fields under credentials. These are the hashes you’ll replicate.

The problem: direct inserts are blocked by default

On the destination, a direct insert into system.users returns:

MongoServerError[Unauthorized]: not authorized on admin to execute command
{ insert: "system.users", ... }

Even when connected as admin, MongoDB blocks direct writes to system collections. The admin user holds userAdminAnyDatabase, but that role does not grant bypass access to internal collections.

Solution: temporarily grant __system

⚠️ Warning: The __system role grants unrestricted access to the server. Grant it only for the duration of this operation and revoke it immediately after.

Step 1: Grant __system to the admin user

use admin
db.grantRolesToUser("admin", [{ role: "__system", db: "admin" }])

Expected output:

{ "ok": 1 }

Step 2: Insert the cloned user

Replace the credentials values with those extracted from the source. Adjust roles as needed for the destination environment.

db.getSiblingDB("admin").system.users.insertOne({
  _id: "admin.db_app_view",
  user: "db_app_view",
  db: "admin",
  credentials: {
    "SCRAM-SHA-1": {
      iterationCount: 10000,
      salt: "<SALT_SHA1>",
      storedKey: "<STORED_KEY_SHA1>",
      serverKey: "<SERVER_KEY_SHA1>"
    },
    "SCRAM-SHA-256": {
      iterationCount: 15000,
      salt: "<SALT_SHA256>",
      storedKey: "<STORED_KEY_SHA256>",
      serverKey: "<SERVER_KEY_SHA256>"
    }
  },
  roles: [
    { role: "IPsPermitidos_users", db: "admin" },
    { role: "read", db: "pix" }
  ]
})

Expected output:

{ "acknowledged": true, "insertedId": "admin.db_app_view" }

💡 Note: Roles on the destination don’t have to match the source. Adjust them to fit the target environment.

Step 3: Invalidate the auth cache

db.adminCommand({ invalidateUserCache: 1 })

MongoDB keeps an in-memory cache of users and roles to avoid reading system.users on every authentication request. A direct insert bypasses the normal update path, so the cache is not refreshed automatically. Running invalidateUserCache forces the server to reload authentication data from disk immediately, making the new user available without a restart.

Expected output:

{ "ok": 1 }

Step 4: Revoke __system

⚠️ This step is mandatory. Do not leave the admin user with the __system role in production.

db.revokeRolesFromUser("admin", [{ role: "__system", db: "admin" }])

Expected output:

{ "ok": 1 }

Verify the result

Confirm the user was created correctly:

db.getSiblingDB("admin").system.users.find(
  { user: "db_app_view", db: "admin" }
).toArray()

Test authentication with the original credentials:

db.auth("db_app_view", "<original_password>")

Quick checklist

[ ] Extract system.users document on the source
[ ] Connect to the destination primary or instance
[ ] Grant __system to admin
[ ] Insert the document with insertOne into system.users
[ ] Run invalidateUserCache
[ ] Revoke __system from admin
[ ] Verify user with find on system.users
[ ] Test authentication

When to use this approach

This method is necessary when:

  • The original password is not available (only the hash)
  • You are migrating users between environments without a password reset
  • You need exact credential replication (e.g., infrastructure rotation without application impact)
  • You are moving users between different topologies (e.g., single instance to replica set)

If the original password is available, prefer db.createUser() on the destination. Direct inserts into system.users should be treated as a surgical operation, not a routine procedure.

authentication mongodb system.users
Share. Facebook Twitter Pinterest LinkedIn Tumblr Email WhatsApp
Previous ArticleORA-06553: DBCA Fails on catalog.sql with PLS-213
Next Article Rolling Upgrade: Percona Server for MongoDB 8.0.23-10 to 8.0.26-11

Related Posts

MongoDB

Rolling Upgrade: Percona Server for MongoDB 8.0.23-10 to 8.0.26-11

2026-06-26
Read More
MongoDB

MongoDB 8.0 + MongoShake on Oracle Linux 8- From Scratch to Cutover

2026-05-05
Read More
Tools

OEM PAM Authentication Failure- Fix with SSH Key Named Credentials

2026-04-16
Read More
0 0 votes
Article Rating
Subscribe
Login
Notify of
guest

guest

0 Comments
Oldest
Newest Most Voted
Demo
Follow Me
  • Email
  • GitHub
  • LinkedIn
  • RSS
  • YouTube

ORA-29548- How to Fix “Java System Class Reported” in Oracle Database

2026-03-0541 Views

INS-06006 – Passwordless SSH Connectivity Not Set Up

2026-02-2626 Views

PRVG-2002- How to Fix “Encountered Error in Copying File” in Oracle RAC

2026-03-0725 Views
Demo
Blogroll
  • oravirt
Execute Step
YouTube LinkedIn RSS
  • Home
  • About
  • Contact
  • RSS
  • English
    • Português (Portuguese (Brazil))
© 2026 ExecuteStep. Designed by ThemeSphere.

Type above and press Enter to search. Press Esc to cancel.

wpDiscuz
Ad Blocker Enabled!
Ad Blocker Enabled!
Our website is made possible by displaying online advertisements to our visitors. Please support us by disabling your Ad Blocker.