.NET Core  

PostgreSQL 18 OAuth Authentication with ASP.NET Core Identity

Authentication is usually one of the first security decisions made when building an ASP.NET Core application.

For many applications, the architecture looks like this:

User
  |
  v
ASP.NET Core
  |
  v
Identity Provider
  |
  v
Application
  |
  v
PostgreSQL

The application authenticates the user, creates an application identity, and then connects to PostgreSQL using a database credential.

PostgreSQL 18 adds another option at the database layer: OAuth 2.0 authentication.

PostgreSQL 18 introduces an oauth authentication method in pg_hba.conf, along with OAuth-related libpq client support and token validation infrastructure. PostgreSQL's documentation describes this as authorization and optional authentication through a third-party OAuth 2.0 identity provider.

This creates an interesting architecture for .NET applications:

                    Identity Provider
                    OAuth / OIDC
                         |
             +-----------+-----------+
             |                       |
             v                       v
      ASP.NET Core             PostgreSQL 18
          |                         |
          |                         |
          +-------- Identity -------+

However, PostgreSQL OAuth authentication and ASP.NET Core Identity solve different problems.

ASP.NET Core Identity manages application users, passwords, roles, claims, login flows, and related application identity concerns. PostgreSQL OAuth authentication controls how a PostgreSQL client authenticates when connecting to the database.

Understanding that distinction is essential before replacing traditional database credentials.

What PostgreSQL 18 Adds

PostgreSQL 18 adds the oauth authentication method to pg_hba.conf. The PostgreSQL server can use an external OAuth 2.0 identity provider, while the client obtains and presents an access token.

A simplified flow looks like:

Application
    |
    | OAuth token
    v
PostgreSQL Client
    |
    v
PostgreSQL 18
    |
    v
OAuth Token Validator
    |
    v
Identity Provider

PostgreSQL documents configuration parameters including:

  • issuer

  • scope

  • validator

  • map

The issuer identifies the authorization server, while scope defines the OAuth scopes required for authentication and authorization. PostgreSQL can also map the identity provider identity to a PostgreSQL role.

OAuth Authentication Is Not the Same as OpenID Connect Login

This distinction is important.

OAuth 2.0 primarily defines delegated authorization.

OpenID Connect builds an authentication layer on top of OAuth 2.0.

An ASP.NET Core application may use OpenID Connect like this:

Browser
   |
   v
ASP.NET Core
   |
   v
OpenID Connect Provider
   |
   v
ID Token / Claims

PostgreSQL OAuth authentication is different:

.NET Database Client
        |
        v
OAuth Access Token
        |
        v
PostgreSQL 18

PostgreSQL uses the OAuth token to authorize and optionally authenticate the database connection.

So adding PostgreSQL OAuth does not mean ASP.NET Core Identity disappears.

Where ASP.NET Core Identity Fits

ASP.NET Core Identity provides application-level identity functionality.

A typical application may have:

ASP.NET Core
 |
 +--> ApplicationUser
 +--> Roles
 +--> Claims
 +--> Login
 +--> Password Management
 +--> External Login

Microsoft's documentation describes ASP.NET Core Identity as providing UI-oriented login functionality for ASP.NET Core web applications. For applications using external identity platforms, ASP.NET Core can also integrate with OAuth and OpenID Connect providers.

PostgreSQL authentication sits below this layer.

Application Layer
-----------------
ASP.NET Core Identity
Authorization
Business Logic

Database Layer
--------------
PostgreSQL Authentication
Database Roles
Database Privileges

The two layers can use the same identity provider without being the same authentication mechanism.

A Practical Architecture

Consider a multi-tenant SaaS application.

                    Identity Provider
                           |
                 +---------+---------+
                 |                   |
                 v                   v
          ASP.NET Core          PostgreSQL 18
                 |                   |
                 v                   v
          Application User      Database Role
                 |                   |
                 +---------+---------+
                           |
                           v
                       Data Access

The identity provider can be responsible for authenticating the human user.

PostgreSQL OAuth can provide a token-based authentication mechanism for the database connection.

The application still needs authorization logic for deciding what that authenticated user is allowed to do.

Authentication answers:

Who are you?

Authorization answers:

What are you allowed to access?

Those are separate questions.

PostgreSQL OAuth Configuration

PostgreSQL's pg_hba.conf controls client authentication. PostgreSQL 18 supports:

oauth

as an authentication method.

A conceptual configuration looks like:

hostssl all all 10.0.0.0/24 oauth

A more complete OAuth configuration uses authentication options:

hostssl appdb appuser 10.0.0.0/24 oauth
    issuer="https://identity.example.com"
    scope="postgres"

The exact issuer and scope values depend on the identity provider and OAuth validator configuration.

Do not copy these values directly into production.

The PostgreSQL documentation notes that the issuer must match the identity provider's discovery metadata exactly, including formatting and case.

Why hostssl Matters

OAuth tokens are credentials.

You should therefore protect the database connection with TLS.

A typical rule is:

hostssl appdb appuser 10.0.0.0/24 oauth ...

rather than exposing bearer-token authentication over an unencrypted connection.

The complete TLS configuration depends on your PostgreSQL deployment.

The important architectural path is:

OAuth Token
     |
     v
TLS Connection
     |
     v
PostgreSQL

PostgreSQL Role Mapping

OAuth identity and PostgreSQL role names do not necessarily have to be identical.

PostgreSQL supports a map option for mapping identity-provider identities to database usernames. If no mapping is configured, the identity determined by the OAuth validator must match the requested PostgreSQL role name.

Conceptually:

OAuth Subject
     |
     v
Identity Mapping
     |
     v
PostgreSQL Role

For example:

[email protected]
        |
        v
ApplicationUser
        |
        v
reporting_user

The exact mapping strategy depends on how the identity provider and PostgreSQL roles are organized.

Why Database Roles Still Matter

OAuth authentication does not eliminate PostgreSQL privileges.

Suppose a user successfully authenticates.

That does not mean the user should have:

SELECT * FROM sensitive_customers;

PostgreSQL permissions still matter.

For example:

GRANT CONNECT ON DATABASE appdb
TO reporting_user;

GRANT USAGE ON SCHEMA public
TO reporting_user;

GRANT SELECT ON TABLE sales
TO reporting_user;

Do not grant broader permissions simply because OAuth is being used.

The authentication mechanism and database authorization model should remain separate.

ASP.NET Core Configuration

An ASP.NET Core application can continue using its normal authentication setup.

For example, an OpenID Connect application can be configured with:

builder.Services
    .AddAuthentication(options =>
    {
        options.DefaultScheme =
            CookieAuthenticationDefaults.AuthenticationScheme;

        options.DefaultChallengeScheme =
            OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddCookie()
    .AddOpenIdConnect(options =>
    {
        options.Authority =
            builder.Configuration["Identity:Authority"];

        options.ClientId =
            builder.Configuration["Identity:ClientId"];

        options.ClientSecret =
            builder.Configuration["Identity:ClientSecret"];

        options.ResponseType = "code";
        options.UsePkce = true;
    });

Microsoft currently recommends the OpenID Connect authorization-code approach with PKCE for appropriate ASP.NET Core web applications.

The database connection is a separate concern.

The Important Question: Which Token Goes to PostgreSQL?

Do not automatically send the user's ASP.NET authentication token to PostgreSQL.

The token audience, scopes, issuer, lifetime, and intended resource must match the PostgreSQL authentication configuration.

A better architecture is:

Browser
   |
   v
ASP.NET Core
   |
   +--> User Authentication
   |
   +--> Application Authorization
   |
   +--> Database Token Acquisition
                |
                v
          PostgreSQL 18

The database token should be issued for the intended PostgreSQL resource and scopes.

The exact token acquisition mechanism depends on your identity provider and PostgreSQL client configuration.

Using Npgsql in .NET

ASP.NET Core applications commonly use Npgsql to communicate with PostgreSQL.

A conventional connection string might look like:

Host=db.example.com;
Port=5432;
Database=appdb;
Username=appuser;
Password=...
SSL Mode=Require;

With OAuth authentication, the password-based credential model changes.

Conceptually:

Host
Port
Database
Username
OAuth Access Token
TLS

The exact Npgsql OAuth configuration depends on the Npgsql version and the OAuth flow supported by your identity provider.

This is an important area where documentation for the specific Npgsql version should be followed rather than assuming every version has identical OAuth APIs.

Keep Database Credentials Out of Source Code

Even if you are not using PostgreSQL OAuth, avoid:

var connectionString =
    "Host=db;Database=app;Username=admin;Password=secret";

Use configuration providers and secret management instead.

For example:

var connectionString =
    builder.Configuration.GetConnectionString(
        "Postgres");

For production, store sensitive configuration in a managed secret system appropriate for your hosting environment.

Microsoft's ASP.NET Core documentation also recommends keeping application secrets out of application configuration checked into source control.

Token Lifetime Changes the Connection Model

Passwords can remain valid for a long time.

OAuth access tokens generally have limited lifetimes.

That means a database connection architecture needs to consider:

Token
  |
  v
Connection
  |
  v
Token Expiration

Questions to answer include:

  • How is the token obtained?

  • How long is it valid?

  • Does the connection pool reuse connections?

  • What happens when a token expires?

  • How does the client refresh credentials?

  • What happens to an existing connection?

  • How are authentication failures surfaced?

These questions should be tested rather than assumed.

Connection Pooling

ASP.NET Core applications commonly use connection pooling.

A simplified flow is:

Request
   |
   v
DbContext
   |
   v
Npgsql Pool
   |
   v
PostgreSQL

OAuth introduces another credential lifecycle into this design.

You need to test:

Token valid
   |
   v
Connection succeeds

Token near expiration
   |
   v
New connection

Token expired
   |
   v
Refresh / reconnect

The exact behavior depends on the Npgsql version and authentication implementation.

Do not disable connection pooling merely because OAuth is being introduced.

Measure the actual behavior first.

User Identity vs Application Identity

One of the most important architecture decisions is whether PostgreSQL should see:

Individual User

or:

Application / Service Identity

A traditional ASP.NET Core application often uses:

Users
   |
   v
ASP.NET Core
   |
   v
Application DB Role

For example:

All authenticated users
        |
        v
webapp_role

The application then enforces user-level authorization.

A more identity-aware design might be:

User A
   |
   v
OAuth Identity A
   |
   v
PostgreSQL Role A

This can provide stronger database-level identity separation, but it also introduces substantially more operational complexity.

Choose the model deliberately.

Application Authorization Still Matters

Suppose:

PostgreSQL Role:
sales_reader

and the user has:

Application Role:
SalesManager

These are not automatically equivalent.

Your ASP.NET Core application might allow:

SalesManager
  |
  +--> View Sales
  +--> Export Reports

while PostgreSQL only provides:

SELECT

The application remains responsible for enforcing business-level authorization.

Do not assume PostgreSQL authentication replaces ASP.NET Core authorization policies.

Row-Level Security

For multi-tenant applications, PostgreSQL Row-Level Security can provide an additional database-level boundary.

Conceptually:

ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

Then a policy can restrict rows based on a database session context.

The exact design depends on how the authenticated identity is propagated.

A conceptual architecture is:

OAuth Identity
      |
      v
PostgreSQL Role / Session Context
      |
      v
RLS Policy
      |
      v
Tenant Rows

This can provide defense in depth.

However, don't implement RLS based on an untrusted client-supplied tenant identifier.

The tenant context must originate from trusted authentication or server-side authorization logic.

OAuth and Connection Pooling With Multi-Tenant Apps

This becomes particularly interesting in SaaS applications.

Suppose:

Tenant A User
Tenant B User

share the same ASP.NET Core application.

If the database layer uses shared application credentials, the application must enforce tenant boundaries.

If PostgreSQL connections are authenticated using user-specific identities, the database can potentially have more identity information available.

But connection pooling can make incorrect session-state handling dangerous.

A secure architecture should explicitly test:

Tenant A request
      |
      v
Connection A
      |
      v
Tenant A data


Tenant B request
      |
      v
Connection B
      |
      v
Tenant B data

and verify that pooled connections cannot retain security context from a previous request.

Authentication Flow

A simplified OAuth database authentication flow is:

1. Application needs PostgreSQL connection
             |
             v
2. OAuth client obtains access token
             |
             v
3. Client connects to PostgreSQL
             |
             v
4. PostgreSQL requests OAuth authentication
             |
             v
5. Client sends bearer token
             |
             v
6. PostgreSQL validates token
             |
             v
7. Identity mapped to database role
             |
             v
8. PostgreSQL privileges applied

PostgreSQL's SASL implementation includes OAUTHBEARER for token-based federated authentication.

Configure pg_hba.conf Carefully

PostgreSQL processes pg_hba.conf rules sequentially.

The first matching rule is used.

There is no fallback to a later rule if authentication fails.

For example:

hostssl appdb appuser 10.0.0.0/24 oauth ...
hostssl appdb all     10.0.0.0/24 scram-sha-256

The first rule that matches appdb, appuser, and the client address controls authentication.

This makes rule ordering important.

Avoid broad rules such as:

host all all 0.0.0.0/0 oauth ...

unless the network and identity architecture explicitly require such exposure.

Validate pg_hba.conf

PostgreSQL 18 provides the pg_hba_file_rules view.

It can help identify configuration errors before or after changes. The view exposes rule ordering, authentication methods, and errors associated with invalid entries.

For example:

SELECT
    rule_number,
    line_number,
    type,
    database,
    user_name,
    address,
    auth_method,
    error
FROM pg_hba_file_rules
ORDER BY rule_number;

If error is not null, investigate the corresponding rule.

This is useful during deployment automation.

Reload Configuration Safely

After changing pg_hba.conf, PostgreSQL needs to reload the configuration.

For example:

SELECT pg_reload_conf();

PostgreSQL documents configuration reload behavior and recommends the pg_hba_file_rules view for checking authentication rules.

Do not edit production authentication rules without validating the resulting access behavior.

A malformed or overly restrictive rule can lock applications out of the database.

PostgreSQL OAuth vs Password Authentication

AreaPassword / SCRAMPostgreSQL OAuth
CredentialPasswordOAuth access token
External identity providerNot requiredRequired
Token expirationNo token lifecycleYes
Centralized identityLimitedStronger integration
pg_hba.confscram-sha-256oauth
Secret rotationPassword rotationToken lifecycle
SSO ecosystemExternalNatural fit
Operational complexityLowerHigher
Database identity mappingRole/passwordOAuth identity + mapping
Best fitTraditional applicationsFederated identity environments

PostgreSQL continues to support multiple authentication mechanisms; OAuth is an additional option rather than a replacement for all existing methods.

OAuth vs ASP.NET Core Identity

CapabilityASP.NET Core IdentityPostgreSQL OAuth
User registrationYesNo
Password managementYesNo
Application loginYesNo
Application rolesYesDatabase roles are separate
ClaimsYesToken claims / identity mapping
Database connection authenticationNoYes
OAuth provider integrationYesYes
PostgreSQL role mappingNoYes
Database privilegesNoYes
Row-level database securityNoCan participate in design

The two technologies should usually be viewed as complementary rather than competing.

Common Mistakes

Assuming PostgreSQL OAuth Replaces ASP.NET Core Identity

It does not.

PostgreSQL OAuth authenticates database connections.

ASP.NET Core Identity handles application identity.

Sending the User's ID Token to PostgreSQL

Do not assume an ID token is an appropriate database access token.

Use a token intended for the PostgreSQL resource and configured scopes.

Ignoring TLS

Bearer tokens should not be treated like ordinary application data.

Use encrypted database connections.

Giving Every User a Superuser Role

OAuth does not change PostgreSQL's privilege model.

Use least privilege.

Ignoring Token Expiration

Database connections and token lifetimes need to be tested together.

Misconfiguring pg_hba.conf

Rule ordering matters.

A broad earlier rule can unexpectedly capture connections intended for another authentication mechanism.

Treating Authentication as Authorization

Successfully authenticating a user does not mean that user should access every table.

Troubleshooting PostgreSQL OAuth

no pg_hba.conf entry

This means PostgreSQL did not find a matching authentication rule.

Check:

Host
Port
Database
User
Client IP
Connection type
pg_hba.conf ordering

PostgreSQL documents this as a common authentication failure.

OAuth Issuer Mismatch

Check the issuer exactly.

PostgreSQL's documentation specifically warns that the configured issuer and discovery metadata must match exactly.

Token Validation Fails

Check:

  • Issuer

  • Audience

  • Scope

  • Expiration

  • Signature

  • Validator configuration

  • Identity mapping

User Authenticates but Database Access Fails

Authentication and authorization are separate.

Check:

SELECT current_user;

Then inspect:

Database CONNECT
Schema USAGE
Table privileges
Role membership
RLS policies

pg_hba.conf Changes Do Not Work

Use:

SELECT *
FROM pg_hba_file_rules;

Look for parsing errors and verify rule ordering.

Production Checklist

Before deploying PostgreSQL OAuth with an ASP.NET Core application, verify:

[ ] PostgreSQL 18 is being used
[ ] OAuth support is available in the PostgreSQL build
[ ] Identity provider is configured
[ ] Issuer exactly matches discovery metadata
[ ] Required scopes are defined
[ ] OAuth validator is configured
[ ] Database role mapping is tested
[ ] TLS is enabled
[ ] pg_hba.conf rules are restricted
[ ] Rule ordering is verified
[ ] Database privileges follow least privilege
[ ] Token expiration is tested
[ ] Connection pooling is tested
[ ] Application authorization remains enabled
[ ] Tenant isolation is tested
[ ] Secrets are not committed to source control
[ ] Failure and recovery scenarios are tested

A Recommended Architecture for .NET Applications

For many enterprise applications, a sensible architecture is:

                    Identity Provider
                    OAuth / OIDC
                         |
              +----------+----------+
              |                     |
              v                     v
        ASP.NET Core          Token Acquisition
              |                     |
              v                     v
      App Authentication      PostgreSQL OAuth
              |                     |
              v                     v
       Authorization         PostgreSQL 18
              |                     |
              +----------+----------+
                         |
                         v
                       Data

The application identity system answers:

Who is the user?

The application authorization system answers:

What can the user do?

PostgreSQL answers:

Can this database client authenticate?

PostgreSQL privileges answer:

What can this database role access?

Keeping these questions separate produces a much clearer security architecture.

Conclusion

PostgreSQL 18's OAuth support provides .NET developers with a new way to integrate PostgreSQL authentication into environments already built around centralized OAuth 2.0 identity providers. PostgreSQL 18 adds the oauth method to pg_hba.conf, OAuth-related client support, and token-validation infrastructure.

But the feature should not be viewed as a replacement for ASP.NET Core Identity.

The two operate at different layers:

ASP.NET Core Identity
        |
        v
Application Authentication
        |
        v
Application Authorization
        |
        v
PostgreSQL OAuth
        |
        v
Database Role
        |
        v
Database Privileges

That layered approach is especially useful for enterprise applications where identity is already centralized through an OAuth or OpenID Connect provider.

The key is to avoid treating OAuth as a magic security switch.

You still need:

  • Least-privilege database roles

  • Correct pg_hba.conf configuration

  • TLS

  • Token lifecycle management

  • Application authorization

  • Tenant isolation

  • Database privileges

  • Careful connection-pooling behavior

PostgreSQL 18 makes the authentication layer more compatible with modern identity infrastructure.

The responsibility for building a secure application architecture, however, still belongs to the application and platform team.

Frequently Asked Questions

Does PostgreSQL 18 support OAuth authentication?

Yes. PostgreSQL 18 adds an oauth authentication method to pg_hba.conf and provides OAuth-related client and server support.

Does PostgreSQL OAuth replace ASP.NET Core Identity?

No. ASP.NET Core Identity manages application users and authentication features, while PostgreSQL OAuth authenticates database connections.

Can I use Microsoft Entra ID or another OAuth provider?

PostgreSQL's OAuth design supports third-party OAuth 2.0 identity providers. The exact configuration depends on the provider, discovery metadata, scopes, token validation mechanism, and client support.

Do I still need PostgreSQL roles?

Yes. OAuth authentication does not eliminate PostgreSQL's authorization model. Database roles and privileges still determine what an authenticated database user can access.

Is OAuth more secure than passwords?

It can provide advantages in centralized identity, token lifecycle, and federation, but security depends on the complete implementation. Incorrect scopes, role mapping, TLS configuration, or excessive database privileges can still create vulnerabilities.

Can I use PostgreSQL OAuth with an existing ASP.NET Core application?

Potentially, yes. The application can continue using ASP.NET Core authentication while its PostgreSQL client uses OAuth for database authentication. The exact implementation depends on the PostgreSQL deployment, identity provider, and versions of the .NET PostgreSQL client library being used.

What should I check first when PostgreSQL OAuth fails?

Start with pg_hba.conf, the exact issuer, required scopes, OAuth validator configuration, role mapping, TLS, and PostgreSQL server logs. PostgreSQL also provides pg_hba_file_rules to help identify authentication configuration problems.