Skip to content

Conversation

@ArjunNarendra
Copy link
Contributor

Remove dependency on DefaultAzureCredential internally and require the user to pass in a credential from which to generate a token across all languages and database drivers

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR updates credential usage across Python, JavaScript, and .NET implementations to require users to explicitly pass authentication credentials instead of relying on internal DefaultAzureCredential instantiation. This change improves flexibility and gives users explicit control over authentication.

  • Removed internal fallback to DefaultAzureCredential() in all language implementations
  • Updated all connection methods to require credential parameters (no longer optional/nullable)
  • Updated documentation and samples to show explicit credential passing
  • Moved identity dependencies from core to peer/dev dependencies

Reviewed Changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
python/src/azure_postgresql_auth/core.py Removed DefaultAzureCredential imports and made credential parameters required (non-nullable)
python/src/azure_postgresql_auth/sqlalchemy/entra_connection.py Updated to require credential via connect_args with validation and added usage examples
python/src/azure_postgresql_auth/sqlalchemy/async_entra_connection.py Updated async SQLAlchemy to require credential via connect_args with validation
python/src/azure_postgresql_auth/psycopg3/entra_connection.py Updated psycopg3 sync connection to require credential parameter
python/src/azure_postgresql_auth/psycopg3/async_entra_connection.py Updated psycopg3 async connection to require AsyncTokenCredential parameter
python/src/azure_postgresql_auth/psycopg2/entra_connection.py Updated psycopg2 connection to require credential parameter
python/pyproject.toml Removed azure-identity from core dependencies
python/README.md Updated all code examples to show explicit credential instantiation
python/samples/sqlalchemy/getting_started/create_db_connection.py Updated sample to pass credential via connect_args
python/samples/psycopg3/getting_started/create_db_connection.py Updated sample to pass credential via kwargs parameter
python/samples/psycopg2/getting_started/create_db_connection.py Updated sample to use partial function to bind credential
javascript/src/entra_id_extension.js Removed DefaultAzureCredential import and made credential parameter required
javascript/samples/sequelize/getting-started/create-db-connection.js Updated sample to instantiate and pass credential explicitly
javascript/samples/pg/getting-started/create-db-connection.js Updated sample to pass credential to getEntraTokenPassword function
javascript/package.json Moved @azure/identity to peer dependency from core dependency
javascript/README.md Updated all documentation examples to show explicit credential usage
dotnet/src/Microsoft/Azure/PostgreSQL/Auth/EntraIdExtension.cs Removed nullable credential parameters and DefaultAzureCredential fallback
dotnet/src/Microsoft/Azure/PostgreSQL/Auth/Microsoft.Azure.PostgreSQL.Auth.csproj Removed Azure.Identity package dependency
dotnet/samples/GettingStarted/GettingStarted.csproj Added Azure.Identity package dependency for sample usage
dotnet/samples/GettingStarted/CreateDbConnectionNpgsql.cs Updated sample to instantiate credential and pass to extension methods
dotnet/README.md Updated documentation examples to show credential instantiation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 53 to 57
if not isinstance(credential, (TokenCredential)):
raise CredentialValueError(
"credential must be a TokenCredential for sync connections"
"credential is required and must be a TokenCredential. "
"Pass it via connect_args={'credential': DefaultAzureCredential()}"
)
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

The validation logic will raise a TypeError when credential is None because isinstance(None, TokenCredential) check happens before raising the CredentialValueError.

The check should validate that credential is not None first:

if credential is None or not isinstance(credential, TokenCredential):
    raise CredentialValueError(
        "credential is required and must be a TokenCredential. "
        "Pass it via connect_args={'credential': DefaultAzureCredential()}"
    )

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed.

Args:
engine: The SQLAlchemy Engine to enable Entra authentication for
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

Trailing whitespace on this line. Remove the trailing spaces after engine:.

Suggested change

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Args:
engine: The async SQLAlchemy Engine to enable Entra authentication for
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

Trailing whitespace on this line. Remove the trailing spaces after engine:.

Suggested change

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

# authentication tokens are properly managed and refreshed so that each connection uses a valid token.
#
# For more details, see: https://www.psycopg.org/docs/advanced.html#subclassing-connection

Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

Trailing whitespace on this line. Remove the trailing spaces.

Suggested change

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this white space serves a purpose here.


# Create a connection factory with the credential bound using functools.partial
credential = DefaultAzureCredential()
connection_factory = partial(EntraConnection, credential=credential)
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

Trailing whitespace on this line. Remove the trailing spaces.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same thoughts as the previous comment

Comment on lines 66 to 68
"@azure/identity": {
"optional": false
},
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

[nitpick] Moving @azure/identity from dependencies to devDependencies while making it a required peer dependency is correct for a library pattern. However, the peerDependenciesMeta marks it as optional: false, which means it's required. This conflicts with the peer dependency pattern where packages are typically optional in metadata.

Either:

  1. Keep it as a regular dependency (if you want to bundle it)
  2. Make it truly optional in peerDependenciesMeta with optional: true and handle the missing credential case gracefully
  3. Remove the peerDependenciesMeta entry entirely (required is the default for peerDependencies)

Given the PR's intent to require users to provide credentials, option 3 (removing the meta entry) would be most appropriate.

Suggested change
"@azure/identity": {
"optional": false
},

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sounds good

"credential is required and must be a TokenCredential. "
"Pass it via connect_args={'credential': DefaultAzureCredential()}"
)

Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

Trailing whitespace on this line. Remove the trailing spaces.

Suggested change

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

"""
credential = kwargs.pop("credential", None)
if credential and not isinstance(credential, (AsyncTokenCredential)):
if not isinstance(credential, (AsyncTokenCredential)):
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

The validation logic will raise a TypeError when credential is None because isinstance(None, AsyncTokenCredential) check happens before raising the CredentialValueError.

The check should validate that credential is not None first:

if credential is None or not isinstance(credential, AsyncTokenCredential):
    raise CredentialValueError(
        "credential is required and must be an AsyncTokenCredential for async connections"
    )
Suggested change
if not isinstance(credential, (AsyncTokenCredential)):
if credential is None or not isinstance(credential, AsyncTokenCredential):

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed

Event handlers do not support async behavior so the token fetching will still
be synchronous.
Entra ID credentials for each database connection. A credential must be
provided via connect_args when creating the engine. Event handlers do not
Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

Trailing whitespace on this line. Remove the trailing spaces after the period.

Suggested change
provided via connect_args when creating the engine. Event handlers do not
provided via connect_args when creating the engine. Event handlers do not

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

"credential is required and must be a TokenCredential. "
"Pass it via connect_args={'credential': DefaultAzureCredential()}"
)

Copy link

Copilot AI Nov 14, 2025

Choose a reason for hiding this comment

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

Trailing whitespace on this line. Remove the trailing spaces.

Suggested change

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@ArjunNarendra ArjunNarendra merged commit 2eb235d into main Dec 4, 2025
5 checks passed
@ArjunNarendra ArjunNarendra deleted the user/an/update-credential-usage branch December 4, 2025 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants