Skip to content

Commit 16bcdf7

Browse files
authored
feat: more consistency with postgres errors on auth errors (#711)
Fixes #710 (see the issue for a more thorough description).
1 parent f90f9b9 commit 16bcdf7

File tree

2 files changed

+38
-14
lines changed

2 files changed

+38
-14
lines changed

lib/supavisor/client_handler.ex

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -351,14 +351,9 @@ defmodule Supavisor.ClientHandler do
351351
"ClientHandler: Exchange error: #{inspect(reason)} when method #{inspect(method)}"
352352
)
353353

354-
msg =
355-
if method == :auth_query_md5,
356-
do: Server.error_message("XX000", reason),
357-
else: Server.exchange_message(:final, "e=#{reason}")
358-
359354
key = {:secrets_check, data.tenant, data.user}
360355

361-
if method != :password and reason == "Wrong password" and
356+
if method != :password and reason == :wrong_password and
362357
Cachex.get(Supavisor.Cache, key) == {:ok, nil} do
363358
case auth_secrets(info, data.user, key, 15_000) do
364359
{:ok, {method2, secrets2}} = value ->
@@ -383,6 +378,7 @@ defmodule Supavisor.ClientHandler do
383378
Logger.debug("ClientHandler: Cache hit for #{inspect(key)}")
384379
end
385380

381+
msg = postgres_auth_error(reason, data.user)
386382
HandlerHelpers.sock_send(sock, msg)
387383
Telem.client_join(:fail, data.id)
388384
{:stop, {:shutdown, :exchange_error}}
@@ -716,8 +712,26 @@ defmodule Supavisor.ClientHandler do
716712

717713
## Internal functions
718714

715+
@spec postgres_auth_error(
716+
:wrong_password | {:timeout, String.t()} | {:unexpected_message, term()},
717+
String.t()
718+
) :: iodata()
719+
defp postgres_auth_error(reason, user) do
720+
case reason do
721+
:wrong_password ->
722+
Server.error_message("28P01", "password authentication failed for user \"#{user}\"")
723+
724+
{:timeout, _message} ->
725+
Server.error_message("08006", "connection failure during authentication")
726+
727+
{:unexpected_message, _details} ->
728+
Server.error_message("08P01", "protocol violation during authentication")
729+
end
730+
end
731+
719732
@spec handle_exchange(Supavisor.sock(), {atom(), fun()}) ::
720-
{:ok, binary() | nil} | {:error, String.t()}
733+
{:ok, binary() | nil}
734+
| {:error, :wrong_password | {:timeout, String.t()} | {:unexpected_message, term()}}
721735
def handle_exchange({_, socket} = sock, {:auth_query_md5 = method, secrets}) do
722736
salt = :crypto.strong_rand_bytes(4)
723737
:ok = HandlerHelpers.sock_send(sock, Server.md5_request(salt))
@@ -775,9 +789,9 @@ defmodule Supavisor.ClientHandler do
775789
Server.decode_pkt(bin)
776790

777791
other ->
778-
{:error, "Unexpected message in receive_next/2 #{inspect(other)}"}
792+
{:error, {:unexpected_message, other}}
779793
after
780-
15_000 -> {:error, timeout_message}
794+
15_000 -> {:error, {:timeout, timeout_message}}
781795
end
782796
end
783797

@@ -790,7 +804,7 @@ defmodule Supavisor.ClientHandler do
790804
defp authenticate_exchange(:password, _secrets, signatures, p) do
791805
if p == signatures.client,
792806
do: {:ok, nil},
793-
else: {:error, "Wrong password"}
807+
else: {:error, :wrong_password}
794808
end
795809

796810
defp authenticate_exchange(:auth_query, secrets, signatures, p) do
@@ -799,14 +813,14 @@ defmodule Supavisor.ClientHandler do
799813
if Helpers.hash(client_key) == secrets.().stored_key do
800814
{:ok, client_key}
801815
else
802-
{:error, "Wrong password"}
816+
{:error, :wrong_password}
803817
end
804818
end
805819

806820
defp authenticate_exchange(:auth_query_md5, client_hash, server_hash, salt) do
807821
if "md5" <> Helpers.md5([server_hash, salt]) == client_hash,
808822
do: {:ok, nil},
809-
else: {:error, "Wrong password"}
823+
else: {:error, :wrong_password}
810824
end
811825

812826
@spec db_checkout(:write | :read | :both, :on_connect | :on_query, map) ::

test/integration/proxy_test.exs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,12 @@ defmodule Supavisor.Integration.ProxyTest do
6161

6262
assert {:error,
6363
%Postgrex.Error{
64-
message: "error received in SCRAM server final message: \"Wrong password\""
64+
postgres: %{
65+
code: :invalid_password,
66+
message: "password authentication failed for user \"" <> _,
67+
severity: "FATAL",
68+
pg_code: "28P01"
69+
}
6570
}} = parse_uri(url) |> single_connection()
6671
end
6772

@@ -259,7 +264,12 @@ defmodule Supavisor.Integration.ProxyTest do
259264

260265
assert {:error,
261266
%Postgrex.Error{
262-
message: "error received in SCRAM server final message: \"Wrong password\""
267+
postgres: %{
268+
code: :invalid_password,
269+
message: "password authentication failed for user \"" <> _,
270+
severity: "FATAL",
271+
pg_code: "28P01"
272+
}
263273
}} = parse_uri(new_pass) |> single_connection()
264274

265275
assert {:ok, pid} = parse_uri(new_pass) |> single_connection()

0 commit comments

Comments
 (0)