Skip to content

Commit adc824c

Browse files
authored
fix: move invalid jwt log to warning level (#1490)
1 parent 76c7a0e commit adc824c

File tree

6 files changed

+90
-24
lines changed

6 files changed

+90
-24
lines changed

lib/realtime_web/channels/realtime_channel.ex

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ defmodule RealtimeWeb.RealtimeChannel do
5555
|> assign(:private?, !!params["config"]["private"])
5656
|> assign(:policies, nil)
5757

58+
token = socket.assigns.access_token
59+
log_level = socket.assigns.log_level
60+
5861
with :ok <- SignalHandler.shutdown_in_progress?(),
5962
:ok <- only_private?(tenant_id, socket),
6063
:ok <- limit_joins(socket.assigns),
@@ -118,11 +121,11 @@ defmodule RealtimeWeb.RealtimeChannel do
118121
{:ok, state, assign(socket, assigns)}
119122
else
120123
{:error, :expired_token, msg} ->
121-
Logging.log_error_with_token_metadata("InvalidJWTToken", msg, socket.assigns.access_token)
124+
Logging.maybe_log_warning_with_token_metadata("InvalidJWTToken", msg, token, log_level)
122125

123126
{:error, :missing_claims} ->
124127
msg = "Fields `role` and `exp` are required in JWT"
125-
Logging.log_error_with_token_metadata("InvalidJWTToken", msg, socket.assigns.access_token)
128+
Logging.maybe_log_warning_with_token_metadata("InvalidJWTToken", msg, token, log_level)
126129

127130
{:error, :unauthorized, msg} ->
128131
Logging.log_error_message(:error, "Unauthorized", msg)

lib/realtime_web/channels/realtime_channel/logging.ex

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,27 +29,46 @@ defmodule RealtimeWeb.RealtimeChannel.Logging do
2929
"""
3030
@spec log_error_with_token_metadata(code :: binary(), msg :: binary(), token :: Joken.bearer_token()) ::
3131
{:error, %{reason: binary()}}
32-
def log_error_with_token_metadata(code, msg, token) do
32+
def log_error_with_token_metadata(code, msg, token) when is_binary(token) do
3333
metadata = Logger.metadata()
3434
metadata = update_metadata_with_token_claims(metadata, token)
3535
log_error_message(:error, code, msg, metadata)
3636
end
3737

3838
@doc """
39-
Logs an error with token metadata
39+
Logs a warning with token metadata
4040
"""
4141
@spec log_warning_with_token_metadata(
4242
code :: binary(),
4343
msg :: binary(),
4444
token :: Joken.bearer_token(),
4545
metadata :: keyword()
4646
) :: {:error, %{reason: binary()}}
47-
def log_warning_with_token_metadata(code, msg, token, metadata \\ []) do
48-
if metadata == [], do: Logger.metadata()
47+
48+
def log_warning_with_token_metadata(code, msg, token, metadata \\ []) when is_binary(token) do
49+
metadata = if metadata == [], do: Logger.metadata(), else: metadata
4950
metadata = update_metadata_with_token_claims(metadata, token)
5051
log_error_message(:warning, code, msg, metadata)
5152
end
5253

54+
@doc """
55+
Maybe logs a warning with token metadata if the log level is set to warning
56+
"""
57+
@spec maybe_log_warning_with_token_metadata(
58+
code :: binary(),
59+
msg :: binary(),
60+
token :: Joken.bearer_token(),
61+
log_level :: Logger.level()
62+
) :: {:error, %{reason: binary()}}
63+
64+
def maybe_log_warning_with_token_metadata(code, msg, token, log_level) when is_binary(token) do
65+
if Logger.compare_levels(log_level, :warning) != :gt do
66+
log_warning_with_token_metadata(code, msg, token)
67+
end
68+
69+
{:error, %{reason: msg}}
70+
end
71+
5372
defp update_metadata_with_token_claims(metadata, token) do
5473
case Joken.peek_claims(token) do
5574
{:ok, claims} ->

lib/realtime_web/channels/user_socket.ex

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ defmodule RealtimeWeb.UserSocket do
2828
%{uri: %{host: host}, x_headers: headers} = opts
2929

3030
{:ok, external_id} = Database.get_external_id(host)
31-
Logger.metadata(external_id: external_id, project: external_id)
32-
Logger.put_process_level(self(), :error)
33-
3431
token = access_token(params, headers)
32+
log_level = log_level(params)
33+
34+
Logger.metadata(external_id: external_id, project: external_id)
35+
Logger.put_process_level(self(), log_level)
3536

3637
with %Tenant{
3738
jwt_secret: jwt_secret,
@@ -67,7 +68,7 @@ defmodule RealtimeWeb.UserSocket do
6768
postgres_extension: PostgresCdc.filter_settings(postgres_cdc_default, extensions),
6869
postgres_cdc_module: postgres_cdc_module,
6970
tenant: external_id,
70-
log_level: log_level(params),
71+
log_level: log_level,
7172
tenant_token: token,
7273
headers: opts.x_headers
7374
}
@@ -85,11 +86,12 @@ defmodule RealtimeWeb.UserSocket do
8586
{:error, :tenant_suspended}
8687

8788
{:error, :expired_token, msg} ->
88-
Logging.log_error_with_token_metadata("InvalidJWTToken", msg, token)
89+
Logging.maybe_log_warning_with_token_metadata("InvalidJWTToken", msg, token, log_level)
8990
{:error, :expired_token}
9091

9192
{:error, :missing_claims} ->
92-
Logging.log_error_with_token_metadata("InvalidJWTToken", "Fields `role` and `exp` are required in JWT", token)
93+
msg = "Fields `role` and `exp` are required in JWT"
94+
Logging.maybe_log_warning_with_token_metadata("InvalidJWTToken", msg, token, log_level)
9395
{:error, :missing_claims}
9496

9597
{:error, :token_malformed} ->

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ defmodule Realtime.MixProject do
44
def project do
55
[
66
app: :realtime,
7-
version: "2.41.19",
7+
version: "2.41.20",
88
elixir: "~> 1.17.3",
99
elixirc_paths: elixirc_paths(Mix.env()),
1010
start_permanent: Mix.env() == :prod,

test/integration/rt_channel_test.exs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,9 @@ defmodule Realtime.Integration.RtChannelTest do
927927

928928
test "invalid JWT with expired token", %{tenant: tenant} do
929929
log =
930-
capture_log(fn -> get_connection(tenant, "authenticated", %{:exp => System.system_time(:second) - 1000}) end)
930+
capture_log(fn ->
931+
get_connection(tenant, "authenticated", %{:exp => System.system_time(:second) - 1000}, %{log_level: :info})
932+
end)
931933

932934
assert log =~ "InvalidJWTToken: Token has expired"
933935
end
@@ -1687,7 +1689,9 @@ defmodule Realtime.Integration.RtChannelTest do
16871689

16881690
test "invalid JWT with expired token", %{tenant: tenant} do
16891691
log =
1690-
capture_log(fn -> get_connection(tenant, "authenticated", %{:exp => System.system_time(:second) - 1000}) end)
1692+
capture_log(fn ->
1693+
get_connection(tenant, "authenticated", %{:exp => System.system_time(:second) - 1000}, %{log_level: :info})
1694+
end)
16911695

16921696
assert log =~ "InvalidJWTToken: Token has expired"
16931697
end

test/realtime_web/channels/realtime_channel/logging_test.exs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ defmodule RealtimeWeb.RealtimeChannel.LoggingTest do
1010
:telemetry.attach(__MODULE__, [:realtime, :channel, :error], &__MODULE__.handle_telemetry/4, pid: self())
1111
level = Logger.level()
1212
Logger.configure(level: :info)
13+
tenant = tenant_fixture()
1314

1415
on_exit(fn ->
1516
:telemetry.detach(__MODULE__)
1617
Logger.configure(level: level)
1718
end)
19+
20+
%{tenant: tenant}
1821
end
1922

2023
describe "maybe_log_handle_info/2" do
@@ -178,11 +181,6 @@ defmodule RealtimeWeb.RealtimeChannel.LoggingTest do
178181
end
179182

180183
describe "log_error_with_token_metadata/4" do
181-
setup do
182-
tenant = tenant_fixture()
183-
%{tenant: tenant}
184-
end
185-
186184
test "logs error messages with token metadata", %{tenant: tenant} do
187185
sub = random_string()
188186
iss = "https://#{random_string()}.com"
@@ -198,22 +196,62 @@ defmodule RealtimeWeb.RealtimeChannel.LoggingTest do
198196
end
199197

200198
describe "log_warning_with_token_metadata/4" do
201-
setup do
202-
tenant = tenant_fixture()
203-
%{tenant: tenant}
199+
test "logs warning messages with token metadata", %{tenant: tenant} do
200+
sub = random_string()
201+
iss = "https://#{random_string()}.com"
202+
exp = System.system_time(:second) + 1000
203+
204+
token = generate_jwt_token(tenant, %{sub: sub, exp: exp, iss: iss})
205+
log = capture_log(fn -> Logging.log_warning_with_token_metadata("TestCode", "test message", token) end)
206+
assert log =~ "TestCode: test message"
207+
assert log =~ "sub=#{sub}"
208+
assert log =~ "exp=#{exp}"
209+
assert log =~ "iss=#{iss}"
204210
end
211+
end
205212

213+
describe "maybe_log_warning_with_token_metadata/4" do
206214
test "logs warning messages with token metadata", %{tenant: tenant} do
207215
sub = random_string()
208216
iss = "https://#{random_string()}.com"
209217
exp = System.system_time(:second) + 1000
210218

211219
token = generate_jwt_token(tenant, %{sub: sub, exp: exp, iss: iss})
212-
log = capture_log(fn -> Logging.log_warning_with_token_metadata("TestCode", "test message", token) end)
220+
221+
log =
222+
capture_log(fn -> Logging.maybe_log_warning_with_token_metadata("TestCode", "test message", token, :warning) end)
223+
213224
assert log =~ "TestCode: test message"
214225
assert log =~ "sub=#{sub}"
215226
assert log =~ "exp=#{exp}"
216227
assert log =~ "iss=#{iss}"
217228
end
229+
230+
test "logs warning messages with token metadata when log level is lower than warning", %{tenant: tenant} do
231+
sub = random_string()
232+
iss = "https://#{random_string()}.com"
233+
exp = System.system_time(:second) + 1000
234+
235+
token = generate_jwt_token(tenant, %{sub: sub, exp: exp, iss: iss})
236+
237+
log =
238+
capture_log(fn -> Logging.maybe_log_warning_with_token_metadata("TestCode", "test message", token, :info) end)
239+
240+
assert log =~ "TestCode: test message"
241+
assert log =~ "sub=#{sub}"
242+
assert log =~ "exp=#{exp}"
243+
assert log =~ "iss=#{iss}"
244+
end
245+
246+
test "does not log warning messages when log level is higher than warning" do
247+
token = random_string()
248+
249+
log =
250+
capture_log(fn ->
251+
Logging.maybe_log_warning_with_token_metadata("TestCode", "test message", token, :error)
252+
end)
253+
254+
assert log == ""
255+
end
218256
end
219257
end

0 commit comments

Comments
 (0)