I have an ASP.NET Core 9 Web API which I need to use managed identity to connect to a postgres database.
I have this code in my Program.cs
and I converted them from
var connectionString = builder.Configuration.GetConnectionString("db_conn_string")!;
builder.Services.AddEntityFrameworkNpgsql().AddDbContext<MyDbContext>(options =>
options.UseNpgsql(connectionString)
);
to this after following this document. But there the example is for console app not for Web API:
var connectionString = builder.Configuration.GetConnectionString("db_conn_string")!;
if (builder.Configuration["ASPNETCORE_ENVIRONMENT"] != "Development")
{
var accessToken = await new DefaultAzureCredential().GetTokenAsync(
new TokenRequestContext(scopes: [
"https://ossrdbms-aad.database.windows.net/.default"
])
);
connectionString = $"{builder.Configuration.GetConnectionString("db_conn_string")};Password={accessToken.Token}";
}
builder.Services.AddEntityFrameworkNpgsql().AddDbContext<MyDbContext>(options =>
options.UseNpgsql(connectionString)
);
But this will only work once right because I'm setting the token first time and after first token expire and getting new refreshed token it is not reset in connection string even though it says that in here
Token lifetime and refreshing is handled automatically. Where possible, reuse credential instances to optimize cache effectiveness
Links i thought are useful but dont know how to continue
I'm new to these things - can someone help me with this?
AS PER Feb 2025
I am using these nuget packages (csproj file):
<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.13.2" />
<PackageReference Include="Npgsql" Version="9.0.2" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.3" />
</ItemGroup>
Looking at the v9.0 documentation, you can use PeriodicPasswordProvider
and do something like that:
builder.Services.AddDbContext<MyDbContext>(options =>
options.UseNpgsql(
builder.Configuration.GetConnectionString("db_conn_string"),
o => o.ConfigureDataSource(dataSourceBuilder => dataSourceBuilder.UsePeriodicPasswordProvider(
async (_, ct) =>
{
var tokenResponse = await new DefaultAzureCredential().GetTokenAsync(
new TokenRequestContext(["https://<your-db-name>.database.windows.net/.default"]));
return tokenResponse.Token;
},
TimeSpan.FromMinutes(55), // Interval for refreshing the token
TimeSpan.FromSeconds(5)) // Interval for retrying after a refresh failure
)
)
);
Connectionstring sould look like that:
Host={host};Database={database};Username={user};SSL Mode=Require;Trust Server Certificate=true
As per @akseli comment, don't include the password int he connectionstring