Status V2UserDocumentParser::initializeUserCredentialsFromUserDocument(
    User* user, const BSONObj& privDoc) const {
    User::CredentialData credentials;
    std::string userDB = privDoc[AuthorizationManager::USER_DB_FIELD_NAME].String();
    BSONElement credentialsElement = privDoc[CREDENTIALS_FIELD_NAME];
    if (!credentialsElement.eoo()) {
        if (credentialsElement.type() != Object) {
            return Status(ErrorCodes::UnsupportedFormat,
                          "'credentials' field in user documents must be an object");
        }
        if (userDB == "$external") {
            BSONElement externalCredentialElement =
                credentialsElement.Obj()[MONGODB_EXTERNAL_CREDENTIAL_FIELD_NAME];
            if (!externalCredentialElement.eoo()) {
                if (externalCredentialElement.type() != Bool || !externalCredentialElement.Bool()) {
                    return Status(ErrorCodes::UnsupportedFormat,
                                  "'external' field in credentials object must be set to true");
                } else {
                    credentials.isExternal = true;
                }
            } else {
                return Status(ErrorCodes::UnsupportedFormat,
                              "User documents defined on '$external' must provide set "
                              "credentials to {external:true}");
            }
        } else {
            BSONElement scramElement = credentialsElement.Obj()[SCRAM_CREDENTIAL_FIELD_NAME];
            BSONElement mongoCRCredentialElement =
                credentialsElement.Obj()[MONGODB_CR_CREDENTIAL_FIELD_NAME];

            if (scramElement.eoo() && mongoCRCredentialElement.eoo()) {
                return Status(ErrorCodes::UnsupportedFormat,
                              "User documents must provide credentials for SCRAM-SHA-1 "
                              "or MONGODB-CR authentication");
            }

            if (!scramElement.eoo()) {
                // We are asserting rather then returning errors since these
                // fields should have been prepopulated by the calling code.
                credentials.scram.iterationCount = scramElement.Obj()["iterationCount"].numberInt();
                uassert(17501,
                        "Invalid or missing SCRAM iteration count",
                        credentials.scram.iterationCount > 0);

                credentials.scram.salt = scramElement.Obj()["salt"].str();
                uassert(17502, "Missing SCRAM salt", !credentials.scram.salt.empty());

                credentials.scram.serverKey = scramElement["serverKey"].str();
                uassert(17503, "Missing SCRAM serverKey", !credentials.scram.serverKey.empty());

                credentials.scram.storedKey = scramElement["storedKey"].str();
                uassert(17504, "Missing SCRAM storedKey", !credentials.scram.storedKey.empty());
            }

            if (!mongoCRCredentialElement.eoo()) {
                if (mongoCRCredentialElement.type() != String ||
                    mongoCRCredentialElement.valueStringData().empty()) {
                    return Status(ErrorCodes::UnsupportedFormat,
                                  "MONGODB-CR credentials must be non-empty strings");
                } else {
                    credentials.password = mongoCRCredentialElement.String();
                    if (credentials.password.empty()) {
                        return Status(ErrorCodes::UnsupportedFormat,
                                      "User documents must provide authentication credentials");
                    }
                }
            }
            credentials.isExternal = false;
        }
    } else {
        return Status(ErrorCodes::UnsupportedFormat,
                      "Cannot extract credentials from user documents without a "
                      "'credentials' field");
    }

    user->setCredentials(credentials);
    return Status::OK();
}