Authenticate After Picking the Database












1















I have 3 databases in my MongoDB server. I am using pymongo to do some scripting with Python3.



I want to use the latest versions and practices. Once I open the client and pick the database, the API for pymongo.MongoClient.['mydatabase'].authenticate is deprecated.
https://api.mongodb.com/python/current/api/pymongo/database.html



Authentication prior to picking the database (while dialing the client) doesn't seem to flow down toward the database. Not just for pymongo, but also when I use mongo shell. So I have a feeling this is the issue.



script.py



import pymongo
from pymongo import MongoClient
u = getUser() # function which prompts for username
p = getPassword() # getpass.getpass('Password')
uri = formatUri(u, p) # formats 'mongodb://%s:%s@%s'.format(user, password, host)

client = MongoClient(uri)
db = client['mydb']
col = db.mycollection
for doc in col.find():
print(doc)


I get the error that I am not authorized for the database. I know my account works in shell but I have to dial the client first then use the db and then auth.



Here's a mongo shell example:



$ mongo
MongoDB shell version: v3.4.10
Connecting to: mongodb://127.0.0.1:port
MongoDB server version: v3.4.10
> use mydb
switched to mydb
> db.auth("user", "pass")
1


Any idea how I can either auth after picking the database or once I use the db it remembers the context I dialed with?










share|improve this question

























  • The intent is that ALL authentication is stored in "admin" and simply identifies which database namespaces the account has the available privileges. So you would assign privelages on to the user for "mydb", but there is no such requirement that you "log in" on that database alone. It simply means that if you switch to "foo" database namespace where there are no assigned privileges, then you "cannot do anything". If you had privileges for "both" database namespaces, then you are allowed access to things without the need to "authenticate" again. Is that somewhat clearer?

    – Neil Lunn
    Nov 12 '17 at 20:34













  • I initially thought that was how it worked. For example, without using a database, I created my mongo user with all privileges in admin with literally every possible access and another user with just read access. I would then auth (still in admin) with that main account. Then switch and use "mydb" and when I "show users" in mydb, nothing shows. So I thought I had to recreate the account in mydb and give access.

    – DeadSupra
    Nov 12 '17 at 23:50











  • Is there something in the provided answer that you believe does not address your question? If so then please comment on the answer to clarify what exactly needs to be addressed that has not. If it does in fact answer the question you asked then please note to Accept your Answers to the questions you ask

    – Neil Lunn
    Nov 16 '17 at 5:28











  • It does. It makes sense to me because that is how I expected it to work the first time and I realized I created separate users within the same database. However, when I try to create a new user in admin I still can't use d.auth() to login in the database I am using. (I'm using just shell at this point since I realized it was never pymongo that had the issue). I believe I may have to reinstall mongo and start clean since I keep messing with the users, config, etc.

    – DeadSupra
    Nov 16 '17 at 6:39











  • You are given a clean case which is showing startup of clean database and reproducible steps for the purpose that you can run and replicate ans see what the correct process is. Once you can see what the correct process is and the answer addresses what was actually asked, then the process here is to "accept the answer" in order to indicate it's correctness to others viewing the question and it's answer.

    – Neil Lunn
    Nov 16 '17 at 6:46
















1















I have 3 databases in my MongoDB server. I am using pymongo to do some scripting with Python3.



I want to use the latest versions and practices. Once I open the client and pick the database, the API for pymongo.MongoClient.['mydatabase'].authenticate is deprecated.
https://api.mongodb.com/python/current/api/pymongo/database.html



Authentication prior to picking the database (while dialing the client) doesn't seem to flow down toward the database. Not just for pymongo, but also when I use mongo shell. So I have a feeling this is the issue.



script.py



import pymongo
from pymongo import MongoClient
u = getUser() # function which prompts for username
p = getPassword() # getpass.getpass('Password')
uri = formatUri(u, p) # formats 'mongodb://%s:%s@%s'.format(user, password, host)

client = MongoClient(uri)
db = client['mydb']
col = db.mycollection
for doc in col.find():
print(doc)


I get the error that I am not authorized for the database. I know my account works in shell but I have to dial the client first then use the db and then auth.



Here's a mongo shell example:



$ mongo
MongoDB shell version: v3.4.10
Connecting to: mongodb://127.0.0.1:port
MongoDB server version: v3.4.10
> use mydb
switched to mydb
> db.auth("user", "pass")
1


Any idea how I can either auth after picking the database or once I use the db it remembers the context I dialed with?










share|improve this question

























  • The intent is that ALL authentication is stored in "admin" and simply identifies which database namespaces the account has the available privileges. So you would assign privelages on to the user for "mydb", but there is no such requirement that you "log in" on that database alone. It simply means that if you switch to "foo" database namespace where there are no assigned privileges, then you "cannot do anything". If you had privileges for "both" database namespaces, then you are allowed access to things without the need to "authenticate" again. Is that somewhat clearer?

    – Neil Lunn
    Nov 12 '17 at 20:34













  • I initially thought that was how it worked. For example, without using a database, I created my mongo user with all privileges in admin with literally every possible access and another user with just read access. I would then auth (still in admin) with that main account. Then switch and use "mydb" and when I "show users" in mydb, nothing shows. So I thought I had to recreate the account in mydb and give access.

    – DeadSupra
    Nov 12 '17 at 23:50











  • Is there something in the provided answer that you believe does not address your question? If so then please comment on the answer to clarify what exactly needs to be addressed that has not. If it does in fact answer the question you asked then please note to Accept your Answers to the questions you ask

    – Neil Lunn
    Nov 16 '17 at 5:28











  • It does. It makes sense to me because that is how I expected it to work the first time and I realized I created separate users within the same database. However, when I try to create a new user in admin I still can't use d.auth() to login in the database I am using. (I'm using just shell at this point since I realized it was never pymongo that had the issue). I believe I may have to reinstall mongo and start clean since I keep messing with the users, config, etc.

    – DeadSupra
    Nov 16 '17 at 6:39











  • You are given a clean case which is showing startup of clean database and reproducible steps for the purpose that you can run and replicate ans see what the correct process is. Once you can see what the correct process is and the answer addresses what was actually asked, then the process here is to "accept the answer" in order to indicate it's correctness to others viewing the question and it's answer.

    – Neil Lunn
    Nov 16 '17 at 6:46














1












1








1








I have 3 databases in my MongoDB server. I am using pymongo to do some scripting with Python3.



I want to use the latest versions and practices. Once I open the client and pick the database, the API for pymongo.MongoClient.['mydatabase'].authenticate is deprecated.
https://api.mongodb.com/python/current/api/pymongo/database.html



Authentication prior to picking the database (while dialing the client) doesn't seem to flow down toward the database. Not just for pymongo, but also when I use mongo shell. So I have a feeling this is the issue.



script.py



import pymongo
from pymongo import MongoClient
u = getUser() # function which prompts for username
p = getPassword() # getpass.getpass('Password')
uri = formatUri(u, p) # formats 'mongodb://%s:%s@%s'.format(user, password, host)

client = MongoClient(uri)
db = client['mydb']
col = db.mycollection
for doc in col.find():
print(doc)


I get the error that I am not authorized for the database. I know my account works in shell but I have to dial the client first then use the db and then auth.



Here's a mongo shell example:



$ mongo
MongoDB shell version: v3.4.10
Connecting to: mongodb://127.0.0.1:port
MongoDB server version: v3.4.10
> use mydb
switched to mydb
> db.auth("user", "pass")
1


Any idea how I can either auth after picking the database or once I use the db it remembers the context I dialed with?










share|improve this question
















I have 3 databases in my MongoDB server. I am using pymongo to do some scripting with Python3.



I want to use the latest versions and practices. Once I open the client and pick the database, the API for pymongo.MongoClient.['mydatabase'].authenticate is deprecated.
https://api.mongodb.com/python/current/api/pymongo/database.html



Authentication prior to picking the database (while dialing the client) doesn't seem to flow down toward the database. Not just for pymongo, but also when I use mongo shell. So I have a feeling this is the issue.



script.py



import pymongo
from pymongo import MongoClient
u = getUser() # function which prompts for username
p = getPassword() # getpass.getpass('Password')
uri = formatUri(u, p) # formats 'mongodb://%s:%s@%s'.format(user, password, host)

client = MongoClient(uri)
db = client['mydb']
col = db.mycollection
for doc in col.find():
print(doc)


I get the error that I am not authorized for the database. I know my account works in shell but I have to dial the client first then use the db and then auth.



Here's a mongo shell example:



$ mongo
MongoDB shell version: v3.4.10
Connecting to: mongodb://127.0.0.1:port
MongoDB server version: v3.4.10
> use mydb
switched to mydb
> db.auth("user", "pass")
1


Any idea how I can either auth after picking the database or once I use the db it remembers the context I dialed with?







python mongodb pymongo






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '17 at 0:44









Neil Lunn

97.9k23174184




97.9k23174184










asked Nov 12 '17 at 20:27









DeadSupraDeadSupra

738




738













  • The intent is that ALL authentication is stored in "admin" and simply identifies which database namespaces the account has the available privileges. So you would assign privelages on to the user for "mydb", but there is no such requirement that you "log in" on that database alone. It simply means that if you switch to "foo" database namespace where there are no assigned privileges, then you "cannot do anything". If you had privileges for "both" database namespaces, then you are allowed access to things without the need to "authenticate" again. Is that somewhat clearer?

    – Neil Lunn
    Nov 12 '17 at 20:34













  • I initially thought that was how it worked. For example, without using a database, I created my mongo user with all privileges in admin with literally every possible access and another user with just read access. I would then auth (still in admin) with that main account. Then switch and use "mydb" and when I "show users" in mydb, nothing shows. So I thought I had to recreate the account in mydb and give access.

    – DeadSupra
    Nov 12 '17 at 23:50











  • Is there something in the provided answer that you believe does not address your question? If so then please comment on the answer to clarify what exactly needs to be addressed that has not. If it does in fact answer the question you asked then please note to Accept your Answers to the questions you ask

    – Neil Lunn
    Nov 16 '17 at 5:28











  • It does. It makes sense to me because that is how I expected it to work the first time and I realized I created separate users within the same database. However, when I try to create a new user in admin I still can't use d.auth() to login in the database I am using. (I'm using just shell at this point since I realized it was never pymongo that had the issue). I believe I may have to reinstall mongo and start clean since I keep messing with the users, config, etc.

    – DeadSupra
    Nov 16 '17 at 6:39











  • You are given a clean case which is showing startup of clean database and reproducible steps for the purpose that you can run and replicate ans see what the correct process is. Once you can see what the correct process is and the answer addresses what was actually asked, then the process here is to "accept the answer" in order to indicate it's correctness to others viewing the question and it's answer.

    – Neil Lunn
    Nov 16 '17 at 6:46



















  • The intent is that ALL authentication is stored in "admin" and simply identifies which database namespaces the account has the available privileges. So you would assign privelages on to the user for "mydb", but there is no such requirement that you "log in" on that database alone. It simply means that if you switch to "foo" database namespace where there are no assigned privileges, then you "cannot do anything". If you had privileges for "both" database namespaces, then you are allowed access to things without the need to "authenticate" again. Is that somewhat clearer?

    – Neil Lunn
    Nov 12 '17 at 20:34













  • I initially thought that was how it worked. For example, without using a database, I created my mongo user with all privileges in admin with literally every possible access and another user with just read access. I would then auth (still in admin) with that main account. Then switch and use "mydb" and when I "show users" in mydb, nothing shows. So I thought I had to recreate the account in mydb and give access.

    – DeadSupra
    Nov 12 '17 at 23:50











  • Is there something in the provided answer that you believe does not address your question? If so then please comment on the answer to clarify what exactly needs to be addressed that has not. If it does in fact answer the question you asked then please note to Accept your Answers to the questions you ask

    – Neil Lunn
    Nov 16 '17 at 5:28











  • It does. It makes sense to me because that is how I expected it to work the first time and I realized I created separate users within the same database. However, when I try to create a new user in admin I still can't use d.auth() to login in the database I am using. (I'm using just shell at this point since I realized it was never pymongo that had the issue). I believe I may have to reinstall mongo and start clean since I keep messing with the users, config, etc.

    – DeadSupra
    Nov 16 '17 at 6:39











  • You are given a clean case which is showing startup of clean database and reproducible steps for the purpose that you can run and replicate ans see what the correct process is. Once you can see what the correct process is and the answer addresses what was actually asked, then the process here is to "accept the answer" in order to indicate it's correctness to others viewing the question and it's answer.

    – Neil Lunn
    Nov 16 '17 at 6:46

















The intent is that ALL authentication is stored in "admin" and simply identifies which database namespaces the account has the available privileges. So you would assign privelages on to the user for "mydb", but there is no such requirement that you "log in" on that database alone. It simply means that if you switch to "foo" database namespace where there are no assigned privileges, then you "cannot do anything". If you had privileges for "both" database namespaces, then you are allowed access to things without the need to "authenticate" again. Is that somewhat clearer?

– Neil Lunn
Nov 12 '17 at 20:34







The intent is that ALL authentication is stored in "admin" and simply identifies which database namespaces the account has the available privileges. So you would assign privelages on to the user for "mydb", but there is no such requirement that you "log in" on that database alone. It simply means that if you switch to "foo" database namespace where there are no assigned privileges, then you "cannot do anything". If you had privileges for "both" database namespaces, then you are allowed access to things without the need to "authenticate" again. Is that somewhat clearer?

– Neil Lunn
Nov 12 '17 at 20:34















I initially thought that was how it worked. For example, without using a database, I created my mongo user with all privileges in admin with literally every possible access and another user with just read access. I would then auth (still in admin) with that main account. Then switch and use "mydb" and when I "show users" in mydb, nothing shows. So I thought I had to recreate the account in mydb and give access.

– DeadSupra
Nov 12 '17 at 23:50





I initially thought that was how it worked. For example, without using a database, I created my mongo user with all privileges in admin with literally every possible access and another user with just read access. I would then auth (still in admin) with that main account. Then switch and use "mydb" and when I "show users" in mydb, nothing shows. So I thought I had to recreate the account in mydb and give access.

– DeadSupra
Nov 12 '17 at 23:50













Is there something in the provided answer that you believe does not address your question? If so then please comment on the answer to clarify what exactly needs to be addressed that has not. If it does in fact answer the question you asked then please note to Accept your Answers to the questions you ask

– Neil Lunn
Nov 16 '17 at 5:28





Is there something in the provided answer that you believe does not address your question? If so then please comment on the answer to clarify what exactly needs to be addressed that has not. If it does in fact answer the question you asked then please note to Accept your Answers to the questions you ask

– Neil Lunn
Nov 16 '17 at 5:28













It does. It makes sense to me because that is how I expected it to work the first time and I realized I created separate users within the same database. However, when I try to create a new user in admin I still can't use d.auth() to login in the database I am using. (I'm using just shell at this point since I realized it was never pymongo that had the issue). I believe I may have to reinstall mongo and start clean since I keep messing with the users, config, etc.

– DeadSupra
Nov 16 '17 at 6:39





It does. It makes sense to me because that is how I expected it to work the first time and I realized I created separate users within the same database. However, when I try to create a new user in admin I still can't use d.auth() to login in the database I am using. (I'm using just shell at this point since I realized it was never pymongo that had the issue). I believe I may have to reinstall mongo and start clean since I keep messing with the users, config, etc.

– DeadSupra
Nov 16 '17 at 6:39













You are given a clean case which is showing startup of clean database and reproducible steps for the purpose that you can run and replicate ans see what the correct process is. Once you can see what the correct process is and the answer addresses what was actually asked, then the process here is to "accept the answer" in order to indicate it's correctness to others viewing the question and it's answer.

– Neil Lunn
Nov 16 '17 at 6:46





You are given a clean case which is showing startup of clean database and reproducible steps for the purpose that you can run and replicate ans see what the correct process is. Once you can see what the correct process is and the answer addresses what was actually asked, then the process here is to "accept the answer" in order to indicate it's correctness to others viewing the question and it's answer.

– Neil Lunn
Nov 16 '17 at 6:46












1 Answer
1






active

oldest

votes


















1














You seem to be missing some concepts here so I'll basically answer as a "guide" to what you should be doing instead. So "authentication' is not really something you do "after" connection, but rather you need to be "looking in the right place" when you actually attempt to authenticate.



We can start this by essentially following the process outlined in Enable Auth from the core documentation, but specifically altered because you want to be running this "test" under your own user account and local directory.



Revision Steps - Straight from Documentation



So first would would want to pick a local working directory and make a path for the database storage files underneath that. On *nix based systems you can do something like:



mkdir -p scratch/data/db
cd scratch


Then we want to startup a separate MongoDB instance without any other options. Making sure the port does not conflict with any other running instance:



mongod --port 37017 --dbpath data/db


In a new terminal or command line window, you can then connect to the shell:



mongo --port 37017


You always want at least one account with administrative privileges to at least "create accounts" and alter them in case you get in trouble, so create one:



use admin
db.createUser(
{
user: "admin",
pwd: "admin",
roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
}
)


Now exit the shell and close the existing mongod instance running in the other terminal or command prompt and then start it again using --auth:



mongod --auth --port 37017 --dbpath data/db


Specific User - Make sure you follow these



Now you actually want to create a user that will be "used by your application". So these steps are important to ensure you get it right.



Log into a shell using your "adminstrative user":



mongo -u admin -p admin --port 37017 --authenticationDatabase 'admin'


You can alternately do the db.auth() method as shown in the question, but as noted this must be authorised on the "admin" namespace.



The next thing you want to do is create a user with access to "mydb" as a namespace with the readWrite role. For kicks, we are also going to let this user have the readAnyDatabase allowing them to "list" all databases namespaces, if not actually being able to do anything else with them.




IMPORTANT: You create ALL your users in the "admin" namespace. And this will be very important in future releases:




use admin
db.createUser(
{
"user": "myuser",
"pwd": "password",
"roles": [
{ "role": "readWrite", "db": "mydb" },
"readAnyDatabase"
]
}
)


Just for additional output, let's look at the current created users:



db.getUsers()
[
{
"_id" : "admin.admin",
"user" : "admin",
"db" : "admin",
"roles" : [
{
"role" : "userAdminAnyDatabase",
"db" : "admin"
}
]
},
{
"_id" : "admin.myuser",
"user" : "myuser",
"db" : "admin",
"roles" : [
{
"role" : "readWrite",
"db" : "mydb"
},
{
"role" : "readAnyDatabase",
"db" : "admin"
}
]
}
]


See how these have expanded in naming, and particularly the values assigned to the various "db" keys on each user. This should give you a little more insight into how MongoDB looks this up and why.



Python Connection



Finally we just want to connect from python. So presuming you have python and pymongo installed already, then it's just a simple listing to verify:



import pymongo
from pymongo import MongoClient
client = MongoClient('mongodb://myuser:password@localhost:37017');

db = client['mydb']
col = db.test

col.remove()

col.insert_one({ "a": 1 })

for doc in col.find():
print(doc)


Which shows the document created and listed without problem:



{u'a': 1, u'_id': ObjectId('5a08e5e0760108251722a737')}


Note that we don't actually need to make any mention of "admin" here, because this is the default where the driver "expects the accounts to be" and where you really "should" be doing it.



But I did it the wrong way



So let's say you originally got all confused and created the user under "mydb" instead:



use mydb
db.createUser({ "user": "bert", "pwd": "password", "roles": ["readWrite"] })


If you go look in "admin" that user is not there. But if you look on "mydb":



use mydb
db.getUsers()
[
{
"_id" : "mydb.bert",
"user" : "bert",
"db" : "mydb",
"roles" : [
{
"role" : "readWrite",
"db" : "mydb"
}
]
}
]


So you can see where the actual user data is now kept and how it has been recorded.



The simple case here is you "must" tell MongoDB where to obtain the authentication from for this user:



client = MongoClient('mongodb://bert:password@localhost:37017/mydb');


See how we add "mydb" on to the connection string. This is how it's done.





This is actually "in progress" to be made consistent with ALL drivers in how connections are made and where authentication happens as well as where you select the database. But there are basic rules:




  1. If no other database namespace is provided with connection details for authentication credentials, then "admin" is taken to be the default.


  2. Where there is a database namespace provided on the connection string, this will be used for authentication and this is the actual intent of the database namespace on the connection string.


  3. Though other drivers "presently" differ in the role of the database namespace on the connection string, the usage is being changed to be consistent with all drivers that "using" a database namespace is in fact an API call, rather than being assigned from the connection string.



So where you need to authenticate depends on "where you created the user". But you should really be noting that "admin" is the place where you "should" be doing this instead of anywhere else.




Deprecation of Authenticate after connect



Whilst all drivers actually do have a similar method to authenticate(), which is used much like the shell example in the question, this method is now considered DEPRECATED as is mentioned throughout the content of the answer it is "intended" that you actually store your users in the "admin" namespace:



"Changed in version 3.5: Deprecated. Authenticating multiple users conflicts with support for logical sessions in MongoDB 3.6. To authenticate as multiple users, create multiple instances of MongoClient."



This is why the whole answer here is based on NOT using that method as you are meant to creating new connection instances, or using the "sessions" functionality available from MongoDB 3.6 instead.







share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f47253584%2fauthenticate-after-picking-the-database%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    1














    You seem to be missing some concepts here so I'll basically answer as a "guide" to what you should be doing instead. So "authentication' is not really something you do "after" connection, but rather you need to be "looking in the right place" when you actually attempt to authenticate.



    We can start this by essentially following the process outlined in Enable Auth from the core documentation, but specifically altered because you want to be running this "test" under your own user account and local directory.



    Revision Steps - Straight from Documentation



    So first would would want to pick a local working directory and make a path for the database storage files underneath that. On *nix based systems you can do something like:



    mkdir -p scratch/data/db
    cd scratch


    Then we want to startup a separate MongoDB instance without any other options. Making sure the port does not conflict with any other running instance:



    mongod --port 37017 --dbpath data/db


    In a new terminal or command line window, you can then connect to the shell:



    mongo --port 37017


    You always want at least one account with administrative privileges to at least "create accounts" and alter them in case you get in trouble, so create one:



    use admin
    db.createUser(
    {
    user: "admin",
    pwd: "admin",
    roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
    }
    )


    Now exit the shell and close the existing mongod instance running in the other terminal or command prompt and then start it again using --auth:



    mongod --auth --port 37017 --dbpath data/db


    Specific User - Make sure you follow these



    Now you actually want to create a user that will be "used by your application". So these steps are important to ensure you get it right.



    Log into a shell using your "adminstrative user":



    mongo -u admin -p admin --port 37017 --authenticationDatabase 'admin'


    You can alternately do the db.auth() method as shown in the question, but as noted this must be authorised on the "admin" namespace.



    The next thing you want to do is create a user with access to "mydb" as a namespace with the readWrite role. For kicks, we are also going to let this user have the readAnyDatabase allowing them to "list" all databases namespaces, if not actually being able to do anything else with them.




    IMPORTANT: You create ALL your users in the "admin" namespace. And this will be very important in future releases:




    use admin
    db.createUser(
    {
    "user": "myuser",
    "pwd": "password",
    "roles": [
    { "role": "readWrite", "db": "mydb" },
    "readAnyDatabase"
    ]
    }
    )


    Just for additional output, let's look at the current created users:



    db.getUsers()
    [
    {
    "_id" : "admin.admin",
    "user" : "admin",
    "db" : "admin",
    "roles" : [
    {
    "role" : "userAdminAnyDatabase",
    "db" : "admin"
    }
    ]
    },
    {
    "_id" : "admin.myuser",
    "user" : "myuser",
    "db" : "admin",
    "roles" : [
    {
    "role" : "readWrite",
    "db" : "mydb"
    },
    {
    "role" : "readAnyDatabase",
    "db" : "admin"
    }
    ]
    }
    ]


    See how these have expanded in naming, and particularly the values assigned to the various "db" keys on each user. This should give you a little more insight into how MongoDB looks this up and why.



    Python Connection



    Finally we just want to connect from python. So presuming you have python and pymongo installed already, then it's just a simple listing to verify:



    import pymongo
    from pymongo import MongoClient
    client = MongoClient('mongodb://myuser:password@localhost:37017');

    db = client['mydb']
    col = db.test

    col.remove()

    col.insert_one({ "a": 1 })

    for doc in col.find():
    print(doc)


    Which shows the document created and listed without problem:



    {u'a': 1, u'_id': ObjectId('5a08e5e0760108251722a737')}


    Note that we don't actually need to make any mention of "admin" here, because this is the default where the driver "expects the accounts to be" and where you really "should" be doing it.



    But I did it the wrong way



    So let's say you originally got all confused and created the user under "mydb" instead:



    use mydb
    db.createUser({ "user": "bert", "pwd": "password", "roles": ["readWrite"] })


    If you go look in "admin" that user is not there. But if you look on "mydb":



    use mydb
    db.getUsers()
    [
    {
    "_id" : "mydb.bert",
    "user" : "bert",
    "db" : "mydb",
    "roles" : [
    {
    "role" : "readWrite",
    "db" : "mydb"
    }
    ]
    }
    ]


    So you can see where the actual user data is now kept and how it has been recorded.



    The simple case here is you "must" tell MongoDB where to obtain the authentication from for this user:



    client = MongoClient('mongodb://bert:password@localhost:37017/mydb');


    See how we add "mydb" on to the connection string. This is how it's done.





    This is actually "in progress" to be made consistent with ALL drivers in how connections are made and where authentication happens as well as where you select the database. But there are basic rules:




    1. If no other database namespace is provided with connection details for authentication credentials, then "admin" is taken to be the default.


    2. Where there is a database namespace provided on the connection string, this will be used for authentication and this is the actual intent of the database namespace on the connection string.


    3. Though other drivers "presently" differ in the role of the database namespace on the connection string, the usage is being changed to be consistent with all drivers that "using" a database namespace is in fact an API call, rather than being assigned from the connection string.



    So where you need to authenticate depends on "where you created the user". But you should really be noting that "admin" is the place where you "should" be doing this instead of anywhere else.




    Deprecation of Authenticate after connect



    Whilst all drivers actually do have a similar method to authenticate(), which is used much like the shell example in the question, this method is now considered DEPRECATED as is mentioned throughout the content of the answer it is "intended" that you actually store your users in the "admin" namespace:



    "Changed in version 3.5: Deprecated. Authenticating multiple users conflicts with support for logical sessions in MongoDB 3.6. To authenticate as multiple users, create multiple instances of MongoClient."



    This is why the whole answer here is based on NOT using that method as you are meant to creating new connection instances, or using the "sessions" functionality available from MongoDB 3.6 instead.







    share|improve this answer






























      1














      You seem to be missing some concepts here so I'll basically answer as a "guide" to what you should be doing instead. So "authentication' is not really something you do "after" connection, but rather you need to be "looking in the right place" when you actually attempt to authenticate.



      We can start this by essentially following the process outlined in Enable Auth from the core documentation, but specifically altered because you want to be running this "test" under your own user account and local directory.



      Revision Steps - Straight from Documentation



      So first would would want to pick a local working directory and make a path for the database storage files underneath that. On *nix based systems you can do something like:



      mkdir -p scratch/data/db
      cd scratch


      Then we want to startup a separate MongoDB instance without any other options. Making sure the port does not conflict with any other running instance:



      mongod --port 37017 --dbpath data/db


      In a new terminal or command line window, you can then connect to the shell:



      mongo --port 37017


      You always want at least one account with administrative privileges to at least "create accounts" and alter them in case you get in trouble, so create one:



      use admin
      db.createUser(
      {
      user: "admin",
      pwd: "admin",
      roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
      }
      )


      Now exit the shell and close the existing mongod instance running in the other terminal or command prompt and then start it again using --auth:



      mongod --auth --port 37017 --dbpath data/db


      Specific User - Make sure you follow these



      Now you actually want to create a user that will be "used by your application". So these steps are important to ensure you get it right.



      Log into a shell using your "adminstrative user":



      mongo -u admin -p admin --port 37017 --authenticationDatabase 'admin'


      You can alternately do the db.auth() method as shown in the question, but as noted this must be authorised on the "admin" namespace.



      The next thing you want to do is create a user with access to "mydb" as a namespace with the readWrite role. For kicks, we are also going to let this user have the readAnyDatabase allowing them to "list" all databases namespaces, if not actually being able to do anything else with them.




      IMPORTANT: You create ALL your users in the "admin" namespace. And this will be very important in future releases:




      use admin
      db.createUser(
      {
      "user": "myuser",
      "pwd": "password",
      "roles": [
      { "role": "readWrite", "db": "mydb" },
      "readAnyDatabase"
      ]
      }
      )


      Just for additional output, let's look at the current created users:



      db.getUsers()
      [
      {
      "_id" : "admin.admin",
      "user" : "admin",
      "db" : "admin",
      "roles" : [
      {
      "role" : "userAdminAnyDatabase",
      "db" : "admin"
      }
      ]
      },
      {
      "_id" : "admin.myuser",
      "user" : "myuser",
      "db" : "admin",
      "roles" : [
      {
      "role" : "readWrite",
      "db" : "mydb"
      },
      {
      "role" : "readAnyDatabase",
      "db" : "admin"
      }
      ]
      }
      ]


      See how these have expanded in naming, and particularly the values assigned to the various "db" keys on each user. This should give you a little more insight into how MongoDB looks this up and why.



      Python Connection



      Finally we just want to connect from python. So presuming you have python and pymongo installed already, then it's just a simple listing to verify:



      import pymongo
      from pymongo import MongoClient
      client = MongoClient('mongodb://myuser:password@localhost:37017');

      db = client['mydb']
      col = db.test

      col.remove()

      col.insert_one({ "a": 1 })

      for doc in col.find():
      print(doc)


      Which shows the document created and listed without problem:



      {u'a': 1, u'_id': ObjectId('5a08e5e0760108251722a737')}


      Note that we don't actually need to make any mention of "admin" here, because this is the default where the driver "expects the accounts to be" and where you really "should" be doing it.



      But I did it the wrong way



      So let's say you originally got all confused and created the user under "mydb" instead:



      use mydb
      db.createUser({ "user": "bert", "pwd": "password", "roles": ["readWrite"] })


      If you go look in "admin" that user is not there. But if you look on "mydb":



      use mydb
      db.getUsers()
      [
      {
      "_id" : "mydb.bert",
      "user" : "bert",
      "db" : "mydb",
      "roles" : [
      {
      "role" : "readWrite",
      "db" : "mydb"
      }
      ]
      }
      ]


      So you can see where the actual user data is now kept and how it has been recorded.



      The simple case here is you "must" tell MongoDB where to obtain the authentication from for this user:



      client = MongoClient('mongodb://bert:password@localhost:37017/mydb');


      See how we add "mydb" on to the connection string. This is how it's done.





      This is actually "in progress" to be made consistent with ALL drivers in how connections are made and where authentication happens as well as where you select the database. But there are basic rules:




      1. If no other database namespace is provided with connection details for authentication credentials, then "admin" is taken to be the default.


      2. Where there is a database namespace provided on the connection string, this will be used for authentication and this is the actual intent of the database namespace on the connection string.


      3. Though other drivers "presently" differ in the role of the database namespace on the connection string, the usage is being changed to be consistent with all drivers that "using" a database namespace is in fact an API call, rather than being assigned from the connection string.



      So where you need to authenticate depends on "where you created the user". But you should really be noting that "admin" is the place where you "should" be doing this instead of anywhere else.




      Deprecation of Authenticate after connect



      Whilst all drivers actually do have a similar method to authenticate(), which is used much like the shell example in the question, this method is now considered DEPRECATED as is mentioned throughout the content of the answer it is "intended" that you actually store your users in the "admin" namespace:



      "Changed in version 3.5: Deprecated. Authenticating multiple users conflicts with support for logical sessions in MongoDB 3.6. To authenticate as multiple users, create multiple instances of MongoClient."



      This is why the whole answer here is based on NOT using that method as you are meant to creating new connection instances, or using the "sessions" functionality available from MongoDB 3.6 instead.







      share|improve this answer




























        1












        1








        1







        You seem to be missing some concepts here so I'll basically answer as a "guide" to what you should be doing instead. So "authentication' is not really something you do "after" connection, but rather you need to be "looking in the right place" when you actually attempt to authenticate.



        We can start this by essentially following the process outlined in Enable Auth from the core documentation, but specifically altered because you want to be running this "test" under your own user account and local directory.



        Revision Steps - Straight from Documentation



        So first would would want to pick a local working directory and make a path for the database storage files underneath that. On *nix based systems you can do something like:



        mkdir -p scratch/data/db
        cd scratch


        Then we want to startup a separate MongoDB instance without any other options. Making sure the port does not conflict with any other running instance:



        mongod --port 37017 --dbpath data/db


        In a new terminal or command line window, you can then connect to the shell:



        mongo --port 37017


        You always want at least one account with administrative privileges to at least "create accounts" and alter them in case you get in trouble, so create one:



        use admin
        db.createUser(
        {
        user: "admin",
        pwd: "admin",
        roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
        }
        )


        Now exit the shell and close the existing mongod instance running in the other terminal or command prompt and then start it again using --auth:



        mongod --auth --port 37017 --dbpath data/db


        Specific User - Make sure you follow these



        Now you actually want to create a user that will be "used by your application". So these steps are important to ensure you get it right.



        Log into a shell using your "adminstrative user":



        mongo -u admin -p admin --port 37017 --authenticationDatabase 'admin'


        You can alternately do the db.auth() method as shown in the question, but as noted this must be authorised on the "admin" namespace.



        The next thing you want to do is create a user with access to "mydb" as a namespace with the readWrite role. For kicks, we are also going to let this user have the readAnyDatabase allowing them to "list" all databases namespaces, if not actually being able to do anything else with them.




        IMPORTANT: You create ALL your users in the "admin" namespace. And this will be very important in future releases:




        use admin
        db.createUser(
        {
        "user": "myuser",
        "pwd": "password",
        "roles": [
        { "role": "readWrite", "db": "mydb" },
        "readAnyDatabase"
        ]
        }
        )


        Just for additional output, let's look at the current created users:



        db.getUsers()
        [
        {
        "_id" : "admin.admin",
        "user" : "admin",
        "db" : "admin",
        "roles" : [
        {
        "role" : "userAdminAnyDatabase",
        "db" : "admin"
        }
        ]
        },
        {
        "_id" : "admin.myuser",
        "user" : "myuser",
        "db" : "admin",
        "roles" : [
        {
        "role" : "readWrite",
        "db" : "mydb"
        },
        {
        "role" : "readAnyDatabase",
        "db" : "admin"
        }
        ]
        }
        ]


        See how these have expanded in naming, and particularly the values assigned to the various "db" keys on each user. This should give you a little more insight into how MongoDB looks this up and why.



        Python Connection



        Finally we just want to connect from python. So presuming you have python and pymongo installed already, then it's just a simple listing to verify:



        import pymongo
        from pymongo import MongoClient
        client = MongoClient('mongodb://myuser:password@localhost:37017');

        db = client['mydb']
        col = db.test

        col.remove()

        col.insert_one({ "a": 1 })

        for doc in col.find():
        print(doc)


        Which shows the document created and listed without problem:



        {u'a': 1, u'_id': ObjectId('5a08e5e0760108251722a737')}


        Note that we don't actually need to make any mention of "admin" here, because this is the default where the driver "expects the accounts to be" and where you really "should" be doing it.



        But I did it the wrong way



        So let's say you originally got all confused and created the user under "mydb" instead:



        use mydb
        db.createUser({ "user": "bert", "pwd": "password", "roles": ["readWrite"] })


        If you go look in "admin" that user is not there. But if you look on "mydb":



        use mydb
        db.getUsers()
        [
        {
        "_id" : "mydb.bert",
        "user" : "bert",
        "db" : "mydb",
        "roles" : [
        {
        "role" : "readWrite",
        "db" : "mydb"
        }
        ]
        }
        ]


        So you can see where the actual user data is now kept and how it has been recorded.



        The simple case here is you "must" tell MongoDB where to obtain the authentication from for this user:



        client = MongoClient('mongodb://bert:password@localhost:37017/mydb');


        See how we add "mydb" on to the connection string. This is how it's done.





        This is actually "in progress" to be made consistent with ALL drivers in how connections are made and where authentication happens as well as where you select the database. But there are basic rules:




        1. If no other database namespace is provided with connection details for authentication credentials, then "admin" is taken to be the default.


        2. Where there is a database namespace provided on the connection string, this will be used for authentication and this is the actual intent of the database namespace on the connection string.


        3. Though other drivers "presently" differ in the role of the database namespace on the connection string, the usage is being changed to be consistent with all drivers that "using" a database namespace is in fact an API call, rather than being assigned from the connection string.



        So where you need to authenticate depends on "where you created the user". But you should really be noting that "admin" is the place where you "should" be doing this instead of anywhere else.




        Deprecation of Authenticate after connect



        Whilst all drivers actually do have a similar method to authenticate(), which is used much like the shell example in the question, this method is now considered DEPRECATED as is mentioned throughout the content of the answer it is "intended" that you actually store your users in the "admin" namespace:



        "Changed in version 3.5: Deprecated. Authenticating multiple users conflicts with support for logical sessions in MongoDB 3.6. To authenticate as multiple users, create multiple instances of MongoClient."



        This is why the whole answer here is based on NOT using that method as you are meant to creating new connection instances, or using the "sessions" functionality available from MongoDB 3.6 instead.







        share|improve this answer















        You seem to be missing some concepts here so I'll basically answer as a "guide" to what you should be doing instead. So "authentication' is not really something you do "after" connection, but rather you need to be "looking in the right place" when you actually attempt to authenticate.



        We can start this by essentially following the process outlined in Enable Auth from the core documentation, but specifically altered because you want to be running this "test" under your own user account and local directory.



        Revision Steps - Straight from Documentation



        So first would would want to pick a local working directory and make a path for the database storage files underneath that. On *nix based systems you can do something like:



        mkdir -p scratch/data/db
        cd scratch


        Then we want to startup a separate MongoDB instance without any other options. Making sure the port does not conflict with any other running instance:



        mongod --port 37017 --dbpath data/db


        In a new terminal or command line window, you can then connect to the shell:



        mongo --port 37017


        You always want at least one account with administrative privileges to at least "create accounts" and alter them in case you get in trouble, so create one:



        use admin
        db.createUser(
        {
        user: "admin",
        pwd: "admin",
        roles: [{ role: "userAdminAnyDatabase", db: "admin" }]
        }
        )


        Now exit the shell and close the existing mongod instance running in the other terminal or command prompt and then start it again using --auth:



        mongod --auth --port 37017 --dbpath data/db


        Specific User - Make sure you follow these



        Now you actually want to create a user that will be "used by your application". So these steps are important to ensure you get it right.



        Log into a shell using your "adminstrative user":



        mongo -u admin -p admin --port 37017 --authenticationDatabase 'admin'


        You can alternately do the db.auth() method as shown in the question, but as noted this must be authorised on the "admin" namespace.



        The next thing you want to do is create a user with access to "mydb" as a namespace with the readWrite role. For kicks, we are also going to let this user have the readAnyDatabase allowing them to "list" all databases namespaces, if not actually being able to do anything else with them.




        IMPORTANT: You create ALL your users in the "admin" namespace. And this will be very important in future releases:




        use admin
        db.createUser(
        {
        "user": "myuser",
        "pwd": "password",
        "roles": [
        { "role": "readWrite", "db": "mydb" },
        "readAnyDatabase"
        ]
        }
        )


        Just for additional output, let's look at the current created users:



        db.getUsers()
        [
        {
        "_id" : "admin.admin",
        "user" : "admin",
        "db" : "admin",
        "roles" : [
        {
        "role" : "userAdminAnyDatabase",
        "db" : "admin"
        }
        ]
        },
        {
        "_id" : "admin.myuser",
        "user" : "myuser",
        "db" : "admin",
        "roles" : [
        {
        "role" : "readWrite",
        "db" : "mydb"
        },
        {
        "role" : "readAnyDatabase",
        "db" : "admin"
        }
        ]
        }
        ]


        See how these have expanded in naming, and particularly the values assigned to the various "db" keys on each user. This should give you a little more insight into how MongoDB looks this up and why.



        Python Connection



        Finally we just want to connect from python. So presuming you have python and pymongo installed already, then it's just a simple listing to verify:



        import pymongo
        from pymongo import MongoClient
        client = MongoClient('mongodb://myuser:password@localhost:37017');

        db = client['mydb']
        col = db.test

        col.remove()

        col.insert_one({ "a": 1 })

        for doc in col.find():
        print(doc)


        Which shows the document created and listed without problem:



        {u'a': 1, u'_id': ObjectId('5a08e5e0760108251722a737')}


        Note that we don't actually need to make any mention of "admin" here, because this is the default where the driver "expects the accounts to be" and where you really "should" be doing it.



        But I did it the wrong way



        So let's say you originally got all confused and created the user under "mydb" instead:



        use mydb
        db.createUser({ "user": "bert", "pwd": "password", "roles": ["readWrite"] })


        If you go look in "admin" that user is not there. But if you look on "mydb":



        use mydb
        db.getUsers()
        [
        {
        "_id" : "mydb.bert",
        "user" : "bert",
        "db" : "mydb",
        "roles" : [
        {
        "role" : "readWrite",
        "db" : "mydb"
        }
        ]
        }
        ]


        So you can see where the actual user data is now kept and how it has been recorded.



        The simple case here is you "must" tell MongoDB where to obtain the authentication from for this user:



        client = MongoClient('mongodb://bert:password@localhost:37017/mydb');


        See how we add "mydb" on to the connection string. This is how it's done.





        This is actually "in progress" to be made consistent with ALL drivers in how connections are made and where authentication happens as well as where you select the database. But there are basic rules:




        1. If no other database namespace is provided with connection details for authentication credentials, then "admin" is taken to be the default.


        2. Where there is a database namespace provided on the connection string, this will be used for authentication and this is the actual intent of the database namespace on the connection string.


        3. Though other drivers "presently" differ in the role of the database namespace on the connection string, the usage is being changed to be consistent with all drivers that "using" a database namespace is in fact an API call, rather than being assigned from the connection string.



        So where you need to authenticate depends on "where you created the user". But you should really be noting that "admin" is the place where you "should" be doing this instead of anywhere else.




        Deprecation of Authenticate after connect



        Whilst all drivers actually do have a similar method to authenticate(), which is used much like the shell example in the question, this method is now considered DEPRECATED as is mentioned throughout the content of the answer it is "intended" that you actually store your users in the "admin" namespace:



        "Changed in version 3.5: Deprecated. Authenticating multiple users conflicts with support for logical sessions in MongoDB 3.6. To authenticate as multiple users, create multiple instances of MongoClient."



        This is why the whole answer here is based on NOT using that method as you are meant to creating new connection instances, or using the "sessions" functionality available from MongoDB 3.6 instead.








        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 13 '17 at 2:48

























        answered Nov 13 '17 at 0:43









        Neil LunnNeil Lunn

        97.9k23174184




        97.9k23174184






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f47253584%2fauthenticate-after-picking-the-database%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            List item for chat from Array inside array React Native

            Jo Brand

            Thiostrepton