Skip to content
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: Introduce pluggable authentication providers. #624

Open
wants to merge 43 commits into
base: master
Choose a base branch
from

Conversation

arthurschreiber
Copy link
Collaborator

@arthurschreiber arthurschreiber commented Oct 13, 2017

In preparation of a new tedious release, I was going through all changes since v2.0.1. One thing I want to cleanup before the release is the integration with sspi-client.

I'm not super happy about the current situation where sspi-client is a hard dependency of tedious, and seeing that SQL Server actually supports more authentication methods and that there is another authentication related pull request in flight (#612) that adds node-kerberos as another hard dependency, I feel that the current approach for authentication methods is not scalable.

In this pull request, I explore the addition of what I call "authentication" providers (they're called "Security Support Providers" in the MS-TDS specification). The whole pull request is still very much in flux and a work in progress, but I believe the direction proposed here to be sound.

Authentication providers are simply objects that implement a .handshake(input, callback) method that is responsible for taking in authentication handshake data coming from SQL Server, and calling the passed callback with the handshake data that should be sent back to the SQL Server.

The long-term goal is to ship tedious with only a "default" dummy provider that does not actually do anything. Other providers like for NTLM, Kerberos or the native SSPI support will be extracted into separate npm modules organization. This way, we can extract both the implementation of these providers out of tedious, and keep tedious free from dependencies that are not required for all users.

The authentication provider to use for connecting to SQL Server will be specifiable via a new option when establishing a connection, and each provider will be able to handle options that are specific to it in it's own way.

For example, when using NTLM (domain) authentication I imagine connection creation could look like this:

new Connection({
  "server": "localhost",
  "userName": "sa",
  "password": "yourStrong(!)Password",
  "authProvider": require("tedious-auth-ntlm")({
    "domain": "MYDOMAIN.COM",
    "workstation": "FOOBARBAZ"
  }),
  "options": {
    "port": 1433,
    "database": "master"
  }
});

While native SSPI could look like this:

new Connection({
  "server": "localhost",
  "userName": "sa",
  "password": "yourStrong(!)Password",
  "authProvider": require("tedious-auth-native")({
    "packageName": "negotiate"
  }),
  "options": {
    "port": 1433,
    "database": "master"
  }
});

@tvrprasad @v-suhame What do you think?

This merges the `SENT_LOGIN7_WITH_STANDARD_LOGIN`,
`SENT_LOGIN7_WITH_NTLM` and `SENT_NTLM_RESPONSE` states into a single
`SENT_LOGIN7` state.
Both domain and workstation are optional according to the MS-NLMP
specification, so we should not require a domain to be given.

This should improve/ease the use of NTLM auth with Azure SQL Server.
SSPI is the interface name / API that's used for all authentication
providers.. "native" is a more fitting name because it depends on the
operating system's native APIs to provide security support.
@Suraiya-Hameed
Copy link
Member

@arthurschreiber sound like a good idea! Later we can also bring these tedious specific authentication providers dependencies under tediousjs organization.
I'll start reviewing PR 👍

@tvrprasad
Copy link
Contributor

@arthurschreiber Couple of quick high level comments:

  1. Further abstracting out Authentication sounds like general goodness.
  2. How does this get rid of dependency on sspi-client? It seems to me like you still need to install it with Tedious. May be I'm missing something.

@arthurschreiber
Copy link
Collaborator Author

@tvrprasad The idea would be to have at least 3 separate packages:

  • tedious-auth-native to expose native system SSPI packages on Windows Systems.
  • tedious-auth-ntlm to expose NTLM auth (regardless of operating system).
  • tedious-auth-kerberos to expose Kerberos auth (regardless of operating system).

I think that'd cover all SSPI types SQL Server supports. I've seen that there is also some sort of Federated Authentication support documented in the latest TDS specifications, but I've not really looked into how it works - but it seems different enough from the SSPI authentication mechanisms that there's probably no sane way to reconcile the APIs.

tedious would not depend directly on any of these packages, so the dependencies like node-kerberos and sspi-client would not automatically be pulled in when installing tedious and using the standard TDS authentication mechanism.

@arthurschreiber
Copy link
Collaborator Author

@v-suhame Thanks! I'd love to have tests for NTLM and Kerberos auth as part of the CI builds (first inside tedious itself, later as part of the individual packages). Is there some "straightforward" way to set up a CI system for this? Maybe via Azure SQL Server and Azure AD? 🤔 I do have an Azure account and could set everything up, but some pointers would be great.

(/cc @tvrprasad - I know you might not have time, but maybe you have a good idea here.)

@Suraiya-Hameed
Copy link
Member

Suraiya-Hameed commented Oct 16, 2017

Federated Authentication was the former name for Azure AD, TDS docs still seems to use the old name. We have long term plan to add Azure AD support to Tedious 😉
For CI, the only option I can think of is to set an Azure VM and test integrated auth and NTLM in there.
@meet-bhagdev @tvrprasad Is there better alternative?

@@ -396,6 +399,8 @@ class Connection extends EventEmitter {
REDIRECT: 1,
RETRY: 2
};

this.authProvider = new DefaultAuthProvider(this);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.authProvider should be equal to the local authProvider here.

authProvider = config.authProvider;
} else if (config.domain) {
authProvider = new NTLMAuthProvider(this, { domain: config.domain });
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NTLMAuthProvider needs username, password, workstation along with domain.

@meet-bhagdev
Copy link

@v-suhame that seems like the best idea right now. @Hadis-Fard any thoughts on this? How do we do this for PHP?

return this.sendDataToTokenStreamParser(data);
// Use SSPI blob if received
if (this.ntlmpacketBuffer) {
return this.authProvider.processChallenge(this.ntlmpacketBuffer, (error, responseBuffer) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function call should be this.authProvider.parseChallengeMessage( ), authentication provider implementation uses the name parseChallengeMessage 😄

@Hadis-Knj
Copy link

@meet-bhagdev +1 to @v-suhame's idea. As she said Tedious doesn't support AzureAD yet and is in our future plans to support it.
In PHP, we are testing the Azure AD scenarios that can be tested using sql server docker (UID and PWD authentication), and added a variable to tests for other cases as we couldn't reveal credentials on GitHub , the variable is replaced with a valid credential when we pull tests from GitHub to internal test lab before connecting to sqlDB

@tvrprasad
Copy link
Contributor

I'd love to have tests for NTLM and Kerberos auth as part of the CI builds (first inside tedious itself, later as part of the individual packages).

There are tests inside Tedious for NTLM, both for sspi-client and the non-sspi-client version. I think they run as part of CI but not 100% sure.

sspi-client is applicable only for Windows and that's where the tests run. sspi-client is not just NTLM, it's NTLM, Kerberos and Negotiate protocols. But since it uses Microsoft proprietary API, it'll only work on Windows.

Kerberos auth code path that @v-suhame has in PR, I think, should only be enabled for Linux.

@Suraiya-Hameed
Copy link
Member

Suraiya-Hameed commented Oct 17, 2017

--Updated--
SQL Server image in docker only supports username/password auth, so current CI doesn't test any NTLM or sspi-client related integration tests. Only feasible alternative (I can think of) is to setup Azure VM with SQL Server.

And yes, Kerberos auth code path is reachable only for non-Windows based system.

@meet-bhagdev
Copy link

@v-suhame how woulad Azure integrated auth work with the SQL Server docker image? I am not sure if that is a supported scenario. Am I missing something?

@Suraiya-Hameed
Copy link
Member

Sorry! I meant SQL Server in Azure VM.

@Suraiya-Hameed
Copy link
Member

@arthurschreiber I've committed changes, based on my review comments.

@tvrprasad
Copy link
Contributor

@v-suhame Could you install box version of SQL Server on Azure VM that's added to an AD domain to test for AD authentication, right? Or does that also only work with Azure AD?

@Hadis-Knj
Copy link

Hadis-Knj commented Dec 13, 2017

@arthurschreiber I have finished AAD (fedauth) authentication usign username password based on current master, and able to connect. I was wondering when would you merge this PR, so I can adapt this design, or should i just send the AAD PR as is? 😕

@arthurschreiber
Copy link
Collaborator Author

@Hadis-Fard Would be great if you could send the current version of your PR. 👍 This would allow us to take a look and see whether we can integrate the different auth approaches somehow.

@Suraiya-Hameed
Copy link
Member

@arthurschreiber Is there anything you need assistance with to wrap up this PR? 😄 Looks like it is almost ready to merge.

@David-Engel
Copy link
Member

@arthurschreiber Is there anything we can do to help move this PR forward? We'd really like to be able to add additional authentication methods in tedious using this method. A lot of customers are migrating to Azure hosted services and supporting them is a high priority for us. 😄

@arthurschreiber
Copy link
Collaborator Author

👋 Hey @David-Engel,

I've picked up work on this pull request and #707 - I'm trying right now to come up with an authentication provider interface that will support both integrated and federated authentication schemes. 👍

@Suraiya-Hameed
Copy link
Member

I've picked up work on this pull request and #707 - I'm trying right now to come up with an authentication provider interface that will support both integrated and federated authentication schemes.

Hey @arthurschreiber, any update on this? Is there anything I can help with to get this going?

@fenngineering
Copy link

When will this be worked on?

@drc-schihak
Copy link

@arthurschreiber This feature sounds perfect, do you know if this will completed?

@pradz85
Copy link

pradz85 commented Nov 12, 2020

I am mainly looking for kerberos authentication support in tedious. Ticket #612 says it would be fixed as part of this ticket. Is there any update ? Thanks.

@2160006332
Copy link

Has the tedious implementation of Windows authentication been accomplished?

I am trying to make the following connection in tedious, however without success.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.