-
Notifications
You must be signed in to change notification settings - Fork 117
Add comprehensive authentication documentation and multi-auth support #57
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -92,12 +92,14 @@ This server leverages the Model Context Protocol (MCP), a versatile framework th | |||||
"env": { | ||||||
"SERVER_NAME": "your-server-name.database.windows.net", | ||||||
"DATABASE_NAME": "your-database-name", | ||||||
"AUTH_METHOD": "azure-ad", | ||||||
"READONLY": "false" | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
``` | ||||||
|
||||||
4. **Restart VS Code** | ||||||
|
@@ -126,25 +128,116 @@ This server leverages the Model Context Protocol (MCP), a versatile framework th | |||||
"env": { | ||||||
"SERVER_NAME": "your-server-name.database.windows.net", | ||||||
"DATABASE_NAME": "your-database-name", | ||||||
"AUTH_METHOD": "azure-ad", | ||||||
"READONLY": "false" | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
} | ||||||
``` | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's an extra closing brace that creates invalid JSON syntax. This should be removed to maintain proper JSON structure.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||
|
||||||
3. **Restart Claude Desktop** | ||||||
- Close and reopen Claude Desktop for the changes to take effect | ||||||
|
||||||
## Authentication Configuration | ||||||
|
||||||
The MCP server supports multiple authentication methods to connect to your MSSQL database. Choose the method that best fits your environment and security requirements. | ||||||
|
||||||
### Authentication Methods | ||||||
|
||||||
#### 1. Azure Active Directory (Default) | ||||||
**Best for:** Azure SQL Database, managed identities, modern security requirements | ||||||
|
||||||
This method uses Azure AD authentication with interactive browser login. No username/password needed in configuration. | ||||||
|
||||||
```json | ||||||
{ | ||||||
"env": { | ||||||
"SERVER_NAME": "your-server.database.windows.net", | ||||||
"DATABASE_NAME": "your-database-name", | ||||||
"AUTH_METHOD": "azure-ad" | ||||||
} | ||||||
} | ||||||
``` | ||||||
|
||||||
**Required Environment Variables:** | ||||||
- `AUTH_METHOD`: Set to `"azure-ad"` or `"azuread"` | ||||||
- `SERVER_NAME`: Your Azure SQL server name | ||||||
- `DATABASE_NAME`: Your database name | ||||||
|
||||||
**Notes:** | ||||||
- Uses interactive browser authentication | ||||||
- Automatically handles token refresh | ||||||
- Requires Azure AD permissions for the database | ||||||
- Most secure option for Azure SQL Database | ||||||
|
||||||
#### 2. SQL Server Authentication | ||||||
**Best for:** Traditional SQL Server instances, local development | ||||||
|
||||||
Uses SQL Server's built-in authentication with username and password. | ||||||
|
||||||
```json | ||||||
{ | ||||||
"env": { | ||||||
"SERVER_NAME": "your-server.database.windows.net", | ||||||
"DATABASE_NAME": "your-database-name", | ||||||
"AUTH_METHOD": "sql", | ||||||
"SQL_USERNAME": "your-sql-username", | ||||||
"SQL_PASSWORD": "your-sql-password" | ||||||
} | ||||||
} | ||||||
``` | ||||||
|
||||||
**Required Environment Variables:** | ||||||
- `AUTH_METHOD`: Set to `"sql"` or `"sqlserver"` | ||||||
- `SERVER_NAME`: Your SQL Server instance | ||||||
- `DATABASE_NAME`: Your database name | ||||||
- `SQL_USERNAME`: SQL Server username | ||||||
- `SQL_PASSWORD`: SQL Server password | ||||||
|
||||||
#### 3. Windows Authentication (NTLM) | ||||||
**Best for:** On-premises SQL Server with Windows domain authentication | ||||||
|
||||||
Uses Windows credentials for authentication. | ||||||
|
||||||
```json | ||||||
{ | ||||||
"env": { | ||||||
"SERVER_NAME": "your-server-instance", | ||||||
"DATABASE_NAME": "your-database-name", | ||||||
"AUTH_METHOD": "windows", | ||||||
"DOMAIN": "your-domain", | ||||||
"USERNAME": "your-windows-username", | ||||||
"PASSWORD": "your-windows-password" | ||||||
} | ||||||
} | ||||||
``` | ||||||
|
||||||
**Required Environment Variables:** | ||||||
- `AUTH_METHOD`: Set to `"windows"` or `"ntlm"` | ||||||
- `SERVER_NAME`: Your SQL Server instance | ||||||
- `DATABASE_NAME`: Your database name | ||||||
- `DOMAIN`: Windows domain (optional, can be empty) | ||||||
- `USERNAME`: Windows username | ||||||
- `PASSWORD`: Windows password | ||||||
|
||||||
### Configuration Parameters | ||||||
|
||||||
#### Common Parameters (All Authentication Methods) | ||||||
- **SERVER_NAME**: Your MSSQL Database server name (e.g., `my-server.database.windows.net`) | ||||||
- **DATABASE_NAME**: Your database name | ||||||
- **AUTH_METHOD**: Authentication method to use (`"azure-ad"`, `"sql"`, or `"windows"`). Defaults to `"azure-ad"` if not specified. | ||||||
- **READONLY**: Set to `"true"` to restrict to read-only operations, `"false"` for full access | ||||||
- **Path**: Update the path in `args` to point to your actual project location. | ||||||
- **CONNECTION_TIMEOUT**: (Optional) Connection timeout in seconds. Defaults to `30` if not set. | ||||||
- **TRUST_SERVER_CERTIFICATE**: (Optional) Set to `"true"` to trust self-signed server certificates (useful for development or when connecting to servers with self-signed certs). Defaults to `"false"`. | ||||||
|
||||||
#### Authentication-Specific Parameters | ||||||
- **SQL_USERNAME** & **SQL_PASSWORD**: Required for SQL Server authentication (`AUTH_METHOD="sql"`) | ||||||
- **USERNAME**, **PASSWORD** & **DOMAIN**: Required for Windows authentication (`AUTH_METHOD="windows"`) | ||||||
- **No additional parameters needed**: For Azure AD authentication (`AUTH_METHOD="azure-ad"`) | ||||||
|
||||||
## Sample Configurations | ||||||
|
||||||
You can find sample configuration files in the `src/samples/` folder: | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -29,36 +29,77 @@ let globalSqlPool: sql.ConnectionPool | null = null; | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let globalAccessToken: string | null = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let globalTokenExpiresOn: Date | null = null; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Function to create SQL config with fresh access token, returns token and expiry | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export async function createSqlConfig(): Promise<{ config: sql.config, token: string, expiresOn: Date }> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const credential = new InteractiveBrowserCredential({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
redirectUri: 'http://localhost' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// disableAutomaticAuthentication : true | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const accessToken = await credential.getToken('https://database.windows.net/.default'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Function to create SQL config with configurable authentication method | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export async function createSqlConfig(): Promise<{ config: sql.config, token?: string, expiresOn?: Date }> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const authMethod = process.env.AUTH_METHOD?.toLowerCase() || 'azure-ad'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const trustServerCertificate = process.env.TRUST_SERVER_CERTIFICATE?.toLowerCase() === 'true'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const connectionTimeout = process.env.CONNECTION_TIMEOUT ? parseInt(process.env.CONNECTION_TIMEOUT, 10) : 30; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
config: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
server: process.env.SERVER_NAME!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
database: process.env.DATABASE_NAME!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
encrypt: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
trustServerCertificate | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
authentication: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type: 'azure-active-directory-access-token', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
token: accessToken?.token!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
connectionTimeout: connectionTimeout * 1000, // convert seconds to milliseconds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const baseConfig = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
server: process.env.SERVER_NAME!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
database: process.env.DATABASE_NAME!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
encrypt: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
trustServerCertificate, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
useUTC: false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
token: accessToken?.token!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expiresOn: accessToken?.expiresOnTimestamp ? new Date(accessToken.expiresOnTimestamp) : new Date(Date.now() + 30 * 60 * 1000) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
connectionTimeout: connectionTimeout * 1000, // convert seconds to milliseconds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
switch (authMethod) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case 'azure-ad': | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case 'azuread': | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Azure Active Directory authentication | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const credential = new InteractiveBrowserCredential({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
redirectUri: 'http://localhost' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const accessToken = await credential.getToken('https://database.windows.net/.default'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
config: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
...baseConfig, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
authentication: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type: 'azure-active-directory-access-token', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
token: accessToken?.token!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
token: accessToken?.token!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
expiresOn: accessToken?.expiresOnTimestamp ? new Date(accessToken.expiresOnTimestamp) : new Date(Date.now() + 30 * 60 * 1000) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case 'windows': | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case 'ntlm': | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Windows authentication | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
config: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
...baseConfig, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
authentication: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type: 'ntlm', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
domain: process.env.DOMAIN || '', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
userName: process.env.USERNAME || '', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
password: process.env.PASSWORD || '' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case 'sql': | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
case 'sqlserver': | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// SQL Server authentication | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
config: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
...baseConfig, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
user: process.env.SQL_USERNAME!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
password: process.env.SQL_PASSWORD!, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the non-null assertion operator (!) on environment variables without validation could cause runtime errors if the required variables are not set. Consider adding validation to ensure SQL_USERNAME and SQL_PASSWORD are defined before using them.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using the non-null assertion operator (!) on environment variables without validation could cause runtime errors if the required variables are not set. Consider adding validation to ensure SQL_USERNAME and SQL_PASSWORD are defined before using them.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
default: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new Error(`Unsupported authentication method: ${authMethod}. Supported methods: azure-ad, windows, sql`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error message lists 'azure-ad' as a supported method but the code also accepts 'azuread' as an alias. Consider updating the error message to include all accepted values: 'azure-ad/azuread, windows/ntlm, sql/sqlserver'.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const updateDataTool = new UpdateDataTool(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -164,21 +205,36 @@ runServer().catch((error) => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Connect to SQL only when handling a request | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
async function ensureSqlConnection() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// If we have a pool and it's connected, and the token is still valid, reuse it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalSqlPool && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalSqlPool.connected && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalAccessToken && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalTokenExpiresOn && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalTokenExpiresOn > new Date(Date.now() + 2 * 60 * 1000) // 2 min buffer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const authMethod = process.env.AUTH_METHOD?.toLowerCase() || 'azure-ad'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// For Azure AD, check token expiry; for other methods, just check connection | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (authMethod === 'azure-ad' || authMethod === 'azuread') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// If we have a pool and it's connected, and the token is still valid, reuse it | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalSqlPool && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalSqlPool.connected && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalAccessToken && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalTokenExpiresOn && | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalTokenExpiresOn > new Date(Date.now() + 2 * 60 * 1000) // 2 min buffer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// For Windows and SQL Server auth, just check if connection exists | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (globalSqlPool && globalSqlPool.connected) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Otherwise, get a new token and reconnect | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { config, token, expiresOn } = await createSqlConfig(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalAccessToken = token; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalTokenExpiresOn = expiresOn; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Get new config (and token if using Azure AD) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const result = await createSqlConfig(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const { config } = result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Store token info for Azure AD | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (authMethod === 'azure-ad' || authMethod === 'azuread') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalAccessToken = result.token!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
globalTokenExpiresOn = result.expiresOn!; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Close old pool if exists | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (globalSqlPool && globalSqlPool.connected) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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.
There's an extra closing brace that creates invalid JSON syntax. This should be removed to maintain proper JSON structure.
Copilot uses AI. Check for mistakes.