Authentication
The authentication step of a pgJDBC connection runs after the optional TLS / GSS upgrade and before the connection is handed back to the application. The server, not the client, picks the authentication method based on the pg_hba.conf rule that matches the connection’s source, and the driver responds to whatever message arrives. This page describes the methods the driver supports, how the negotiation resolves, and the connection properties that bound it (allow-list which methods are acceptable, require channel binding, swap in a custom credential source).
For specific error messages on this path (Channel Binding is required, but SSL is not in use, Authentication method is not allowed by requireAuth, and friends), see SCRAM authentication failed
. For the TLS layer that sits underneath, see SSL / TLS
. For the recommended-default posture, see Configure SSL/TLS (in Quick start)
.
Methods the driver supports
org.postgresql.core.AuthMethod enumerates the six methods the server may request:
| Method | Server-side trigger | Notes |
|---|---|---|
scram-sha-256 | pg_hba.conf scram-sha-256, or md5 with a SCRAM-stored password | Recommended. Salted, iterated PBKDF2. The only password method that supports channel binding. New passwords are stored as SCRAM by default since PostgreSQL 14. |
md5 | pg_hba.conf md5 with an MD5-stored password | Hashed but weak by modern standards; offers no channel binding. Migrate the user’s password to SCRAM by re-setting it while password_encryption = scram-sha-256 is in effect. |
password (cleartext) | pg_hba.conf password method | The password is sent verbatim in the startup exchange. Only safe over TLS (and even then SCRAM is strictly better). |
gss | pg_hba.conf gss method | Kerberos via GSSAPI on *nix (and on Windows when gsslib=gssapi). |
sspi | pg_hba.conf sspi method | Windows native single-sign-on via SSPI. Requires waffle-jna on the classpath. |
none | pg_hba.conf trust method | No credentials. Reasonable for a Unix-domain-socket dev loop, dangerous over the network. |
The two extension-style methods, gss and sspi, are dispatched to the Kerberos stack and are tuned by gsslib, gssEncMode, kerberosServerName, jaasApplicationName, jaasLogin, gssUseDefaultCreds, useSpnego, and sspiServiceClass. See Kerberos, GSSAPI, SSPI
for the dispatch model, JAAS configuration, the waffle-jna compatibility matrix, and gssEncMode for GSS-encrypted connections.
How the negotiation resolves
After the startup packet, the server sends an AuthenticationRequest message naming the method to use, picked by matching the connection against pg_hba.conf. The driver routes the message to a handler:
- For
md5andpassword,AuthenticationPluginManager.withPasswordis called to obtain the credential, sends it, and zero-wipes thechar[]before the call returns. - For
scram-sha-256(SASL),ScramAuthenticatorruns the four-message SCRAM exchange (SASLInitialResponse→SASLContinue→SASLResponse→SASLFinal) with the chosen mechanism:SCRAM-SHA-256-PLUSwhen channel binding is in play, plainSCRAM-SHA-256otherwise. - For
gssandsspi, the dedicated Kerberos / SSPI paths run. - For
none(trust), the driver sends nothing and proceeds to the next startup message.
The application has no direct hand in this; the choice is the server’s. The driver’s role is to (a) respond correctly to whatever the server asks, (b) refuse to respond if requireAuth forbids the requested method, and (c) decide whether channel binding can be negotiated for SCRAM.
Recommended baseline
For any production connection over a public or shared network:
sslmode=verify-full # validate cert chain and SAN; defense against MITM
sslrootcert=/path/to/ca.crt # what we validate the chain against
channelBinding=require # tie the SCRAM exchange to the TLS channel
This is the combination Configure SSL/TLS (in Quick start) recommends. It defends against the credible attacker (one who can intercept and re-negotiate the TLS handshake but does not have the server’s private key) by ensuring (a) the certificate presented is the one we expect, and (b) the SCRAM exchange is bound to that TLS session.
For an extra notch of defence in depth, add an explicit requireAuth=scram-sha-256 so the driver refuses MD5 even if pg_hba.conf is later relaxed; see the next section.
requireAuth: allow-list / deny-list
requireAuth
(introduced in 42.7.0) accepts a comma-separated list of method names matching the table above, with optional ! prefix to flip each entry into a negative. The driver evaluates the list in one of two modes:
- Allow-list: entries have no
!. The driver only accepts a method that appears in the list. Example:requireAuth=scram-sha-256rejects MD5, cleartext password, and trust. - Deny-list: every entry has
!. The driver accepts any method not in the list. Example:requireAuth=!password,!md5,!nonerejects the three weak options and accepts SCRAM / GSS / SSPI.
Mixing the two (requireAuth=scram-sha-256,!md5) fails parsing with requireAuth cannot mix positive and negative authentication methods (see AuthMethod.parseRequireAuth). Pick a stance.
The check fires before the driver responds to the AuthenticationRequest, so no credentials are ever transmitted under a rejected method. A mismatch raises PSQLException with SQLState 08004 (CONNECTION_REJECTED) and the message Authentication method is not allowed by requireAuth. See SCRAM authentication failed § Authentication method is not allowed by requireAuth
for the runtime behaviour.
channelBinding
channelBinding
(introduced in 42.7.0, default prefer) controls whether the SCRAM exchange is tied to the TLS channel:
require: refuse SCRAM-SHA-256 without-PLUS; refuse the connection entirely if the server doesn’t offer a-PLUSmechanism or if no TLS session is in use. This is the production posture.prefer(default): use channel binding when both client and server support it, otherwise fall back to plain SCRAM-SHA-256. Suitable for mixed environments where some servers are too old for-PLUS.disable: never request channel binding, even if available.
Channel binding works only with SCRAM-SHA-256 (the tls-server-end-point binding hashes the server’s TLS certificate into the SCRAM exchange). With prefer or disable, MD5, cleartext password, GSS, SSPI, and trust proceed without a binding; with require, current drivers reject non-SASL authentication before credentials are sent. Before 42.7.7 the driver allowed channelBinding=require to silently pass when the server selected a non-SASL method, a downgrade attack vector that was fixed via CVE-2025-49146
; pair channelBinding=require with requireAuth=scram-sha-256 on older driver versions, or upgrade to 42.7.7+.
For the specific channel-binding error strings, see SCRAM authentication failed .
scramMaxIterations
scramMaxIterations
(default 100000, introduced in 42.7.11) caps the PBKDF2 iteration count the driver will accept from the server. Without it, a malicious or compromised server could pick an arbitrarily high iteration count and force the client to burn CPU before the connection even completes: a quiet denial-of-service vector.
The cap is checked before PBKDF2 runs. A server advertising more than scramMaxIterations rounds is refused with the message Server requested N SCRAM PBKDF2 iterations, which exceeds the client-side limit of M. Raise the value only if you trust the server and have audited that it legitimately uses a higher count; setting 0 disables the check entirely (not recommended).
AuthenticationPlugin: custom credentials
When the password belongs to a credential source that isn’t a string in the URL (IAM-generated short-lived tokens, Vault, a hardware token, a keyring), implement org.postgresql.plugin.AuthenticationPlugin
and name the class in authenticationPluginClassName
.
The contract is short:
public interface AuthenticationPlugin {
char @Nullable [] getPassword(AuthenticationRequestType type) throws PSQLException;
}
type is one of CLEARTEXT_PASSWORD, MD5_PASSWORD, SASL (SCRAM), GSS. Returning null refuses the request, useful for per-type policy (“we never serve cleartext”).
Three contract points to honour:
- Return a fresh
char[]on every call. The driver overwrites the array with zeroes after use (seeAuthenticationPluginManager.withPassword); reusing a cached array would leave the buffer wiped on the next call. - The class must have a public constructor that
ObjectFactorycan use. For authentication plugins the driver first looks for a publicPropertiesconstructor, then falls back to a public no-arg constructor. If instantiation fails, the driver raisesUnable to load Authentication Plugin ...with SQLState22023(INVALID_PARAMETER_VALUE). - Don’t perform unbounded work in
getPassword. The method runs on the connection-establishing thread; a hang here looks identical to a server-side hang and is bounded byloginTimeout(see Timeouts ) rather than by anything in the plugin.
The plugin is not consulted for trust auth: the server never asks for a password and the driver never invokes the plugin. For SCRAM, the plugin returns the cleartext password, which the driver feeds into the SCRAM client; the password leaves the JVM in salted/iterated form, not as cleartext.
Security history
- CVE-2025-49146 (fixed in 42.7.7):
channelBinding=requirewas silently honoured even when the server selected a non-SASL authentication method (e.g. MD5 or trust), allowing a server-side downgrade to defeat the binding. Pre-42.7.7 driver versions should pairchannelBinding=requirewithrequireAuth=scram-sha-256; alternatively upgrade. The advisory is at GHSA-hq9p-pm7w-8p54 ; see the Security page for the project’s full disclosure history.
Related connection properties
| Name | Type | Default | Versions | Description |
|---|---|---|---|---|
authenticationPluginClassName | class | — |
| Name of class which implements AuthenticationPlugin |
channelBinding | enum | prefer |
| This option controls the client’s use of channel binding. |
password | string | — |
| Password to use when authenticating. |
requireAuth | string | — |
| Comma-separated list of acceptable authentication methods. Use ‘!’ prefix to reject methods (e.g., ‘!password’ to reject cleartext). Supported: password, md5, gss, sspi, scram-sha-256, none |
scramMaxIterations | int | 100000 |
| Maximum PBKDF2 iteration count accepted from the server during SCRAM authentication. A value of zero disables this check. |
user | string | — |
| Username to connect to the database as. |
Related
- Kerberos, GSSAPI, SSPI
: the GSS/SSPI dispatch model, JAAS configuration, the
waffle-jnacompatibility matrix, andgssEncModefor GSS-encrypted connections. - SCRAM authentication failed : error-message decoding for the SCRAM and channel-binding paths.
- SSL / TLS : the layer underneath; without it, channel binding cannot apply and cleartext-password traffic is in the clear.
- Configure SSL/TLS (in Quick start) : the recommended-default combination.
- Security advisories : driver-level CVE / GHSA history including authentication-related ones.
- Connection properties reference : every property in one place.