-
Notifications
You must be signed in to change notification settings - Fork 438
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: ActiveDirectoryPassword and sqlpassword authentication support #707
Conversation
noticed the latency in generating token in adal-node lib, follow up on AzureAD/azure-activedirectory-library-for-nodejs#192 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @Hadis-Fard,
what's the current state of this PR? @David-Engel let me know that there's a bunch of customers waiting for it's integration, so I'm trying to figure out what needs to be done to get it into a shippable state.
I left a few comments for things that jumped out to me, but I also wanted to check with how you feel about these changes. 🙇
src/token/fedauth-info-parser.js
Outdated
|
||
const countOfInfoIDs = data.readUInt32LE(infoData.offset); | ||
infoData.offset += 4; | ||
async.times(countOfInfoIDs, () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think async.times
usage is required here. The full token data was already loaded into data
, and can be processed synchronously here.
src/token/fedauth-info-parser.js
Outdated
@@ -0,0 +1,61 @@ | |||
const async = require('async'); | |||
|
|||
function readFedAuthInfoOpt(data, infoData, FEDAUTHINFOID, callback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd be great if this function could be refactored a bit for better readability. It can be a regular non-async method, and I think it should return a { stsurl: '...', spn: '...' }
object.
Having it take and modify the infoData
object in place is a bit confusing. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, FEDAUTHINFOID
could be a top-level constant, instead of being passed in as well.
src/token/feature-ext-parser.js
Outdated
@@ -0,0 +1,27 @@ | |||
|
|||
module.exports = function featureExtAckParser(parser, colMetadata, options, callback) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this parser is quite right. 🤔
According to the MS-TDS spec, the FEATUREEXTACK
token can return multiple different features, while this implementation only ever returns the latest feature that was read.
Also, it only returns the feature data length, not the actual data itself.
What do you think about changing the token to return an object with the following structure:
{
name: 'FEATUREEXTACK',
event: 'featureExtAck',
features: [
{
id: number,
data: Buffer,
},
....
]
}
Oh, and another thing that we'll need before this can be merged is a SQL Server in Azure that we can use for CI testing. @David-Engel @tediousjs/microsoft-contributors Is there some way to get an instance for testing? |
Thanks @arthurschreiber for reviewing this PR . It contains the AAD foundation and support of two auth methods - sqlpassword and AD password, and their unit tests. there are two other auth methods -token based auth and AD integrated auth - to be implemented, but those can be added incrementally in separate PRs after the foundation is merged, which is the same approach we took in implementing AAD in other client drivers. |
I have set environment variables in Travis ( - stage: azure
node_js: 8
before_install:
- mkdir ~/.tedious
- >
echo '{
"config": {
"server": "'${AZURE_SERVER}'",
"userName": "'${AZURE_USERNAME}'",
"password": "'${AZURE_PASS}'",
"options": {
"port": 1433,
"database": "test",
"encrypt": "true"
}
}
}' > ~/.tedious/test-connection.json
before_script: skip
script: npm run test-integration How does that sound? Also, is it enough to just test with the latest version of node? 🤔 |
We should also fix the test that fails intermittently (test/integration/pause-resume-test.js), it fails every time with remote server 😅 |
@v-suhame That looks great! Can we add this change to the travis configuration in this pull request here? |
I forgot AAD had 4 auth mechanisms 😅 The initial credentials I had set was for |
@Hadis-Fard This should be almost ready to merge now. I had to update some tests to better handle missing permissions and will extract these changes out of this PR, but I think this should be ready otherwise. Would you mind taking another look over the refactorings I made? 🙇 |
src/connection.js
Outdated
@@ -744,7 +743,7 @@ class Connection extends EventEmitter { | |||
switch (this.fedAuthInfo.fedAuthLibrary) { | |||
case FEDAUTH_OPTIONS.LIBRARY_ADAL: | |||
if (0 !== fedAuthAck.length) { | |||
this.loginError = ConnectionError(`Active Directory authentication acknowledgment for ${this.fedAuthInfo.method} authentication method includes extra data`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should keep the method property, azure-active-directory should be a basket for various methods of AAD auth, for example security token, msi, and aad integrated auth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather have individual auth types, like azure-active-directory-integrated
. I was not really able to find a lot of documentation on the other two methods, but for those we could also have separate authentication types? 🤔
src/connection.js
Outdated
@@ -739,17 +738,14 @@ class Connection extends EventEmitter { | |||
if (!this.fedAuthInfo.fedAuthInfoRequested) { | |||
this.loginError = ConnectionError('Did not request Active Directory authentication, but received the acknowledgment'); | |||
this.loggedIn = false; | |||
} | |||
switch (this.fedAuthInfo.fedAuthLibrary) { | |||
case FEDAUTH_OPTIONS.LIBRARY_ADAL: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should keep adal library check and FEDAUTH_OPTIONS and ADAL LIBRARY as we'll expand the feature to other auth types
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here as well, I'd rather have this as separate authentication types, instead of mixing this all together into one type with a large set of options.
@arthurschreiber in addition to 'azure-active-directory' user should set the method of authentication which could be so in the config in addition to new Connection({
"server": "ADServer",
"authentication": {
"type": "azure-active-directory",
"method" : "ACTIVEDIRECOTRYPASSWORD",
"options": {
"userName": "ADUser",
"password": "foobar"
}
}
}); and have the if (this.config.authentication.type === 'azure-active-directory') {
if(!Object.values(this.fedAuthInfo.ValidFedAuthEnum).includes(config.authentication.toUpperCase())) {
throw new Error(`${config.authentication} is not a valid authentication method`);
}
if (this.config.options.tdsVersion < '7_4') {
throw new Error(`Azure Active Directory authentication is not supported in the TDS version ${this.config.options.tdsVersion}`);
} |
@Hadis-Fard The latency in getting a token was due to the way execution was delayed via recursive |
@Hadis-Fard We could also rename the authentication type to |
👍 to have separate type for each kind of AAD auth. However all other drivers are using the same keyword for AAD methods . I suggest to rename |
@arthurschreiber thanks for working on this 👌, we need to make adjustments and then AAD should be ready to merge:
"server": "yourServer",
"authentication": {
"type": "azure-active-directory",
"options": {
"userName": "user",
"password": "pwd",
},
"options": {
"encrypt": true
},
} in this case encrypt is not set to true and authentication fails with the message that server requires encrypt to be true |
@Hadis-Fard there's two |
🎉 This PR is included in version 4.1.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
@arthurschreiber setting encrypt in the options object after authentication would raise var connectionADnew = {
server: "ADServer.windows.net",
authentication: {
type: "azure-active-directory-password",
options: {
userName: "ADuser",
password: "pwd",
},
options: {
encrypt: true,
}
}
}; |
@Hadis-Fard I've trouble reproducing this error? This is exactly how the Travis tests are configured, and how I locally test against Azure DB. Lines 83 to 98 in da45fef
|
@Hadis-Fard I only get the error you mentioned if I don't set |
@arthurschreiber 😕 we don't need to worry about this error that much since as you said it'll gonna get fixed by merging #694 |
squash merged of #661, please see details and previous discussion there.