Authentication
ArpePGSQL supports PostgreSQL password-family authentication (SCRAM-SHA-256, MD5, cleartext) on every platform, integrated authentication on Windows (SSPI), TLS, and SCRAM channel binding. This page is the reference for the options and credential modes.
Authentication methods
| Method | Platform | Notes |
|---|---|---|
| SCRAM-SHA-256 | Linux, Windows | RFC 7677. Default for modern PostgreSQL (scram-sha-256 in pg_hba.conf) |
| SCRAM-SHA-256-PLUS | Linux, Windows (TLS) | SCRAM with RFC 5929 tls-server-end-point channel binding |
| MD5 | Linux, Windows | Legacy md5 auth method |
| password | Linux, Windows | Cleartext (password auth method) — only safe under TLS |
| Integrated (SSPI / Negotiate) | Windows only | Logged-in Windows identity; answers the server's gss or sspi method; mutual authentication always enforced |
The driver selects the method from what the server requests in the
Authentication* message; you choose between password-family and
integrated auth via the options below.
Non-ASCII passwords: SCRAM uses the password bytes as-is; SASLprep (RFC 4013) normalisation is not applied. Printable-ASCII passwords (the common case) are unaffected. A password containing non-ASCII code points that the server normalised with
pg_saslprepwhen storing the verifier may fail to authenticate — use an ASCII password, or pre-normalise it to the same form the server stored.
Option / keyword reference
Options take a dotted database-level form (adbc.arpepgsql.<key>, passed to
AdbcDatabaseSetOption / db_kwargs); the database form is copied to the
connection before the session opens. Several also have a short
connection-level form (passed to AdbcConnectionSetOption / conn_kwargs).
The short forms marked "connection only" below are rejected as database
options — in db_kwargs use the adbc.arpepgsql.* name. The connection
string also accepts ADO.NET-style keywords (e.g. User ID, Password,
Integrated Security). Full matrix in
Connection → Database-level vs connection-level keys.
| Database option | Short form | Purpose |
|---|---|---|
adbc.arpepgsql.username / .password | username / password (both levels) | SQL login credentials; when unset, taken from PGUSER / PGPASSWORD / ~/.pgpass (since v0.4.5, see PostgreSQL environment variables) |
adbc.arpepgsql.auth_type=integrated (or adbc.arpepgsql.trusted=true) | trusted (database only), auth_mode (connection only) | Enable integrated authentication (Windows only) |
adbc.arpepgsql.sslmode | sslmode (connection only) | disable / prefer (default) / require / verify-ca / verify-full |
adbc.arpepgsql.ssl_root_cert | ssl_root_cert (connection only) | PEM root-CA file for verify-ca / verify-full (default: PGSSLROOTCERT, else OpenSSL's default locations, see TLS) |
adbc.arpepgsql.channel_binding | channel_binding (connection only) | prefer (default) / require / disable; require enforces SCRAM-SHA-256-PLUS |
adbc.arpepgsql.require_password_encryption | require_password_encryption (connection only) | false (default) / true; refuse to send a cleartext or MD5 password over an unencrypted transport |
adbc.arpepgsql.krb5.spn | krb5_spn (connection only) | Integrated auth: use this SPN verbatim instead of the derived POSTGRES/<server> |
adbc.arpepgsql.krbsrvname | krbsrvname (both levels) | Integrated auth: replace the service part of the derived SPN (default POSTGRES) |
With integrated auth, set username to the PostgreSQL role to log in as (the
server checks that your Windows identity may use it); a password is rejected.
import adbc_driver_manager.dbapi as dbapi
conn = dbapi.connect(driver="arpepgsql", db_kwargs={
"adbc.arpepgsql.server": "db.example.com",
"adbc.arpepgsql.username": "alice",
"adbc.arpepgsql.auth_type": "integrated",
"adbc.arpepgsql.krb5.spn": "POSTGRES/db.example.com", # not "krb5_spn"
"adbc.arpepgsql.sslmode": "verify-full", # not "sslmode"
})
Security — the default
sslmode=prefergives no MITM protection. Like libpq,preferfalls back to plaintext when the server answers theSSLRequestwithN, and that reply is unauthenticated. On an untrusted network usesslmode=verify-fulland/orchannel_binding=require(which binds SCRAM to the TLS channel and refuses a PLUS-stripping downgrade).requireencrypts but does not verify the certificate.
Integrated authentication (Windows)
Since ArpePGSQL v0.2.0.
Integrated (trusted) authentication is available with the Windows driver only. The Linux driver does not support it: requesting it there fails at connect time with "Trusted/integrated authentication is unavailable". On Linux, use a password-family method (SCRAM-SHA-256 recommended) over TLS.
On Windows the driver authenticates as the logged-in Windows user through
the SSPI Negotiate package; no password, Kerberos configuration or ticket
management is needed on the client. The server side is a gss (or, on a Windows server,
sspi) line in pg_hba.conf.
- Service principal name. The target SPN is
POSTGRES/<server>(no port), built from theservervalue as given. Connect by the fully qualified host name under which the SPN is registered, not by IP address or an alias. Override the service part withadbc.arpepgsql.krbsrvnamewhen the server runs under a different service name, or the whole SPN withadbc.arpepgsql.krb5.spn(for example when the SPN is registered under another host name);krb5.spnwins when both are set. - Mutual authentication is always required: the driver refuses an
AuthenticationOkfrom a server that never completed the exchange, and refuses password-family requests while integrated auth is active. If Windows does not report mutual authentication for the session, the login fails with "server did not provide mutual authentication"; registering the SPN and connecting by fully qualified host name lets Kerberos be used. - Role. Set
adbc.arpepgsql.usernameto the PostgreSQL role. The server accepts it only if your Windows identity maps to that role (pg_hba.confoptions such asinclude_realm=0, or apg_ident.confmap). A password is rejected.
Platform support
| Mode | Linux | Windows |
|---|---|---|
| SQL login (SCRAM/MD5/password) | ✓ | ✓ |
| TLS and SCRAM channel binding | ✓ | ✓ |
| Integrated (SSPI / Negotiate) | — | ✓ |
TLS
ArpePGSQL asks for TLS with the PostgreSQL SSLRequest message, before the
login. Direct TLS (PostgreSQL 17's sslnegotiation=direct) is not supported.
The options are in
Connection → TLS & encryption options.
Modes
sslmode | Encrypts | Checks the certificate | Checks the host name |
|---|---|---|---|
disable | no | — | — |
prefer (default) | if the server agrees | no | no |
require | yes | no | no |
verify-ca | yes | chain | no |
verify-full | yes | chain | yes |
- Under
prefer, a server that declines TLS gets a plaintext session, and the driver prints a warning to standard error. Once the server has agreed to TLS, a failed handshake is an error; there is no retry in clear. requirenever checks the certificate, even whenssl_root_certis set. libpq upgradesrequiretoverify-cawhen a root certificate file exists; ArpePGSQL does not. Useverify-caorverify-fullto have it checked.channel_binding=require(SCRAM-SHA-256-PLUS) ties the login to the server certificate and needs TLS.gssencmode(GSS transport encryption) is not available in the released binaries:requirefails andpreferhas no effect.
Protocol versions
TLS 1.2 is the minimum and TLS 1.3 is used when the server offers it. There is
no ssl_min_protocol_version / ssl_max_protocol_version option.
Independent of the host's TLS stack
Because the driver brings its own OpenSSL, the TLS versions it can use do not depend on the host. A server that only accepts TLS 1.3 works even where the host's own TLS stack has no TLS 1.3: for example Windows Server 2019 and older (Schannel), or a Linux host whose system OpenSSL is 1.0.x. The limit on Linux is the C library: the released binary needs glibc 2.28 or later (RHEL 8, Debian 10, Ubuntu 20.04 or newer), so RHEL 7 is not supported.
Where trusted certificates come from
ArpePGSQL carries its own copy of OpenSSL 3, linked into the library (the
Linux release is built with OpenSSL 3.6.4). It never uses the operating
system's TLS stack or certificate store. For verify-ca / verify-full, the
CAs come from, in this order:
ssl_root_cert(a PEM file; it may hold several certificates);- the
PGSSLROOTCERTenvironment variable; - OpenSSL's default locations: the
SSL_CERT_FILE/SSL_CERT_DIRenvironment variables, else/etc/ssl/cert.pemand/etc/ssl/certs/on Linux.
~/.postgresql/root.crt is not read, and sslrootcert=system is taken as
a file name.
| Client OS | Without a root certificate setting |
|---|---|
| Debian, Ubuntu | Works: /etc/ssl/certs holds the system CAs. |
| RHEL, Rocky, AlmaLinux 8 and newer | Fails with "unable to get local issuer certificate": the CA bundle lives under /etc/pki. Set ssl_root_cert, or SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt. |
| Windows | Fails: the Windows certificate store is not read. Set ssl_root_cert to a PEM file holding the CA. |
Managed services (AWS RDS, Azure Database for PostgreSQL, Google Cloud SQL, …)
publish their CA bundles: download yours and pass it as ssl_root_cert.
Host name check and SNI
With verify-full, the server name must match the certificate: a DNS name
against its DNS SANs (or its CN when it has none), an IP address against its IP
SANs. A wildcard must be the whole first label (*.example.com). Always set
the server explicitly: when no server is set, the driver connects to
localhost but does not check the host name. SNI is always sent, including
for an IP address, and cannot be turned off.
Client certificates
Not supported: sslcert / sslkey do not exist, and the cert
authentication method cannot be used.
OpenSSL configuration
Like any OpenSSL 3 program, the driver reads an OpenSSL configuration file at
the first TLS connection: the file named by OPENSSL_CONF, else
/etc/ssl/openssl.cnf on Linux. Settings there, such as cipher lists or the
security level, apply. The driver's TLS 1.2 minimum always wins. RHEL's system
crypto-policies live under /etc/pki/tls/openssl.cnf, so they apply only if
that file is the one loaded (for example with
OPENSSL_CONF=/etc/pki/tls/openssl.cnf).
TLS errors are listed under Troubleshooting → TLS / certificates.