Skip to main content

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​

MethodPlatformNotes
SCRAM-SHA-256Linux, WindowsRFC 7677. Default for modern PostgreSQL (scram-sha-256 in pg_hba.conf)
SCRAM-SHA-256-PLUSLinux, Windows (TLS)SCRAM with RFC 5929 tls-server-end-point channel binding
MD5Linux, WindowsLegacy md5 auth method
passwordLinux, WindowsCleartext (password auth method) — only safe under TLS
Integrated (SSPI / Negotiate)Windows onlyLogged-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_saslprep when 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 optionShort formPurpose
adbc.arpepgsql.username / .passwordusername / 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.sslmodesslmode (connection only)disable / prefer (default) / require / verify-ca / verify-full
adbc.arpepgsql.ssl_root_certssl_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_bindingchannel_binding (connection only)prefer (default) / require / disable; require enforces SCRAM-SHA-256-PLUS
adbc.arpepgsql.require_password_encryptionrequire_password_encryption (connection only)false (default) / true; refuse to send a cleartext or MD5 password over an unencrypted transport
adbc.arpepgsql.krb5.spnkrb5_spn (connection only)Integrated auth: use this SPN verbatim instead of the derived POSTGRES/<server>
adbc.arpepgsql.krbsrvnamekrbsrvname (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.

Python
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=prefer gives no MITM protection. Like libpq, prefer falls back to plaintext when the server answers the SSLRequest with N, and that reply is unauthenticated. On an untrusted network use sslmode=verify-full and/or channel_binding=require (which binds SCRAM to the TLS channel and refuses a PLUS-stripping downgrade). require encrypts but does not verify the certificate.

Integrated authentication (Windows)​

Version

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 the server value 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 with adbc.arpepgsql.krbsrvname when the server runs under a different service name, or the whole SPN with adbc.arpepgsql.krb5.spn (for example when the SPN is registered under another host name); krb5.spn wins when both are set.
  • Mutual authentication is always required: the driver refuses an AuthenticationOk from 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.username to the PostgreSQL role. The server accepts it only if your Windows identity maps to that role (pg_hba.conf options such as include_realm=0, or a pg_ident.conf map). A password is rejected.

Platform support​

ModeLinuxWindows
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​

sslmodeEncryptsChecks the certificateChecks the host name
disableno——
prefer (default)if the server agreesnono
requireyesnono
verify-cayeschainno
verify-fullyeschainyes
  • 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.
  • require never checks the certificate, even when ssl_root_cert is set. libpq upgrades require to verify-ca when a root certificate file exists; ArpePGSQL does not. Use verify-ca or verify-full to 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: require fails and prefer has 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:

  1. ssl_root_cert (a PEM file; it may hold several certificates);
  2. the PGSSLROOTCERT environment variable;
  3. OpenSSL's default locations: the SSL_CERT_FILE / SSL_CERT_DIR environment variables, else /etc/ssl/cert.pem and /etc/ssl/certs/ on Linux.

~/.postgresql/root.crt is not read, and sslrootcert=system is taken as a file name.

Client OSWithout a root certificate setting
Debian, UbuntuWorks: /etc/ssl/certs holds the system CAs.
RHEL, Rocky, AlmaLinux 8 and newerFails 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.
WindowsFails: 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.