Knex not able to connect with azure-active-directory-password - azure-active-directory

I have a project using Objection.js and Knex.
I am trying to connect to a database that is hosted in Azure and uses Azure Active Directory to authenticate.
objection: 3.0.1
knex: 2.2.0
My understanding is Knex uses Tedious to build the connection to the database. Looking into the github I am referencing this document for connection properties.
https://github.com/knex/knex/blob/master/lib/dialects/mssql/index.js
const cfg = {
authentication: {
type: settings.type || 'default',
options: {
userName: settings.userName || settings.user,
password: settings.password,
domain: settings.domain,
token: settings.token,
clientId: settings.clientId,
clientSecret: settings.clientSecret,
tenantId: settings.tenantId,
msiEndpoint: settings.msiEndpoint,
},
},
server: settings.server || settings.host,
options: {
database: settings.database,
encrypt: settings.encrypt || false,
port: settings.port || 1433,
connectTimeout: settings.connectionTimeout || settings.timeout || 15000,
requestTimeout: !isNil(settings.requestTimeout)
? settings.requestTimeout
: 15000,
rowCollectionOnDone: false,
rowCollectionOnRequestCompletion: false,
useColumnNames: false,
tdsVersion: settings.options.tdsVersion || '7_4',
appName: settings.options.appName || 'knex',
trustServerCertificate: false,
...settings.options,
},
};
Looking into Tedious it looks like the connection can be setup with these settings:
https://tediousjs.github.io/tedious/api-connection.html
I have followed various troubleshooting threads but none have worked for me and the errors I am getting are not helping.
Here are what I have as my Knex initialization.
const db = knex({
client: 'mssql'
useNullAsDefault: true,
connection: {
type: 'azure-active-directory-password',
server: 'sql-db.database.windows.net',
database: 'my-db',
user: 'myUser',
password: 'myPassword',
clientId: 'myUser-AzureAd-Object-Id',
tenantId: 'myTenantId',
encrypt: true,
...knexSnakeCaseMappers()
}
})
When I try to run my migrations I get the error:
AggregateError
at c:\path\node_modules\tedious\lib\connection.js:2759:31
at processTicksAndRejections (node:internal/process/task_queues:94:5)
While running the code normally, without applying the migration first I get this error.
this.loginError = new _esAggregateError.default([new _errors.ConnectionError('Security token could not be authenticated or authorized.', 'EFEDAUTH'), err]);
At this point I do not know why it is not connecting to the database. On the same machine I can connect to the database over SSMS using Azure Active Directory - Password and the same credentials I am passing in the knexfile.
I am lost as to why this is not connecting any help would be greatly appreciated.
FIXED: I had more of an issue with the logging of Knex, after using Tedious directly the error was a bit more clear.
The issue was related to the Client ID, it says it is going to be required, but when I provided it, it said it was incorrect. Removing the Client ID fixed the issue.

Related

App runs fine on heroku, except for one problem

I have an application that allows people to look up their government representatives using an address. When it is connected to a local mongo db it works perfectly. I am using the db to store like/dislikes on the reps page. The problem is that I added the documents in the db manually and so it doesn't/cant track likes on heroku, since the db isnt create dynamically in the code. That didn't seem like too much of a problem though. I would just create the exact same documents in Atlas db, right? Well here I am several hours later and Im pulling my hair out.
I have never used Atlas but it seems straightforward. Use their url to connected to your cluster/db. Thats about it from what I can tell. Problem is, I can get an empty array back from a return all route... and thats it. I have two docs in the db currently and need them to track my likes/dislikes. Im just not sure where to go from here and have to deploy this by tomorrow evening. Please help
I have reformatted the url six ways to Sunday. I have moved around code in server to try and diagnose the problem and I have messed with my routes. Ive tried postman and am getting an array back but thats it. I added a console.log in server that returns my cluster so I know Im connected in some capacity.
Sorry if Im missing something obvious and didn't show enough code, I am fairly new to all this if you cant tell. Thank you so much for any help you can provide.
````const routes = require("./routes");
````const app = express();
//////////////////////////////////////////////////////////////////
````const mongoose = require("mongoose")
````const bodyParser = require("body-parser")
````//Bodyparser middleware
````app.use(bodyParser.json());
````//DB config
````const MongoClient = require('mongodb').MongoClient;
````const uri = "mongodb+srv://NicoP93:REDACTED#cluster0-vplwy.mongodb.net/test?retryWrites=true"
````MongoClient.connect(uri, function(err, client) {
````if(err){
````console.log("Not connected to atlas")
````} else {
````console.log("connected to atlas")
````}
````const collection = client.db("Overthrow").collection("Knowledge")
````if(collection){console.log("Collection Connection")};
````console.log(collection);
````mongoose.connect(uri).then(() => {console.log("Mongoose connected")})
````})
````const items = require("./routes/api/items")
````app.use('/api/items', items);
````const PORT = process.env.PORT || 3001;
///////////////////////////////////////////////////////////////////////////////
````app.use(express.urlencoded({
````extended: true
````}));
````app.use(express.json());
````if (process.env.NODE_ENV === "production") {
````app.use(express.static("client/build"));
````}
````app.use(routes);
````app.listen(PORT, function () {
```` console.log("🌎 ==> API Server now listening on port " + PORT);
````});
When I hit the get all route I would expect something like
{"_id:5cd9fff41c9d440000f25cb8
buttonLike:0
buttonDislike:0
representativeName:"Ted Cruz"
__v:"0"}
because thats what in my atlas db, Im looking at it right now in their website.
Additionally, node server returns:
{(node:5600) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
🌎 ==> API Server now listening on port 3001
connected to atlas
Collection Connection
Collection {
s:
{ pkFactory:
{ [Function: ObjectID]
index: 550824,
createPk: [Function: createPk],
createFromTime: [Function: createFromTime],
createFromHexString: [Function: createFromHexString],
isValid: [Function: isValid],
ObjectID: [Circular],
ObjectId: [Circular] },
db:
Db {
_events: [Object: null prototype] {},
_eventsCount: 0,
_maxListeners: undefined,
s: [Object],
serverConfig: [Getter],
bufferMaxEntries: [Getter],
databaseName: [Getter] },
topology:
ReplSet {
_events: [Object],
_eventsCount: 25,
_maxListeners: Infinity,
clientInfo: [Object],
s: [Object] },
dbName: 'Overthrow',
options:
{ promiseLibrary: [Function: Promise],
readConcern: undefined,
readPreference: [ReadPreference] },
namespace: 'Overthrow.Knowledge',
readPreference: ReadPreference { mode: 'primary', tags: undefined },
slaveOk: true,
serializeFunctions: undefined,
raw: undefined,
promoteLongs: undefined,
promoteValues: undefined,
promoteBuffers: undefined,
internalHint: null,
collectionHint: null,
name: 'Knowledge',
promiseLibrary: [Function: Promise],
readConcern: undefined,
writeConcern: undefined } }
Mongoose connected }

Trying to connect to Mssql server via knex

I'm trying to connect to a remote database with knex but I get this error:
"tedious deprecated The default value for options.encrypt will change from false to true. Please pass false explicitly if you want to retain current behaviour. at node_modules\mssql\lib\tedious.js:212:23
Unhandled rejection ConnectionError: Failed to connect to 151.80.119.227,14831:1433 - getaddrinfo ENOTFOUND 151.80.119.227,14831"
I can connect via Microsoft sql server management studio with same host, user, password so I'm lost.
Edit:
This is how I create my knex var:
var knex = require('knex')({
client: 'mssql',
connection: {
server : '151.80.119.227,14831',
user : '****',
password : '****',
database : '****'
}
});
I can connect to it via python with:
con = pyodbc.connect("DRIVER={SQL Server};server=151.80.119.227,14831;database=*****;uid=****;pwd=****")
So why won't it connect through node.js ....
Port should actually be specified in the MSSQL options variable:
var knex = require('knex')({
client: 'mssql',
connection: {
server : '151.80.119.227',
user : '****',
password : '****',
database : '****',
options: {
port: 14831
}
}
});
This is from reading the code at https://github.com/tgriesser/knex/blob/v0.16.2/src/dialects/mssql/index.js
port for node-mssql driver should be set like this:
{
dialect: 'mssql',
connection: {
user: "sa",
password: "S0meVeryHardPassword",
server: "151.80.119.227",
port: 14831,
database: "knex_test"
}
}

AWS RDS MS SQL Unable to connect

I am trying to connect to my newly created ms sql database. However, I am getting an error when I try to connect. Error : Unable to connect to the database: { SequelizeConnectionError: Failed to connect to ....
const sequelize =new Sequelize({
dialect: 'mssql',
dialectModulePath: 'tedious',
dialectOptions: {
driver: '**SQL Server Native Client 11.0 - is this correct?**',
instanceName: '**where do i get this?**'
},
host: '**what do i put for this?'is this the end point?**',
port: '1433',
username: 'username',
password: 'password,
database: '**what do i put for this?**',
pool: {
min: 0,
max: 10,
idle: 10000
}
});
dbname is the name of the database you're interacting with (you entered this into aws)
also make sure you did npm install tedious -S
const sequelize =new Sequelize('dbname', 'dbusername', 'dbpassword', {
host: 'http://endpoint-from-aws.com'
dialect: 'mssql',
operatorsAliases: false,
pool: {
min: 0,
max: 10,
idle: 10000
}
});
http://docs.sequelizejs.com/manual/installation/getting-started.html
const sequelize = await new Sequelize(database, user, password, { host: 'rds-end-point', dialect: 'mysql' });

How do I get Sails.js to query an existing database?

There's a dev database already set up for another project. I'm trying to create a sails.js server to connect to this database and act as a RESTful API. I'm also using SQL Workbench with the profile below to connect to the database and verify my query statements. On that tool, I'm able to send queries like select top 10 * from advisor and get the data I expect in response.
My connection configuration in sails.js seems to be alright, since I'm able to start the server. I've gotten simple static actions to work, like hi: function (req, res) { return res.send("Hi there!"); }. However, I can't figure out what to do to get a response from the database served by sails. My goal (at this point) is to have http://localhost:1337/advisor return JSON for the results of select top 10 * from advisor.
I initially tried using the freshly-generated model. Then, I tried adding attributes to the model file. Then, I tried adding my own code to the controller. In each case, the browser never received a response. At the end, I tested /advisor/list to run my own code and it doesn't look like the query() callback was ever executed. In case it's the first question, I have run npm install sails-sqlserver and I've double-checked that my host, db, username, & password are identical to what was used in Workbench.
connections.js
sqlserver: {
adapter: 'sails-sqlserver',
user: 'myusername',
password: 'mypassword',
host: 'mysubdomain.mydomain.net:1433',
database: 'frontofficedev'
}
models.js
module.exports.models = {
connection: 'sqlserver',
migrate: 'safe'
};
api\models\Advisor.js
module.exports = {
attributes: {
advcode: 'string',
advname: 'string',
'adv-default': 'boolean',
"user-id": 'string',
"pc-code": 'string',
"adv-tag": 'string',
"is-group": 'boolean',
"trade-grouping": 'string',
AdvisorId: 'int',
orgcode: 'string',
BranchId: 'int',
OrdPrnBranchId: 'int',
zdec1: 'float',
zdec2: 'float',
zchar1: 'string',
zchar2: 'string',
zchar3: 'string',
zchar4: 'string',
AdvStatus: 'string'
}
};
api\controllers
module.exports = {
hi: function (req, res) {
return res.send("Hi there!");
},
list: function (req, res) {
var myQuery = "select TOP 10 * from advisor";
sails.log.debug("Query :", myQuery);
console.log(Advisor);
Advisor.query(myQuery, function (err, advisors){
console.log(advisors);
console.log(err);
if(err || !advisors.rows.length){
return res.json({"status": 0, "error": err});
}
else{
return res.json(advisors);
}
});
}
};
Any ideas on what I'm doing wrong? Is JDBC causing problems? Thanks in advance.
Im assuming you've already run: npm install sails-sqlserver --save
You have to specify your connection and the table you will be using in the model, the variables in the model should match with your DB variables, like this:
api\models\Advisor.js
module.exports = {
schema: true,
connection: 'sqlserver',
tableName: 'yourTableName',
attributes: {
advcode:{
type: 'string',
primaryKey: true //if this is a primary key
},
advname:{
type: 'string'
},
'adv-default':{
type: 'boolean'
}
};
In your controller you can use the Sails ORM waterline like this:
api\controllers
module.exports = {
list: function (req, res) {
Advisor.query('SELECT * FROM advisor', function(err, results) {
if (err) {
res.send(400);
} else {
res.send(results);
}
});
}
};
Where Advisor is the model.
For more specific information about models and ORM waterline i recommend you read the sails docs: http://sailsjs.org/documentation/reference/waterline-orm/models
My colleague spotted the problem. The port that database lives on needs to be a separate attribute in sails' connection.js (instead of including it in the host string). No need for extra libraries, like node-jdbc.
config/connections.js
sqlserver: {
adapter: 'sails-sqlserver',
user: 'myusername',
password: 'mypassword',
host: 'mysubdomain.mydomain.net',
port: 1433,
database: 'frontofficedev'
}
After making that change, I was able to delete all my custom code from the controller and almost everything from the model (I still need to specify a primary key, since sails looks for id by default and the database was using AdvisorId.
api/models/Advisor.js
module.exports = {
attributes: {
AdvisorId: {primaryKey: true}
}
};

Connecting NodeJS Express to MS SQL Server

I'm a NodeJS newbie and I am building an application that talks to an MSSQL (SQL Server 2008 R2) Database. For this, I tried using Sequelize, an ORM library that claims to do so.
While I have been successful in making it work with MySQL, SQL Server connection is just not working. I connected to a local database on both the occasions. Here's what I tried (as given in the docs):
[Part 1: Establish Connection]
... Express Code ...
var Sequelize = require('sequelize');
var sequelize = new Sequelize('NewDB', '', '', {
host: '(localdb)\v11.0',
dialect: 'mssql',
pool: {
max: 5,
min: 0,
idle: 10000
}
});
[Part 2: Testing]
var User = sequelize.define('user', {
firstName: {
type: Sequelize.STRING,
field: 'first_name' // Will result in an attribute that is firstName when user facing but first_name in the database
},
lastName: {
type: Sequelize.STRING
}
}, {
freezeTableName: true // Model tableName will be the same as the model name
});
User.sync({force: true}).then(function () {
// Table created
return User.create({
firstName: 'John',
lastName: 'Hancock'
});
});
... Express Code ...
The database NewDB does exist on the server. Now, While using SQL Server Express, the same credentials work. But not here. The error that I see is:
Unhandled rejection SequelizeConnectionError: Failed to connect to (localdb)\v11.0:1433 = getaddrinfo ENOTFOUND (localdb)\v11.0
So, here's the question. What credentials do I put, so that it works? And if it doesn't what would be alternate library to establish a Database connection? I'll prefer an ORM, but it's not that important a thing (anything works as long as I can connect to the DB).

Resources