Allow authenticating via client-sent events
This commit is contained in:
parent
273cda63ad
commit
21395aa509
3 changed files with 118 additions and 0 deletions
|
@ -214,6 +214,42 @@ defmodule Pleroma.Web.MastodonAPI.WebsocketHandler do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp handle_client_event(
|
||||||
|
%{"type" => "pleroma.authenticate", "token" => access_token} = _params,
|
||||||
|
state
|
||||||
|
) do
|
||||||
|
with {:auth, nil, nil} <- {:auth, state.user, state.oauth_token},
|
||||||
|
{:ok, user, oauth_token} <- authenticate_request(access_token, nil) do
|
||||||
|
{[
|
||||||
|
{:text,
|
||||||
|
StreamerView.render("pleroma_respond.json", %{
|
||||||
|
type: "pleroma.authenticate",
|
||||||
|
result: "success"
|
||||||
|
})}
|
||||||
|
], %{state | user: user, oauth_token: oauth_token}}
|
||||||
|
else
|
||||||
|
{:auth, _, _} ->
|
||||||
|
{[
|
||||||
|
{:text,
|
||||||
|
StreamerView.render("pleroma_respond.json", %{
|
||||||
|
type: "pleroma.authenticate",
|
||||||
|
result: "error",
|
||||||
|
error: :already_authenticated
|
||||||
|
})}
|
||||||
|
], state}
|
||||||
|
|
||||||
|
_ ->
|
||||||
|
{[
|
||||||
|
{:text,
|
||||||
|
StreamerView.render("pleroma_respond.json", %{
|
||||||
|
type: "pleroma.authenticate",
|
||||||
|
result: "error",
|
||||||
|
error: :unauthorized
|
||||||
|
})}
|
||||||
|
], state}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
defp handle_client_event(params, state) do
|
defp handle_client_event(params, state) do
|
||||||
Logger.error("#{__MODULE__} received unknown event: #{inspect(params)}")
|
Logger.error("#{__MODULE__} received unknown event: #{inspect(params)}")
|
||||||
{[], state}
|
{[], state}
|
||||||
|
|
|
@ -152,5 +152,6 @@ defmodule Pleroma.Web.StreamerView do
|
||||||
|
|
||||||
defp maybe_error(%{error: :bad_topic}), do: %{error: "bad_topic"}
|
defp maybe_error(%{error: :bad_topic}), do: %{error: "bad_topic"}
|
||||||
defp maybe_error(%{error: :unauthorized}), do: %{error: "unauthorized"}
|
defp maybe_error(%{error: :unauthorized}), do: %{error: "unauthorized"}
|
||||||
|
defp maybe_error(%{error: :already_authenticated}), do: %{error: "already_authenticated"}
|
||||||
defp maybe_error(_), do: %{}
|
defp maybe_error(_), do: %{}
|
||||||
end
|
end
|
||||||
|
|
|
@ -224,6 +224,87 @@ defmodule Pleroma.Integration.MastodonWebsocketTest do
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "accepts valid token on client-sent event", %{token: token} do
|
||||||
|
assert {:ok, pid} = start_socket()
|
||||||
|
|
||||||
|
WebsocketClient.send_text(
|
||||||
|
pid,
|
||||||
|
%{type: "pleroma.authenticate", token: token.token} |> Jason.encode!()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_receive {:text, raw_json}, 1_000
|
||||||
|
|
||||||
|
assert {:ok,
|
||||||
|
%{
|
||||||
|
"event" => "pleroma.respond",
|
||||||
|
"payload" => %{"type" => "pleroma.authenticate", "result" => "success"}
|
||||||
|
}} = decode_json(raw_json)
|
||||||
|
|
||||||
|
WebsocketClient.send_text(pid, %{type: "subscribe", stream: "user"} |> Jason.encode!())
|
||||||
|
assert_receive {:text, raw_json}, 1_000
|
||||||
|
|
||||||
|
assert {:ok,
|
||||||
|
%{
|
||||||
|
"event" => "pleroma.respond",
|
||||||
|
"payload" => %{"type" => "subscribe", "result" => "success"}
|
||||||
|
}} = decode_json(raw_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rejects invalid token on client-sent event" do
|
||||||
|
assert {:ok, pid} = start_socket()
|
||||||
|
|
||||||
|
WebsocketClient.send_text(
|
||||||
|
pid,
|
||||||
|
%{type: "pleroma.authenticate", token: "Something else"} |> Jason.encode!()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_receive {:text, raw_json}, 1_000
|
||||||
|
|
||||||
|
assert {:ok,
|
||||||
|
%{
|
||||||
|
"event" => "pleroma.respond",
|
||||||
|
"payload" => %{
|
||||||
|
"type" => "pleroma.authenticate",
|
||||||
|
"result" => "error",
|
||||||
|
"error" => "unauthorized"
|
||||||
|
}
|
||||||
|
}} = decode_json(raw_json)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "rejects new authenticate request if already logged-in", %{token: token} do
|
||||||
|
assert {:ok, pid} = start_socket()
|
||||||
|
|
||||||
|
WebsocketClient.send_text(
|
||||||
|
pid,
|
||||||
|
%{type: "pleroma.authenticate", token: token.token} |> Jason.encode!()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_receive {:text, raw_json}, 1_000
|
||||||
|
|
||||||
|
assert {:ok,
|
||||||
|
%{
|
||||||
|
"event" => "pleroma.respond",
|
||||||
|
"payload" => %{"type" => "pleroma.authenticate", "result" => "success"}
|
||||||
|
}} = decode_json(raw_json)
|
||||||
|
|
||||||
|
WebsocketClient.send_text(
|
||||||
|
pid,
|
||||||
|
%{type: "pleroma.authenticate", token: "Something else"} |> Jason.encode!()
|
||||||
|
)
|
||||||
|
|
||||||
|
assert_receive {:text, raw_json}, 1_000
|
||||||
|
|
||||||
|
assert {:ok,
|
||||||
|
%{
|
||||||
|
"event" => "pleroma.respond",
|
||||||
|
"payload" => %{
|
||||||
|
"type" => "pleroma.authenticate",
|
||||||
|
"result" => "error",
|
||||||
|
"error" => "already_authenticated"
|
||||||
|
}
|
||||||
|
}} = decode_json(raw_json)
|
||||||
|
end
|
||||||
|
|
||||||
test "disconnect when token is revoked", %{app: app, user: user, token: token} do
|
test "disconnect when token is revoked", %{app: app, user: user, token: token} do
|
||||||
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
assert {:ok, _} = start_socket("?stream=user:notification&access_token=#{token.token}")
|
||||||
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
assert {:ok, _} = start_socket("?stream=user&access_token=#{token.token}")
|
||||||
|
|
Loading…
Reference in a new issue