tediousjs / tedious

Node TDS module for connecting to SQL Server databases.

Home Page:http://tediousjs.github.io/tedious/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

What 'clientId' should I provide when using 'azure-active-directory-password'?

richardcarrigan opened this issue · comments

When I connect to my SQL server using the azure-active-directory-password method, I get the warning:

When using the 'azure-active-directory-password' authentication method, please provide a value for the 'clientId' option. 
This option will be required in a future release.

Should I provide the AAD user's object ID or is there some other expected value?

Hi @nihonjinboy85, I actually explained this in another issue that you have commented on as well. Here is that comment.

We also have an explanation on our GitHub io page under "azure-active-directory-password". If you want, you can also check that.

To get the client, I also had a Microsoft side doc linked in the comment that I mentioned. You can refer to that to get your clientID.

Hope this helps!

Hi @MichaelSun90 , I did read that explanation which makes sense for applications, but I didn't understand how that fits with individual AAD users. For my use case, I was using my own user account when developing locally and the app service's managed identity when deployed. Therefore, when I was in the dev env, I was using azure-active-directory-password, but I was authenticating as myself, not the application. Is the expectation that we should register an application and then use that client ID in both dev and prod env's?

Admittedly, this is a somewhat moot point now, as I've been able to use jamesderrick's workaround in order to use azure-active-directory-access-token throughout, and will eventually be using azure-active-directory-default once it hits NPM. That being said, I'd still like to gain a better understanding of what client ID is expected when using an individual user's credentials for AAD auth...or maybe that scenario is not a recommended/supported approach.

Thanks for all your help this week, @MichaelSun90 !

Hi @nihonjinboy85 , sorry for the later responses. I was also doing some investigation, so I will be 100% sure that I am sharing the correct information.

One thing that I want to confirm with you:

I was using my own user account when developing locally

This means that you pass your own username and password to tedious connection configuration for logging in and developing your own project.

app service's managed identity when deployed

This means the users have their managed identities and those are used for tedious connection configuration for logging in and accessing the SQL server.

For clientID, sorry that I may not be 100% clear from my previous message. It actually has another name called application Id, which may be a bit clearer name since the client id is used in multiple places. You can get the id when you register your project under your tenant from the Azure portal. The application that you are developing must be registered and approved in order to try and authenticate your users in a tenant within Azure. Once an application has done the registration, it is "permitted" to try and authenticate users. This is the "first security checkpoint" that must be passed to do anything against a tenant in Azure. The client (application) id is an identifier of the Azure AD-registered application. For tedious, it acts as the part of your project that handles communicating with the server for actions like authentication and requesting data. For example, after you have registered your application and you pass your credentials along with the clientID to tedious. Tedious will communicate with the Microsoft identity platform using Microsoft Authentication Library (MSAL). Microsoft identity platform will decide whether the provided info is sufficient for an AAD token. If a token is returned, tedious will use the token to form the connection with the server and handle other operations like sending out requests later. For other authentication types, the different config settings passed to tedious hances that tedious can grab the token and auth the connection in different passed that MSAL provide, so client(application)ID may not need to be provided like this.

For application registration, you can check this doc: Quickstart: Register an application with the Microsoft identity platform.
Also found an example for NodeJS application registration. Not sure how close it is to your situation, but you can check it here: Azure-Samples

  • Specifically this section: Register the service app
  • Also, this example does not involve tedious authentication processes. Just provide an idea for how the application is registered.

Hope this helps, and we may also add something in our FAQ document to explain this, so it will not cause further confusion.

Hi @MichaelSun90 ,

First of all, thank you so much for taking the time to discuss this with me and provide your guidance and insight. I'm still very new to all of the nuances of Azure authentication (AAD et al), so the community's support has been instrumental in the work I'm currently doing to update my team's project to no longer use SQL server auth or Blob storage connection strings and instead use the @azure/identity DefaultAzureCredential.

Update

After doing some further R&D into this, I now understand that an app registration does not have to have any connection to the Azure App Service, but is essentially a service principal that can be used to allow users (or developers in my case) of the app to access certain Microsoft APIs. In my case, here is the configuration I went with:

  • For local dev, I have created an Azure app registration, assigned it the 'Storage Blob Data Contributor' role on my staging storage account, and added it as a db_owner to the staging SQL DB. I then added the AZURE_CLIENT_ID, AZURE_TENANT_ID, and AZURE_CLIENT_SECRET to my .env file.
  • For the deployed app, I have created a system-assigned managed identity and given that managed identity the same permissions as above.
  • For the app code itself, I just use DefaultAzureCredential as it will automatically use my env vars when available (development only) and, otherwise, will use the app's managed identity. This means no if (process.env.NODE_ENV === 'development')!

In addition to the above improvements, which are being deployed now, I'm also working on updating our DevOps pipeline to automatically create the app registration, create the app service managed identity, and grant both the necessary roles as part of our CD process. This will ensure that whenever a change is made to our code, this managed identity connection will be configured correctly, regardless of what anyone has changed within Azure since the last deployment.

Feedback

I think the biggest concern I still have, however, is if I'm developing a brand new PoC after Tedious starts requiring a clientId for the azure-active-directory-password auth, that means that I have no choice but to create a new app registration, even though I haven't even deployed the app yet. Not a huge deal, now that I know how trivial it is to create a new app registration, but it should definitely be called out as a mandatory first step when starting to leverage AAD auth through Tedious.

Thanks again for all your help!