1. Home
  2. Home
  3. Documentation
  4. Security
  5. Authentication
Last reviewed Edit this page on GitHub

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) .

Reviewed 2026-05-21 against source:AuthMethod.java:16-30, PGProperty.java:807-820, ConnectionFactoryImpl.java:758-779

org.postgresql.core.AuthMethod enumerates the six methods the server may request:

MethodServer-side triggerNotes
scram-sha-256pg_hba.conf scram-sha-256, or md5 with a SCRAM-stored passwordRecommended. Salted, iterated PBKDF2. The only password method that supports channel binding. New passwords are stored as SCRAM by default since PostgreSQL 14.
md5pg_hba.conf md5 with an MD5-stored passwordHashed 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 methodThe password is sent verbatim in the startup exchange. Only safe over TLS (and even then SCRAM is strictly better).
gsspg_hba.conf gss methodKerberos via GSSAPI on *nix (and on Windows when gsslib=gssapi).
sspipg_hba.conf sspi methodWindows native single-sign-on via SSPI. Requires waffle-jna on the classpath.
nonepg_hba.conf trust methodNo 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.

Reviewed 2026-05-21 against source:ConnectionFactoryImpl.java:781-1046, ScramAuthenticator.java:134-194, AuthenticationPluginManager.java:38-88

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 md5 and password, AuthenticationPluginManager.withPassword is called to obtain the credential, sends it, and zero-wipes the char[] before the call returns.
  • For scram-sha-256 (SASL), ScramAuthenticator runs the four-message SCRAM exchange (SASLInitialResponseSASLContinueSASLResponseSASLFinal) with the chosen mechanism: SCRAM-SHA-256-PLUS when channel binding is in play, plain SCRAM-SHA-256 otherwise.
  • For gss and sspi, 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.

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.

Reviewed 2026-05-21 against source:PGProperty.java:807-820, AuthMethod.java:34-75, ConnectionFactoryImpl.java:794-798, ConnectionFactoryImpl.java:864-1042

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-256 rejects MD5, cleartext password, and trust.
  • Deny-list: every entry has !. The driver accepts any method not in the list. Example: requireAuth=!password,!md5,!none rejects 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.

Reviewed 2026-05-21 against source:PGProperty.java:188-201, ChannelBinding.java:16-43, ConnectionFactoryImpl.java:845-859, ScramAuthenticator.java:52-131, SslTest.java:539-596

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 -PLUS mechanism 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 .

Reviewed 2026-05-21 against source:PGProperty.java:835-850, ConnectionFactoryImpl.java:997-1021, ScramAuthenticator.java:151-171

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).

Reviewed 2026-05-21 against source:PGProperty.java:106-116, AuthenticationPlugin.java:12-31, AuthenticationRequestType.java:8-13, AuthenticationPluginManager.java:38-128, ObjectFactory.java:20-69

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:

  1. Return a fresh char[] on every call. The driver overwrites the array with zeroes after use (see AuthenticationPluginManager.withPassword); reusing a cached array would leave the buffer wiped on the next call.
  2. The class must have a public constructor that ObjectFactory can use. For authentication plugins the driver first looks for a public Properties constructor, then falls back to a public no-arg constructor. If instantiation fails, the driver raises Unable to load Authentication Plugin ... with SQLState 22023 (INVALID_PARAMETER_VALUE).
  3. 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 by loginTimeout (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.

  • CVE-2025-49146 (fixed in 42.7.7): channelBinding=require was 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 pair channelBinding=require with requireAuth=scram-sha-256; alternatively upgrade. The advisory is at GHSA-hq9p-pm7w-8p54 ; see the Security page for the project’s full disclosure history.
NameTypeDefaultVersionsDescription
authenticationPluginClassNameclass
  • since 42.2.25
Name of class which implements AuthenticationPlugin
channelBindingenumprefer
  • since 42.7.0
This option controls the client’s use of channel binding.
passwordstring
  • since 9.4
Password to use when authenticating.
requireAuthstring
  • since 42.7.0
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
scramMaxIterationsint100000
  • since 42.7.11
Maximum PBKDF2 iteration count accepted from the server during SCRAM authentication. A value of zero disables this check.
userstring
  • since 9.4
Username to connect to the database as.