Page MenuHomePhorge

No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/pleroma/web/auth/database_authenticator.ex b/lib/pleroma/web/auth/authenticator.ex
similarity index 63%
rename from lib/pleroma/web/auth/database_authenticator.ex
rename to lib/pleroma/web/auth/authenticator.ex
index e78068b03..82267c595 100644
--- a/lib/pleroma/web/auth/database_authenticator.ex
+++ b/lib/pleroma/web/auth/authenticator.ex
@@ -1,20 +1,25 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.Web.Auth.DatabaseAuthenticator do
+defmodule Pleroma.Web.Auth.Authenticator do
alias Pleroma.User
def implementation do
Pleroma.Config.get(
- Pleroma.Web.Auth.DatabaseAuthenticator,
- Pleroma.Web.Auth.PleromaDatabaseAuthenticator
+ Pleroma.Web.Auth.Authenticator,
+ Pleroma.Web.Auth.PleromaAuthenticator
)
end
@callback get_user(Plug.Conn.t()) :: {:ok, User.t()} | {:error, any()}
def get_user(plug), do: implementation().get_user(plug)
@callback handle_error(Plug.Conn.t(), any()) :: any()
def handle_error(plug, error), do: implementation().handle_error(plug, error)
+
+ @callback auth_template() :: String.t() | nil
+ def auth_template do
+ implementation().auth_template() || Pleroma.Config.get(:auth_template, "show.html")
+ end
end
diff --git a/lib/pleroma/web/auth/pleroma_database_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex
similarity index 83%
rename from lib/pleroma/web/auth/pleroma_database_authenticator.ex
rename to lib/pleroma/web/auth/pleroma_authenticator.ex
index 39aa1a586..3cc19af01 100644
--- a/lib/pleroma/web/auth/pleroma_database_authenticator.ex
+++ b/lib/pleroma/web/auth/pleroma_authenticator.ex
@@ -1,26 +1,28 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
-defmodule Pleroma.Web.Auth.PleromaDatabaseAuthenticator do
+defmodule Pleroma.Web.Auth.PleromaAuthenticator do
alias Pleroma.User
alias Comeonin.Pbkdf2
- @behaviour Pleroma.Web.Auth.DatabaseAuthenticator
+ @behaviour Pleroma.Web.Auth.Authenticator
def get_user(%Plug.Conn{} = conn) do
%{"authorization" => %{"name" => name, "password" => password}} = conn.params
with {_, %User{} = user} <- {:user, User.get_by_nickname_or_email(name)},
{_, true} <- {:checkpw, Pbkdf2.checkpw(password, user.password_hash)} do
{:ok, user}
else
error ->
{:error, error}
end
end
def handle_error(%Plug.Conn{} = _conn, error) do
error
end
+
+ def auth_template, do: nil
end
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index 5c2b0507c..b16e3b2a7 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -1,219 +1,217 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.OAuth.OAuthController do
use Pleroma.Web, :controller
- alias Pleroma.Web.Auth.DatabaseAuthenticator
+ alias Pleroma.Web.Auth.Authenticator
alias Pleroma.Web.OAuth.Authorization
alias Pleroma.Web.OAuth.Token
alias Pleroma.Web.OAuth.App
alias Pleroma.Repo
alias Pleroma.User
alias Comeonin.Pbkdf2
import Pleroma.Web.ControllerHelper, only: [oauth_scopes: 2]
plug(:fetch_session)
plug(:fetch_flash)
action_fallback(Pleroma.Web.OAuth.FallbackController)
def authorize(conn, params) do
app = Repo.get_by(App, client_id: params["client_id"])
available_scopes = (app && app.scopes) || []
scopes = oauth_scopes(params, nil) || available_scopes
- template = Pleroma.Config.get(:auth_template, "show.html")
-
- render(conn, template, %{
+ render(conn, Authenticator.auth_template(), %{
response_type: params["response_type"],
client_id: params["client_id"],
available_scopes: available_scopes,
scopes: scopes,
redirect_uri: params["redirect_uri"],
state: params["state"],
params: params
})
end
def create_authorization(conn, %{
"authorization" =>
%{
"client_id" => client_id,
"redirect_uri" => redirect_uri
} = auth_params
}) do
- with {_, {:ok, %User{} = user}} <- {:get_user, DatabaseAuthenticator.get_user(conn)},
+ with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn)},
%App{} = app <- Repo.get_by(App, client_id: client_id),
true <- redirect_uri in String.split(app.redirect_uris),
scopes <- oauth_scopes(auth_params, []),
{:unsupported_scopes, []} <- {:unsupported_scopes, scopes -- app.scopes},
# Note: `scope` param is intentionally not optional in this context
{:missing_scopes, false} <- {:missing_scopes, scopes == []},
{:auth_active, true} <- {:auth_active, User.auth_active?(user)},
{:ok, auth} <- Authorization.create_authorization(app, user, scopes) do
redirect_uri =
if redirect_uri == "." do
# Special case: Local MastodonFE
mastodon_api_url(conn, :login)
else
redirect_uri
end
cond do
redirect_uri == "urn:ietf:wg:oauth:2.0:oob" ->
render(conn, "results.html", %{
auth: auth
})
true ->
connector = if String.contains?(redirect_uri, "?"), do: "&", else: "?"
url = "#{redirect_uri}#{connector}"
url_params = %{:code => auth.token}
url_params =
if auth_params["state"] do
Map.put(url_params, :state, auth_params["state"])
else
url_params
end
url = "#{url}#{Plug.Conn.Query.encode(url_params)}"
redirect(conn, external: url)
end
else
{scopes_issue, _} when scopes_issue in [:unsupported_scopes, :missing_scopes] ->
conn
|> put_flash(:error, "Permissions not specified.")
|> put_status(:unauthorized)
|> authorize(auth_params)
{:auth_active, false} ->
conn
|> put_flash(:error, "Account confirmation pending.")
|> put_status(:forbidden)
|> authorize(auth_params)
error ->
- DatabaseAuthenticator.handle_error(conn, error)
+ Authenticator.handle_error(conn, error)
end
end
def token_exchange(conn, %{"grant_type" => "authorization_code"} = params) do
with %App{} = app <- get_app_from_request(conn, params),
fixed_token = fix_padding(params["code"]),
%Authorization{} = auth <-
Repo.get_by(Authorization, token: fixed_token, app_id: app.id),
{:ok, token} <- Token.exchange_token(app, auth),
{:ok, inserted_at} <- DateTime.from_naive(token.inserted_at, "Etc/UTC") do
response = %{
token_type: "Bearer",
access_token: token.token,
refresh_token: token.refresh_token,
created_at: DateTime.to_unix(inserted_at),
expires_in: 60 * 10,
scope: Enum.join(token.scopes)
}
json(conn, response)
else
_error ->
put_status(conn, 400)
|> json(%{error: "Invalid credentials"})
end
end
def token_exchange(
conn,
%{"grant_type" => "password", "username" => name, "password" => password} = params
) do
with %App{} = app <- get_app_from_request(conn, params),
%User{} = user <- User.get_by_nickname_or_email(name),
true <- Pbkdf2.checkpw(password, user.password_hash),
{:auth_active, true} <- {:auth_active, User.auth_active?(user)},
scopes <- oauth_scopes(params, app.scopes),
[] <- scopes -- app.scopes,
true <- Enum.any?(scopes),
{:ok, auth} <- Authorization.create_authorization(app, user, scopes),
{:ok, token} <- Token.exchange_token(app, auth) do
response = %{
token_type: "Bearer",
access_token: token.token,
refresh_token: token.refresh_token,
expires_in: 60 * 10,
scope: Enum.join(token.scopes, " ")
}
json(conn, response)
else
{:auth_active, false} ->
conn
|> put_status(:forbidden)
|> json(%{error: "Account confirmation pending"})
_error ->
put_status(conn, 400)
|> json(%{error: "Invalid credentials"})
end
end
def token_exchange(
conn,
%{"grant_type" => "password", "name" => name, "password" => _password} = params
) do
params =
params
|> Map.delete("name")
|> Map.put("username", name)
token_exchange(conn, params)
end
def token_revoke(conn, %{"token" => token} = params) do
with %App{} = app <- get_app_from_request(conn, params),
%Token{} = token <- Repo.get_by(Token, token: token, app_id: app.id),
{:ok, %Token{}} <- Repo.delete(token) do
json(conn, %{})
else
_error ->
# RFC 7009: invalid tokens [in the request] do not cause an error response
json(conn, %{})
end
end
# XXX - for whatever reason our token arrives urlencoded, but Plug.Conn should be
# decoding it. Investigate sometime.
defp fix_padding(token) do
token
|> URI.decode()
|> Base.url_decode64!(padding: false)
|> Base.url_encode64(padding: false)
end
defp get_app_from_request(conn, params) do
# Per RFC 6749, HTTP Basic is preferred to body params
{client_id, client_secret} =
with ["Basic " <> encoded] <- get_req_header(conn, "authorization"),
{:ok, decoded} <- Base.decode64(encoded),
[id, secret] <-
String.split(decoded, ":")
|> Enum.map(fn s -> URI.decode_www_form(s) end) do
{id, secret}
else
_ -> {params["client_id"], params["client_secret"]}
end
if client_id && client_secret do
Repo.get_by(
App,
client_id: client_id,
client_secret: client_secret
)
else
nil
end
end
end

File Metadata

Mime Type
text/x-diff
Expires
Fri, Sep 18, 11:06 PM (4 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1765154
Default Alt Text
(10 KB)

Event Timeline