PostgreSQL のサーバを上げた、あるいは新しいマネージドの PostgreSQL に向けた直後から、Java のアプリが接続で 落ちるようになります。
org.postgresql.util.PSQLException: The authentication type 10 is not supported. Check that you have configured the pg_hba.conf file to include the client's IP address or subnet, and that it is using an authentication scheme supported by the driver.
Spring Boot や HikariCP を使っている場合は、コネクションプールの初期化で止まるので
ApplicationContext の起動失敗として現れ、この 1 行はスタックトレースの奥に入ります。
直し方の要点を先に
PostgreSQL JDBC ドライバ(pgjdbc)の版を上げます。 サーバ・接続 URL・ユーザー・アプリのコードは
そのままです。pom.xml の既存の org.postgresql:postgresql の <version> を、公式が案内している現行の
保守版に更新します。
<!-- pom.xml の既存の依存の version を更新する -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.13</version>
</dependency>
版は Maven Central の org.postgresql:postgresql で確認できます。古い版を選ばない理由が SCRAM 自体にあります——
pgjdbc は SCRAM 認証まわりで High 深刻度の脆弱性を複数修正しており、channelBinding=require の
フォールバック(CVE-2025-49146・42.7.7 で修正)、SCRAM の PBKDF2 反復回数が無制限で CPU を枯渇させる問題
(CVE-2026-42198・42.7.11 で修正)、チャネルバインディングの静かな格下げ(CVE-2026-54291・42.7.12 で修正)が
それに当たります。この記事が扱っているのと同じ認証経路の修正なので、接続を直すために版を動かすなら
そこまで上げます。
版の下限としては 42.2.1 です。SCRAM 対応が入ったのは 42.2.0 ですが、その版の jar には SCRAM の
クライアント実装が同梱されておらず、接続すると今度は NoClassDefFoundError で止まります。上流の
changelog も 42.2.0 の Known issues に「SCRAM does not work as scram:client library is not packaged」と
記載しています。「42.2.0 以降に上げる」という案内をそのまま 42.2.0 に当てはめると、この 1 段目のエラーが
消えた先で 2 段目に当たります(pgjdbc 42.2.0 で SCRAM 接続すると ScramClient が見つからない)。
下限は「どこから直っているか」の話で、実際に固定する版ではありません。
Gradle や、親 POM・BOM で版を管理している構成では、そちらの宣言を更新します。実行時に読まれている版は
接続成功時に DatabaseMetaData#getDriverVersion() で確認できます。
errfix の検証は 42.1.4(失敗)と 42.7.4(成功)の 2 点で行っています。この 2 点は境界を示すためのもので、
本番で固定する版ではありません(42.7.4 は上記の 3 件をまだ含みません)。
エラー文が指している pg_hba.conf は、この場合の原因ではない
メッセージは「pg_hba.conf にクライアントの IP アドレスかサブネットを設定しているか確認せよ」と案内します。
しかし止まっている地点は、サーバが提示した認証方式をドライバが解釈できなかったところです。
「認証タイプ 10」は PostgreSQL のフロントエンド/バックエンドプロトコルのメッセージコードで、
AuthenticationSASL(SASL 認証を要求する)を指します。参考までに、以前から使われてきた
AuthenticationMD5Password は 5、AuthenticationCleartextPassword は 3 です。つまりサーバは
「SASL(SCRAM)で認証する」と応答していて、その 10 という数字を知らない古いドライバが、
知らないコードとして拒否しています。
実際に試した結果です。検証したサーバの pg_hba.conf は既に接続元(127.0.0.1)を許可していて、それでも
上記のエラーになります。そこへさらに、接続するユーザーとアドレスを名指しした行を先頭に足して
pg_hba.conf を再読み込みしました。
host all appuser 127.0.0.1/32 scram-sha-256
host all appuser ::1/128 scram-sha-256
同じドライバで再接続すると、同じメッセージが同じ場所(ConnectionFactoryImpl.doAuthentication)から
返ります。 エラー文の指示どおりに直しても、出力は 1 文字も変わりません。その行の認証方式が
scram-sha-256 である限り、サーバは同じ 10 を返します。
なぜ PostgreSQL 14 以降で出るのか:パスワードの保存形式の既定が変わった
境界は 2 段あります。
- PostgreSQL 10 で
scram-sha-256が追加されました。ここで初めて認証タイプ 10 が存在します。 - PostgreSQL 14 で
password_encryptionの既定値がmd5からscram-sha-256になりました。 以降に設定したパスワードは、明示的に変えない限り SCRAM の形式で保存されます。
10 の時点では「使うと決めた人だけ」が踏む設定でしたが、14 以降は何も設定しなくてもそちら側に入ります。 サーバを 14 以降へ上げてユーザーのパスワードを設定し直した時点、あるいは 14 以降で新しく作った インスタンスに向けた時点で、ドライバ側だけが取り残されます。
SCRAM に対応した最初の pgjdbc は 42.2.0 です(上流 CHANGELOG の 42.2.0 が
Support SCRAM-SHA-256 for PostgreSQL 10 in the JDBC 4.2 version (Java 8+) を Added に挙げています)。
SCRAM を実装する前の系列は、サーバの版に関係なく scram-sha-256 で認証するユーザーに接続できません
——サーバが 10 を返す限り、解釈できる実装が入っていないためです。実測では 42.1.4 が上記のメッセージで
終了コード 1、42.7.4 が同一条件で接続成功(終了コード 0)でした。
サーバ側を md5 に戻す案について
password_encryption を md5 に戻してパスワードを設定し直せば、古いドライバのまま接続できるようになります。
戻り先がどう扱われているかは、サーバの版で書かれ方が違います。
-
PostgreSQL 14 / 16 / 17 のパスワード認証のドキュメントは、md5 を「custom less secure challenge-response mechanism」と説明し、サーバからハッシュを盗まれた場合に保護にならないこと、
Also, the MD5 hash algorithm is nowadays no longer considered secure against determined attacks.を書いています。 非推奨とは書いていません。 -
PostgreSQL 18 で、同じページに次の警告が入りました。
Support for MD5-encrypted passwords is deprecated and will be removed in a future release of PostgreSQL.
つまり、いま md5 に戻すのはその版のドキュメントでは非推奨ではない一方、18 以降では非推奨・将来削除と 名指しされている方式へ戻すことになります。サーバをいずれ 18 以降へ上げる予定があるなら、その時点でもう一度 同じ移行をやることになります。ドライバを上げられない事情があって時間を稼ぐ場合でも、ドライバ更新までの期限を 一緒に決めておくことになります。
切り分け
- ドライバを上げたら
NoClassDefFoundError: org/postgresql/shaded/com/ongres/scram/client/ScramClient$ChannelBindingに変わった: 42.2.0 を選んでいます。同梱漏れが直るのは 42.2.1 からで、上げ先は現行の保守版にします (pgjdbc 42.2.0 で SCRAM 接続すると ScramClient が見つからない)。 - アプリの依存は上げたのに変わらない:実行時に読まれている jar が別のものである可能性があります。
接続に成功したときは
DatabaseMetaData#getDriverVersion()で実際に使われている版を確認できます (検証コードでも接続成功時にこの値を出力しています)。アプリケーションサーバが自前のlib/に 古い pgjdbc を持っている構成では、依存の宣言よりそちらが優先されることがあります。 .jre7/.jre6が付いた版を使っている:SCRAM 対応は JDBC 4.2(Java 8 以上)版に入ったものです。 古い JRE 向けの派生版を使い続けている場合は、まず JDK 側の前提を確認します。この構成は本記事では実測していません。- 一部のユーザーだけ接続できる:
password_encryptionを変えても既存のパスワードは変換されません。 保存形式はパスワードを設定し直した時点で決まるので、同じサーバの中に md5 のまま残っているユーザーと SCRAM のユーザーが混在します。どちらの形式かはpg_authid.rolpasswordの先頭で判別できます。 - 接続先はマネージドサービス(Aurora / Cloud SQL 等):
pg_hba.confを直接編集できない環境でも、 原因と直し方は同じです。動かすのはドライバの版です。
検証環境
- image:
postgres(digest 固定sha256:33f923b0...= PostgreSQL 16.14)。同じコンテナにdefault-jdk-headlessを追加し、PostgreSQL サーバと JDBC クライアントを 1 コンテナ内で動かして127.0.0.1へ接続 - 公式
postgresイメージは127.0.0.1からの接続をtrust(認証なし)にしているため、pg_hba.confの 該当行をscram-sha-256に戻してから検証している。これはイメージ固有の緩和を外して PostgreSQL 14 以降の 既定の状態に合わせる操作で、再現のための仕込みではない - 接続するユーザーは
password_encryptionの既定(scram-sha-256)のもとで作成し、保存形式が SCRAM に なっていることをpg_authid.rolpasswordの先頭で確認している - 再現:
postgresql-42.1.4.jarを classpath に置いてjdbc:postgresql://127.0.0.1:5432/appdbへ接続 → 上記のPSQLException・終了コード 1 - 修正:
postgresql-42.7.4.jarに替えて同じ接続 →SELECT 1まで通って終了コード 0。 この 42.7.4 は境界を示すための検証点で、本文が勧める固定版ではない(上記の SCRAM 関連修正を含まない) - reproduce と fix で違うのは classpath の jar 1 つだけ。サーバ・URL・ユーザー・接続コードは同一
- 反例の実測:上の「エラー文が指している pg_hba.conf は原因ではない」は、接続元とユーザーを名指しした
scram-sha-256の行をpg_hba.confの先頭に足し、pg_reload_conf()を実行してから同じドライバで 再接続して確かめている(同じ例外・同じフレーム・終了コード 1)
再現から修正までは errfix の検証ハーネスが機械的に確認しています。認証タイプ 10 が AuthenticationSASL で
あることは PostgreSQL のプロトコル仕様、scram-sha-256 の追加は PostgreSQL 10 のリリースノート、
password_encryption の既定変更は PostgreSQL 14 のリリースノート、md5 の非推奨は PostgreSQL 18 の
パスワード認証の項(14 / 16 / 17 の同じページには無いことも確認)、42.2.0 の同梱漏れは pgjdbc の changelog、
SCRAM 関連の修正版は pgjdbc の公開セキュリティアドバイザリで、それぞれ確認しています。