"Login failed" connecting to SQL-Azure from node.js (msnodesql) - node.js

I followed the tutorial here for building a node.js website on Azure that connects to a SQL-Azure DB:
http://www.windowsazure.com/en-us/develop/nodejs/tutorials/web-site-with-sql-database/
Here's what my .js code looks like:
var sql = require('msnodesql'),
nconf = require('nconf');
exports.authenticate = function(req, res){
var select = "select userID, clientID from users where username_e = '?' AND pwd_e = '?'";
nconf.env().file({ file: 'config.json' });
var conn = nconf.get("SQL_CONN");
console.log(conn);
sql.query(conn, select, [req.param('username'), req.param('password')], function(err, results) {
if(err)
throw err;
console.log(results);
if(results.length == 0) {
// no match
res.redirect('/login?failed=true');
} else {
// authenticated
res.redirect('/start');
}
});
return;
};
But when I run it on my local node.js, I keep getting
"Login failed for user 'mylogin'"
I copied the ODBC connection string directly from the Azure management
site
I replaced {your password here} with my password
I quadruple-checked the username and password are correct (I can successfully log into the management tools, AND I can connect to the DB fine via SQL Server Management Studio from my local)
I added an IP exception for my public IP address for good measure
I tried editing the connection string here and there (changed username to mylogin instead of mylogin#server, tried using the ADO connection string instead)
I ALSO was able to connect successfully in Java using jdbc. Here's the jdbc connection string that worked:
jdbc:sqlserver://xxxmyserver.database.windows.net:1433;DatabaseName=mydb;user=mylogin#xxxmyserver;password=pwd
And here's the node.js ODBC connection string that does not work:
Driver={SQL Server Native Client 10.0};Server=tcp:xxxmyserver.database.windows.net,1433;Database=[mydb];Uid=mylogin#xxxmyserver;Pwd=pwd;Encrypt=yes;Connection Timeout=30;
I am just completely at a loss here, especially since I can connect fine from my local using SSMS. Anyone else run into the same issue?
In case it matters, I am using node.js v0.8.2 (since that's what's on Azure's VMs) and msnodesql v0.2.1

To anyone else stumbling across this and still getting the problem even after taking out the square brackets, there's a flag you need to set in the Azure management portal to enable other Azure services to connect to your Azure SQL database. To add confusion, when you first create it, it adds your IP address to the list, which is why you seem to be able to connect to it fine from your dev machine but not from your Azure instance.
Anyway, to do this, go into the database's settings in your Azure management portal, go to 'allowed IP addresses' and enable 'Windows Azure Services' under allowed services at the bottom.

Try your query without the quotes around the question mark parameters.
var select = "select userID, clientID from users where username_e = ? AND pwd_e = ?";
Quotes are not needed for string (or any type of) parameters. Parameters are sent out of band rather than substituted directly into the query. This is what makes them so much more secure, since they are never evaluated with the SQL.

The problem was with the Database section of my connection string - the square brackets around the database name were causing the problem. The ODBC connection string Azure tells you to use looks like this:
Driver={SQL Server Native Client 10.0};Server=tcp:xxxmyserver.database.windows.net,1433;Database=[mydb];Uid=mylogin#xxxmyserver;Pwd=pwd;Encrypt=yes;Connection Timeout=30;
When instead you need to use this:
Driver={SQL Server Native Client 10.0};Server=tcp:xxxmyserver.database.windows.net,1433;Database=mydb;Uid=mylogin#xxxmyserver;Pwd=pwd;Encrypt=yes;Connection Timeout=30;
Note the lack in square brackets around the database name.
This looks like it's a bug in Azure's management tool that will hopefully go away soon. Hope this saves someone else several hours of debugging.

Related

Getting 'Could not find stored procedure' error calling SQL Server stored procedure in Node JS from AWS RDS database

We always normally work in Azure where I write around 200 stored procedures a year in their SQL Server database.
We had to create a SQL Server database in AWS-RDS and still call it in our Node APIs like usual. I was able to quickly and easily set up the AWS DB in SQL Server Management Studio so I do know the credentials.
I created several tables and several stored procedures with no problems and tested to make sure they worked there. When I called them like I normally do in Node, I found I was getting an error
Could not find stored procedure
I went through forums all over but most of the data pertains to MySQL instead of SQL Server, and after trying everything I saw in the forums have not been able to complete what should be a very simple process. I would imagine there is some simple thing I missed, but after 2 days it is time for some fresh ideas.
I am setting up the credentials like this:
var awsConnection = {
host : process.env.RDS_HOSTNAME,
user : process.env.RDS_USERNAME,
password : process.env.RDS_PASSWORD,
port : process.env.RDS_PORT
};
I am using the endpoint provided by AWS for the host, the username and password I use to login to SQL Server Management Tool (which works). The port number is the one specified by AWS (1433 - the default for SQL Server).
I call it in my api like this:
await sql.connect(connectionAWS).then(pool => {
// Stored procedure
console.log("awsConnection INSIDE: " + JSON.stringify(awsConnection));
return pool.request()
.input('repId', sql.VARCHAR(40), repObj.RepID)
.execute('UserExistsBD');
}).then(async result => { ...
I added the console.log to see if we were getting past the login and it appears that we do. I also used Telnet to make sure the endpoint/port combo work and they do. I also checked AWS to make sure the Subnets, Route tables, and gateways were good and to make sure my IP Address was white listed. Any ideas would be very much appreciated!

Azure Function does not connect to Cosmos DB

I keep getting an error in application insight when trying to run my Azure function, it works locally on my computer but does not work in Azure. Here is the error message:
System.InvalidOperationException at Microsoft.Azure.WebJobs.Extensions.CosmosDB.CosmosDBTriggerAttributeBindingProvider.ResolveConnectionString
I have added CosmosDbTrigger as a connection string in the settings configurations, so I do not understand what's wrong. The function is triggered when a change is made in the cosmos db so if I change something in the db, and am running the function localy on my pc it works, It's only in the azure portal it keeps failing. The triggers are also working, so I think it's only the function that's the problem.
As there are many other discussions happening with similar issue from this link and check this link and try re checking your configuration file.
internal string ResolveConnectionString(string unresolvedConnectionString, string propertyName)
{
// First, resolve the string.
if (!string.IsNullOrEmpty(unresolvedConnectionString))
{
string resolvedString = _configuration.GetConnectionStringOrSetting(unresolvedConnectionString);
if (string.IsNullOrEmpty(resolvedString))
{
throw new InvalidOperationException($"Unable to resolve app setting for property '{nameof(CosmosDBTriggerAttribute)}.{propertyName}'. Make sure the app setting exists and has a valid value.");
}
return resolvedString;
}
// If that didn't exist, fall back to options.
return _options.ConnectionString;
}
Also, check your _options.ConnectionString value and set that dynamically.
builder.Services.PostConfigure<CosmosDBOptions>(options =>
{
options.ConnectionString = "dynamically set the connection string value here";
});

MongoDB Docker URI does not have hostname, domain name and tld

I am trying to connect to my local MongoDB Database that is on docker with nodejs. My component are:
.env file
MONGODB_USERNAME = 'accountUser'
MONGODB_PASSWORD = 'password'
MONGODB_HOST = 'mongodb'
MONGODB_DATABASE = 'mydb'
Code:
const uri = `mongodb+srv://${process.env.MONGODB_USERNAME}:${process.env.MONGODB_PASSWORD}#${process.env.MONGODB_HOST}/${process.env.MONGODB_DATABASE}?retryWrites=true&w=majority`;
console.log(uri);
const client = new MongoClient(uri);
Console Output
mongodb+srv://accountUser:abc123#mongodb/mydb?retryWrites=true&w=majority
Error
MongoParseError: URI does not have hostname, domain name and tld
What can I be doing wrong?
You are trying to use an SRV URI when you should be using an ordirary URI.
SRV URIs have the additional security requirements on hostnames (that it contains 3 components minimum).
Remove +srv from your URI.
1). Go to the database, click edit password and generate a new password.
2). Go to the database, click edit password and give only characters and numbers.
If the username or password includes the following characters:
: / ? # [ ] #
You should simply replace those characters.
How to connect to MongoDB Atlas from a NestJS Application:
Under Deployment select Databases
Click on your database instance
Next to the name and status of the instance click Connect
Click Connect your application
Under DRIVER select Node.js
Under VERSION select 2.2.12 or later
Copy the full URI including all of the individual nodes and use that to connect instead
As D. SM said earlier you can't use a URI with +srv in it and rolling back the driver version is the only way to get a connection string generated without +srv.

MongoDB custom user roles - "user is not allowed(...)"

I created a free tier cluster on MongoDB Atlas (it has 3 shards) and I want my Node.js app to connect with a database I created there, using a specific user, that will be restricted from using any other database than the one inteded for this app.
So step by step.
I create a database called, let's say, test.
I create a role here - I go to Security -> MongoDB Roles -> Add New Custom Role and I give it all Collection actions and all Database actions and roles to test
Time for a user, so again Security -> MongoDB Users -> Add New User and I assign a previously created role to it so it has access only to test database. So now I have 2 users - atlasAdmin and my created user.
That's where the problem occurs, when I use admin user in my app to connect, .find() or .create() it works fine all the time. With a user with custom role, it works for like 10mins/1 connection (until I shut down the local server I have my node app on) and the next time I get an error that "user is not allowed to perform action (...)".
I tried everything, tinkering with a string I use to connect, updating mongoose (I use it in my app), creating user and custom role using mongodb shell but nothing seems to work.
HOWEVER:
if I have this custom user, my app connects with it to the database and it works, then on the next connection it stops working AND I go here and just click UPDATE USER without changing anything there (I just click edit next to the user and then update) then wait for the cluster to make changes, it will work again for like +/- one connection.
everything works just fine if my app uses admin account
Anyone had similar problem? Screenshot of the error I was also thinking that it might be because of how many times I try to connect with mongo from the app (I use nodemon so everytime I save a file with changes, server restarts, thus connecting to database again) but I think that's not the case - if it was, why would I be able to make it work with admin user?
The string I use to connect with mongo:
// DATABASE SETUP
var dbURL = 'mongodb://[cluster0:port],[cluster1:port],[cluster2:port]/test?ssl=true&replicaSet=Cluster0-shard-0&authSource=admin&retryWrites=true';
var options = {
useNewUrlParser: true,
dbName: "test"
user: [login],
pass: [pass]
};
mongoose.connect(dbURL, options);
I have also encountered this problem on Atlas Free tier, not just on NodeJS but Java as well
For now, you can try mitigating this problem by using a default role instead of having a custom one
On the MongoDB Users tab, click "Edit" on your user => Add Default Privileges
Picture 1
Then select "readWrite" and type your database name on the first field, then save the user
Picture 2
Or, if you want database administration, add another field with "dbAdmin" role
Picture 3
At least that's how I solved it. I hope this helps.
Side note: You can also use the shorter connection string (MongoDB+SRV) and it would still work.

Access remote MongoDB database?

I've mostly worked with PHP/MySQL but I've now been handed a Node.js/MongoDB project on Github.
Having gone through a Mongo tutorial, I feel I understand the concept to a reasonable extent now, but I am still unsure how to do the most basic thing - view the Mongo database associated with the project.
In the config file, I found the following:
module.exports = {
database: {
url: 'localhost:27017/app_name'
},
But seeing how I'm on a remote machine, how do I reach the database? Do I need to ask the previous dev for the DB so I can set it up locally?
Searching the code for the word mongo it only appears in packages.json so that's not a lot of help.
localhost:27017
means the DB is in the local machine in which your are developing your app.
In your case, you have MONGO DB installed in your local machine and run the project.
Otherwise if you have a centralized DB then you have to configure that IP here as follows:
Also configure your mongodb.config of your remote DB to accept the connection from your local machine by changing the "BIND IP"
module.exports = {
database: {
url: 'yourRemoteIP:27017/app_name'
},
Use a GUI tool, i would recommend MongoChef. All you need to do is when you start the server, just open this GUI and connect to DB. GAME ON!! You will be able to see your collections and you are ready to go. You can also run mongo query direct on the shell. It is a helpful tool for playing with your local DB.
PS I am considering you want to see your local DB.
You can access your DB through terminal as well, all upto you.

Resources