Let the OAuth form remember you, fixes #1909

This commit is contained in:
Alex Gleason 2020-07-19 19:37:54 -05:00
parent 9f48dfb705
commit d11c0ede3a
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7
5 changed files with 93 additions and 27 deletions

View File

@ -76,8 +76,17 @@ defp do_authorize(%Plug.Conn{} = conn, params) do
available_scopes = (app && app.scopes) || []
scopes = Scopes.fetch_scopes(params, available_scopes)
user =
with %{assigns: %{user: %User{} = user}} <- conn do
user
else
_ -> nil
end
# Note: `params` might differ from `conn.params`; use `@params` not `@conn.params` in template
render(conn, Authenticator.auth_template(), %{
app: app && Map.delete(app, :client_secret),
user: user,
response_type: params["response_type"],
client_id: params["client_id"],
available_scopes: available_scopes,
@ -121,11 +130,13 @@ defp handle_existing_authorization(
end
end
def create_authorization(
%Plug.Conn{} = conn,
%{"authorization" => _} = params,
opts \\ []
) do
def create_authorization(_, _, opts \\ [])
def create_authorization(%Plug.Conn{assigns: %{user: %User{} = user}} = conn, params, []) do
create_authorization(conn, params, user: user)
end
def create_authorization(%Plug.Conn{} = conn, %{"authorization" => _} = params, opts) do
with {:ok, auth, user} <- do_create_authorization(conn, params, opts[:user]),
{:mfa_required, _, _, false} <- {:mfa_required, user, auth, MFA.require?(user)} do
after_create_authorization(conn, auth, params)

View File

@ -278,9 +278,9 @@ defmodule Pleroma.Web.Router do
scope [] do
pipe_through([:oauth, :after_auth])
get("/authorize", OAuthController, :authorize)
post("/authorize", OAuthController, :create_authorization)
end
post("/authorize", OAuthController, :create_authorization)
post("/token", OAuthController, :token_exchange)
post("/revoke", OAuthController, :token_revoke)
get("/registration_details", OAuthController, :registration_details)

View File

@ -5,32 +5,51 @@
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
<% end %>
<h2>OAuth Authorization</h2>
<%= form_for @conn, o_auth_path(@conn, :authorize), [as: "authorization"], fn f -> %>
<%= if @params["registration"] in ["true", true] do %>
<h3>This is the first time you visit! Please enter your Pleroma handle.</h3>
<p>Choose carefully! You won't be able to change this later. You will be able to change your display name, though.</p>
<div class="input">
<%= label f, :nickname, "Pleroma Handle" %>
<%= text_input f, :nickname, placeholder: "lain" %>
<%= if @user do %>
<div class="account-header">
<div class="avatar">
<img src="<%= Pleroma.User.avatar_url(@user) %>">
</div>
<div class="name">
Signed in as:
<div class="username">@<%= @user.nickname %></div>
</div>
</div>
<%= hidden_input f, :name, value: @params["name"] %>
<%= hidden_input f, :password, value: @params["password"] %>
<br>
<% else %>
<div class="input">
<%= label f, :name, "Username" %>
<%= text_input f, :name %>
</div>
<div class="input">
<%= label f, :password, "Password" %>
<%= password_input f, :password %>
</div>
<%= submit "Log In" %>
<% end %>
<%= if @app do %>
<p>Application <strong><%= @app.client_name %></strong> is requesting access to your account.</p>
<%= render @view_module, "_scopes.html", Map.merge(assigns, %{form: f}) %>
<% end %>
<%= if @user do %>
<%= submit "Authorize" %>
<% else %>
<%= if @params["registration"] in ["true", true] do %>
<h3>This is the first time you visit! Please enter your Pleroma handle.</h3>
<p>Choose carefully! You won't be able to change this later. You will be able to change your display name, though.</p>
<div class="input">
<%= label f, :nickname, "Pleroma Handle" %>
<%= text_input f, :nickname, placeholder: "lain" %>
</div>
<%= hidden_input f, :name, value: @params["name"] %>
<%= hidden_input f, :password, value: @params["password"] %>
<br>
<% else %>
<div class="input">
<%= label f, :name, "Username" %>
<%= text_input f, :name %>
</div>
<div class="input">
<%= label f, :password, "Password" %>
<%= password_input f, :password %>
</div>
<%= submit "Log In" %>
<% end %>
<% end %>
<%= hidden_input f, :client_id, value: @client_id %>
<%= hidden_input f, :response_type, value: @response_type %>
<%= hidden_input f, :redirect_uri, value: @redirect_uri %>
@ -40,4 +59,3 @@
<%= if Pleroma.Config.oauth_consumer_enabled?() do %>
<%= render @view_module, Pleroma.Web.Auth.Authenticator.oauth_consumer_template(), assigns %>
<% end %>

Binary file not shown.

View File

@ -606,6 +606,43 @@ test "redirects with oauth authorization, " <>
end
end
test "authorize from cookie" do
app_scopes = ["read", "write"]
app = insert(:oauth_app)
redirect_uri = OAuthController.default_redirect_uri(app)
user = insert(:user)
conn =
build_conn()
|> Plug.Session.call(Plug.Session.init(@session_opts))
|> fetch_session()
|> put_session(:user_id, user.id)
|> post(
"/oauth/authorize",
%{
"authorization" => %{
"name" => user.nickname,
"client_id" => app.client_id,
"redirect_uri" => redirect_uri,
"scope" => app_scopes,
"state" => "statepassed"
}
}
)
assert Enum.count(Repo.all(Pleroma.Web.OAuth.Authorization)) == 1
target = redirected_to(conn)
assert target =~ redirect_uri
query = URI.parse(target).query |> URI.query_decoder() |> Map.new()
assert %{"state" => "statepassed", "code" => code} = query
auth = Repo.get_by(Authorization, token: code)
assert auth
assert auth.scopes == app_scopes
end
test "redirect to on two-factor auth page" do
otp_secret = TOTP.generate_secret()