# Security and Encryption

## Password management

The simplest way to log into PostgreSQL is by specifying a `Username` and a `Password` in your connection string. Depending on how your PostgreSQL is configured (in the `pg_hba.conf` file), Npgsql will send the password via SASL (SCRAM-SHA-256), in MD5 or in clear-text (not recommended).

If a `Password` is not specified and your PostgreSQL is configured to request a password, Npgsql will look for a standard PostgreSQL password file. If you specify the `Passfile` connection string parameter, the file it specifies will be used. If that parameter isn't defined, Npgsql will look under the path taken from `PGPASSFILE` environment variable. If the environment variable isn't defined, Npgsql will fall back to the system-dependent default directory which is `$HOME/.pgpass` for Unix and `%APPDATA%\postgresql\pgpass.conf` for Windows.

### Auth token rotation and dynamic password

In some cloud scenarios, logging into PostgreSQL is done with an auth token that is rotated every time interval (e.g. one hour). Npgsql has a built-in periodic password provider mechanism, which allows using an up-to-date access token with zero effort:

    var dataSourceBuilder = new NpgsqlDataSourceBuilder(...);
    dataSourceBuilder.UsePasswordProvider(
        passwordProvider: _ => throw new NotSupportedException(),
        passwordProviderAsync: (builder, token) => /* code to fetch the new access token */);
    await using var dataSource = dataSourceBuilder.Build();

Every time a new physical connection needs to be opened to PostgreSQL, either the synchronous `passwordProvider` or the asynchronous `passwordProviderAsync` will be called (depending whether you used `Open()` or `OpenAsync()`). Since modern .NET applications are encouraged to always use asynchronous I/O, it's good practice to simply throw in the synchronous password provider, as above.

Note that since the password provider is invoked every time a physical connection is opened, it shouldn't take too long; typically, this would call into a cloud provider API (e.g. Azure Managed Identity), which itself implements a caching mechanism. However, if no such caching is done and the code could take a while, you can instead instruct Npgsql to cache the auth token for a given amount of time:

    dataSourceBuilder.UsePeriodicPasswordProvider(
        (settings, cancellationToken) =>  /* async code to fetch the new access token */,
        TimeSpan.FromMinutes(55), // Interval for refreshing the token
        TimeSpan.FromSeconds(5)); // Interval for retrying after a refresh failure

Finally, if you already have code running when the auth token changes, you can simply inject it manually at any time into a working data source:

    dataSource.Password = <new password>;

Any physical connection that's opened after this point will use the newly-injected password.

## GSS session encryption (GSS-API)

Connections to PostgreSQL are unencrypted by default, but you can turn on session encryption if you wish. Npgsql 10 supports GSS-API for session encryption, and defaults to it if PostgreSQL is set up to support GSS-API (GSS-API is preferred over SSL/TLS).

To use GSS-API, configure your PostgreSQL for GSS-API session encryption (docs). Once that's done, you can use `GSS Encryption Mode` in your connection string to configure support (this is similar to the PG `gccencmode` parameter):

GSS Encryption Mode | Meaning
--- | ---
Disable | Only try a non-GSSAPI-encrypted connection.
Prefer (default) | If there are GSSAPI credentials present (i.e., in a credentials cache), first try a GSSAPI-encrypted connection; if that fails or there are no credentials, try a non-GSSAPI-encrypted connection.
Require | Only try a GSSAPI-encrypted connection.

The default mode is `Prefer`, which allows GSS-API session encryption but does not require it.

##### Note

Some Linux environments do not have Kerberos installed; since Npgsql 10.0 defaults to `Prefer`, it will attempt to get GSSAPI credentials, and may generate an error such as the following: Cannot load library libgssapi_krb5.so.2: cannot open shared object file: No such file or directory Npgsql internally handles this and falls back to connecting without GSSAPI, so the error is harmless. You can specify `GSS Encryption Mode=Disable` to stop Npgsql from trying to use GSSAPI and remove the error.

## Encryption (SSL/TLS)

As an alternative to GSS-API, you can use SSL/TLS. First, you have to set up your PostgreSQL to receive SSL/TLS connections as described here. Once that's done, specify `SSL Mode` in your connection string as detailed below.

The following `SSL Mode` values are supported (see the PostgreSQL docs for more details):

SSL Mode | Eavesdropping protection | Man-in-the-middle protection | Statement
--- | --- | --- | ---
Disable | No | No | I don't care about security, and I don't want to pay the overhead of encryption.
Allow | Maybe | No | I don't care about security, but I will pay the overhead of encryption if the server insists on it.
Prefer (default) | Maybe | No | I don't care about encryption, but I wish to pay the overhead of encryption if the server supports it.
Require1 | Yes | No | I want my data to be encrypted, and I accept the overhead. I trust that the network will make sure I always connect to the server I want.
VerifyCA | Yes | Depends on CA policy | I want my data encrypted, and I accept the overhead. I want to be sure that I connect to a server that I trust.
VerifyFull | Yes | Yes | I want my data encrypted, and I accept the overhead. I want to be sure that I connect to a server I trust, and that it's the one I specify.

The default mode is `Prefer`, which allows SSL but does not require it, and does not validate certificates.

### SSL Negotiation

Starting with Npgsql 9.0, you can control how SSL encryption is negotiated while connecting to PostgreSQL via the `SSL Negotiation` connection string parameter, or via the `PGSSLNEGOTIATION` environment variable. In the default `postgres` mode, the client first asks the server if SSL is supported. In `direct` mode, the client starts the standard SSL handshake directly after establishing the TCP/IP connection.

Enabling this option (by changing it to `direct` mode) can improve latency while opening a physical connection by removing one round trip.

This option is only supported with PostgreSQL 17 and above.

### Advanced server certificate validation

If the root CA of the server certificate isn't installed in your machine's CA store, validation will fail. Either install the certificate in your machine's CA store, or point to it via the `Root Certificate` connection string parameter or via the `PGSSLROOTCERT` environment variable.

Note that Npgsql does not perform certificate revocation validation by default, since this is an optional extension not implemented by all providers and CAs. To turn on certificate revocation validation, specify `Check Certificate Revocation=true` on the connection string.

Finally, if the above options aren't sufficient for your scenario, you can call NpgsqlDataSourceBuilder.UseUserCertificateValidationCallback to provide your custom server certificate validation logic (this gets set on the underlying .NET `SslStream`).

### Client certificates

PostgreSQL may be configured to require valid certificates from connecting clients for authentication. Npgsql automatically sends client certificates specified in the following places:

- The `SSL Certificate` connection string parameter.
- The `PGSSLCERT` environment variable.
- The default locations of `~/.postgresql/postgresql.crt` (on Unix) or `%APPDATA%\postgresql\postgresql.crt` (on Windows)

To provide a password for a client certificate, set either the `SSL Password` (6.0 and higher) or `Client Certificate Key` (5.0 and lower) connection string parameter.

Finally, you can call NpgsqlDataSourceBuilder.UseClientCertificate, NpgsqlDataSourceBuilder.UseClientCertificates or NpgsqlDataSourceBuilder.UseClientCertificatesCallback to programmatically provide a certificate, multiple certificates or a callback which returns certificates (this works like on the underlying .NET `SslStream`).

##### Note

Npgsql supports .PFX and .PEM certificates starting with 6.0. Previously, only .PFX certificates were supported.

## Password-less authentication (GSS/SSPI/Kerberos)

Logging in with a username and password may not be ideal, since your application must have access to your password, and raise questions around secret management. An alternate way of authenticating is to use GSS or SSPI to negotiate Kerberos. The advantage of this method is that authentication is handed off to your operating system, using your already-open login session. Your application never needs to handle a password. You can use this method for a Kerberos login, Windows Active Directory or a local Windows session.

Instructions on setting up Kerberos and SSPI are available in the PostgreSQL auth methods docs. Some more instructions for SSPI are available here.

Once your PostgreSQL is configured correctly, it will require GSS/SSPI authentication from Npgsql at login, and you can simply drop the `Password` parameter from the connection string. However, Npgsql must still send a username to PostgreSQL. If you specify a `Username` connection string parameter, Npgsql will send that as usual. If you omit it, Npgsql will attempt to detect your system username, including the Kerberos realm. Note that by default, PostgreSQL expects your Kerberos realm to be sent in your username (e.g. `username@REALM`); you can have Npgsql detect the realm by setting `Include Realm` to true in your connection string. Alternatively, you can disable add `include_realm=0` in your PostgreSQL's pg_hba.conf entry, which will make it strip the realm. You always have the possibility of explicitly specifying the username sent to PostgreSQL yourself.

Note that in versions of Npgsql prior to 8.0, use of GSS/SSPI authentication requires that `Integrated Security=true` be specified on the connection string. This requirement has been removed in Npgsql 8.0.