1
0
Fork 0
mirror of https://git.pleroma.social/pleroma/pleroma.git synced 2026-02-15 17:16:57 +00:00

Save OAuth state into session instead of a URL parameter

The URL parameter "state" is now used by Ueberauth for CSRF
protection, so we should be putting our own state into the session
instead.

Suggestion taken from:
https://github.com/ueberauth/ueberauth/issues/149#issuecomment-2139312032
This commit is contained in:
Ekaterina Vaartis 2025-06-22 17:46:31 +03:00
parent 490a273dc1
commit e015055998
3 changed files with 15 additions and 16 deletions

View file

@ -0,0 +1 @@
Save OAuth state into session instead of a URL parameter, since ueberauth uses "state" for CSRF protection now

View file

@ -418,15 +418,11 @@ defmodule Pleroma.Web.OAuth.OAuthController do
auth_attrs
|> Map.delete("scopes")
|> Map.put("scope", scope)
|> Jason.encode!()
params =
auth_attrs
|> Map.drop(~w(scope scopes client_id redirect_uri))
|> Map.put("state", state)
conn = put_session(conn, :o_auth_state, state)
# Handing the request to Ueberauth
redirect(conn, to: Routes.o_auth_path(conn, :request, provider, params))
redirect(conn, to: Routes.o_auth_path(conn, :request, provider))
end
def request(%Plug.Conn{} = conn, params) do
@ -445,7 +441,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
end
def callback(%Plug.Conn{assigns: %{ueberauth_failure: failure}} = conn, params) do
params = callback_params(params)
params = callback_params(conn, params)
messages = for e <- Map.get(failure, :errors, []), do: e.message
message = Enum.join(messages, "; ")
@ -458,7 +454,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
end
def callback(%Plug.Conn{} = conn, params) do
params = callback_params(params)
params = callback_params(conn, params)
with {:ok, registration} <- Authenticator.get_registration(conn) do
auth_attrs = Map.take(params, ~w(client_id redirect_uri scope scopes state))
@ -488,8 +484,10 @@ defmodule Pleroma.Web.OAuth.OAuthController do
end
end
defp callback_params(%{"state" => state} = params) do
Map.merge(params, Jason.decode!(state))
defp callback_params(conn, params) do
state = get_session(conn, :o_auth_state)
Map.merge(params, state)
end
def registration_details(%Plug.Conn{} = conn, %{"authorization" => auth_attrs}) do

View file

@ -61,7 +61,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
assert response =~ o_auth_path(conn, :prepare_request)
end
test "GET /oauth/prepare_request encodes parameters as `state` and redirects", %{
test "GET /oauth/prepare_request puts `state` into session and redirects", %{
app: app,
conn: conn
} do
@ -82,9 +82,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
assert html_response(conn, 302)
redirect_query = URI.parse(redirected_to(conn)).query
assert %{"state" => state_param} = URI.decode_query(redirect_query)
assert {:ok, state_components} = Jason.decode(state_param)
state_components = get_session(conn, :o_auth_state)
expected_client_id = app.client_id
expected_redirect_uri = app.redirect_uris
@ -112,6 +110,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
conn =
conn
|> assign(:ueberauth_auth, %{provider: registration.provider, uid: registration.uid})
|> put_session(:o_auth_state, state_params)
|> get(
"/oauth/twitter/callback",
%{
@ -144,6 +143,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
uid: "171799000",
info: %{nickname: user.nickname, email: user.email, name: user.name, description: nil}
})
|> put_session(:o_auth_state, state_params)
|> get(
"/oauth/twitter/callback",
%{
@ -175,13 +175,13 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
conn =
conn
|> assign(:ueberauth_failure, %{errors: [%{message: "(error description)"}]})
|> put_session(:o_auth_state, state_params)
|> get(
"/oauth/twitter/callback",
%{
"oauth_token" => "G-5a3AAAAAAAwMH9AAABaektfSM",
"oauth_verifier" => "QZl8vUqNvXMTKpdmUnGejJxuHG75WWWs",
"provider" => "twitter",
"state" => Jason.encode!(state_params)
"provider" => "twitter"
}
)