user2877989
user2877989

Reputation: 701

MongoDB C# Driver check Authentication status & Role

This is my code to login to MongoDB by using MongoDB Authentication Mechanisms.

try
{
    var credential = MongoCredential.CreateMongoCRCredential("test", "admin", "123456");
    var settings = new MongoClientSettings
    {
        Credentials = new[] { credential }
    };
    var mongoClient = new MongoClient(settings);
    var _database = mongoClient.GetDatabase("test");
    var collection = _database.GetCollection<Test>("book");
    var filter = new BsonDocument();
    var document = collection.Find(new BsonDocument()).ToList();
}
catch (Exception ex)
{
}

When we put wrong username/password in the Credential, how to check the login result? Currently I can't check it, I have to wait to collection.Find().ToList() throw an TimeoutException , and in this context it's authentication failed. We must make a CRUD to check the authentication result (by catching TimeoutException). It's not a good manner to check login status.

And when we put right username/password to authenticate, how to check the account role in this database?

Upvotes: 3

Views: 2228

Answers (1)

Alex
Alex

Reputation: 21766

Looking at the source code for the C# MongoDB client, the MongoClient constructors do not throw any connectivity-related exceptions. It's only when an application uses the MongoClient to perform some a on the MongoDB server that an exception will be thrown. However, as you discovered, that exception is a generic time-out exception indicating that the driver failed to find a suitable server. As the exception itself does contain details regarding the failure, you can use that information to create a method like the one below to check if you can run a dummy command against the database. In this method I have reduced all the time out values to one second:

public static void CheckAuthentication(MongoCredential credential, MongoServerAddress server)
    {
        try
        {
            var clientSettings = new MongoClientSettings()
            {
                Credentials = new[] {credential},
                WaitQueueTimeout = new TimeSpan(0, 0, 0, 1),
                ConnectTimeout = new TimeSpan(0, 0, 0, 1),
                Server = server,
                ClusterConfigurator = builder =>
                {
                    //The "Normal" Timeout settings are for something different. This one here really is relevant when it is about
                    //how long it takes until we stop, when we cannot connect to the MongoDB Instance
                    //https://jira.mongodb.org/browse/CSHARP-1018, https://jira.mongodb.org/browse/CSHARP-1231
                    builder.ConfigureCluster(
                        settings => settings.With(serverSelectionTimeout: TimeSpan.FromSeconds(1)));
                }
            };

            var mongoClient = new MongoClient(clientSettings);
            var testDB = mongoClient.GetDatabase("test");
            var cmd = new BsonDocument("count", "foo");

            var result = testDB.RunCommand<BsonDocument>(cmd);
        }
        catch (TimeoutException e)
        {

            if (e.Message.Contains("auth failed"))
            {
                Console.WriteLine("Authentication failed");
            }

            throw;
        }
    }

As per your comment you can query roles for a given user, using the snippet below:

var mongoClient = new MongoClient(clientSettings);
var testDB = mongoClient.GetDatabase("test");
string userName = "test1";
var cmd = new BsonDocument("usersInfo", userName);
var queryResult = testDB.RunCommand<BsonDocument>(cmd);
var roles = (BsonArray)queryResult[0][0]["roles"];
var result = from roleDetail in roles select new {Role=roleDetail["role"].AsBsonValue.ToString(),RoleDB=roleDetail["db"].AsBsonValue.ToString()};

Upvotes: 5

Related Questions