Create tesla middleware for adding signature to federation requests
Change repo structure
This commit is contained in:
parent
214293323c
commit
be9860f7d0
23 changed files with 83 additions and 58 deletions
|
@ -1,5 +1,5 @@
|
|||
defmodule MatrixServerWeb.Plug.AuthenticateClient do
|
||||
import MatrixServerWeb.Plug.Error
|
||||
defmodule MatrixServerWeb.Client.AuthenticateClientPlug do
|
||||
import MatrixServerWeb.Error
|
||||
import Plug.Conn
|
||||
|
||||
alias MatrixServer.Account
|
|
@ -2,7 +2,7 @@ defmodule MatrixServerWeb.Client.AccountController do
|
|||
use MatrixServerWeb, :controller
|
||||
|
||||
import MatrixServer
|
||||
import MatrixServerWeb.Plug.Error
|
||||
import MatrixServerWeb.Error
|
||||
|
||||
alias MatrixServer.{Account, Repo}
|
||||
alias Plug.Conn
|
|
@ -1,7 +1,7 @@
|
|||
defmodule MatrixServerWeb.Client.AliasesController do
|
||||
use MatrixServerWeb, :controller
|
||||
|
||||
import MatrixServerWeb.Plug.Error
|
||||
import MatrixServerWeb.Error
|
||||
|
||||
alias MatrixServer.Alias
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
defmodule MatrixServerWeb.Client.InfoController do
|
||||
use MatrixServerWeb, :controller
|
||||
|
||||
import MatrixServerWeb.Plug.Error
|
||||
import MatrixServerWeb.Error
|
||||
|
||||
@supported_versions ["r0.6.1"]
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
defmodule MatrixServerWeb.Client.LoginController do
|
||||
use MatrixServerWeb, :controller
|
||||
|
||||
import MatrixServerWeb.Plug.Error
|
||||
import MatrixServerWeb.Error
|
||||
import Ecto.Changeset
|
||||
|
||||
alias MatrixServer.{Repo, Account}
|
||||
alias MatrixServerWeb.Request.Login
|
||||
alias MatrixServerWeb.Client.Request.Login
|
||||
alias Ecto.Changeset
|
||||
|
||||
@login_type "m.login.password"
|
|
@ -1,11 +1,11 @@
|
|||
defmodule MatrixServerWeb.Client.RegisterController do
|
||||
use MatrixServerWeb, :controller
|
||||
|
||||
import MatrixServerWeb.Plug.Error
|
||||
import MatrixServerWeb.Error
|
||||
import Ecto.Changeset
|
||||
|
||||
alias MatrixServer.{Repo, Account}
|
||||
alias MatrixServerWeb.Request.Register
|
||||
alias MatrixServerWeb.Client.Request.Register
|
||||
alias Ecto.Changeset
|
||||
|
||||
@register_type "m.login.dummy"
|
|
@ -1,11 +1,11 @@
|
|||
defmodule MatrixServerWeb.Client.RoomController do
|
||||
use MatrixServerWeb, :controller
|
||||
|
||||
import MatrixServerWeb.Plug.Error
|
||||
import MatrixServerWeb.Error
|
||||
import Ecto.Changeset
|
||||
|
||||
alias MatrixServer.Room
|
||||
alias MatrixServerWeb.Request.{CreateRoom}
|
||||
alias MatrixServerWeb.Client.Request.CreateRoom
|
||||
alias Ecto.Changeset
|
||||
alias Plug.Conn
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
defmodule MatrixServerWeb.Request.CreateRoom do
|
||||
defmodule MatrixServerWeb.Client.Request.CreateRoom do
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Changeset
|
|
@ -1,4 +1,4 @@
|
|||
defmodule MatrixServerWeb.Request.Login do
|
||||
defmodule MatrixServerWeb.Client.Request.Login do
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Changeset
|
|
@ -1,4 +1,4 @@
|
|||
defmodule MatrixServerWeb.Request.Register do
|
||||
defmodule MatrixServerWeb.Client.Request.Register do
|
||||
use Ecto.Schema
|
||||
|
||||
import Ecto.Changeset
|
|
@ -1,4 +1,4 @@
|
|||
defmodule MatrixServerWeb.Plug.Error do
|
||||
defmodule MatrixServerWeb.Error do
|
||||
import Plug.Conn
|
||||
import Phoenix.Controller, only: [json: 2]
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
defmodule MatrixServerWeb.AuthenticateServer do
|
||||
import MatrixServerWeb.Plug.Error
|
||||
defmodule MatrixServerWeb.Federation.AuthenticateServer do
|
||||
import MatrixServerWeb.Error
|
||||
|
||||
alias MatrixServer.{SigningKey, ServerKeyInfo}
|
||||
|
||||
|
@ -71,7 +71,7 @@ defmodule MatrixServerWeb.AuthenticateServer do
|
|||
action = action_name(conn)
|
||||
|
||||
if action not in unquote(except) do
|
||||
case MatrixServerWeb.AuthenticateServer.authenticate(conn) do
|
||||
case MatrixServerWeb.Federation.AuthenticateServer.authenticate(conn) do
|
||||
{origin, _key, _sig} ->
|
||||
conn = Plug.Conn.assign(conn, :origin, origin)
|
||||
apply(__MODULE__, action, [conn, conn.params])
|
|
@ -1,7 +1,7 @@
|
|||
defmodule MatrixServerWeb.Federation.KeyController do
|
||||
use MatrixServerWeb, :controller
|
||||
|
||||
import MatrixServerWeb.Plug.Error
|
||||
import MatrixServerWeb.Error
|
||||
|
||||
alias MatrixServer.KeyServer
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
defmodule MatrixServerWeb.Federation.QueryController do
|
||||
use MatrixServerWeb, :controller
|
||||
use MatrixServerWeb.AuthenticateServer
|
||||
use MatrixServerWeb.Federation.AuthenticateServer
|
||||
|
||||
import MatrixServerWeb.Plug.Error
|
||||
import MatrixServerWeb.Error
|
||||
import Ecto.Query
|
||||
|
||||
alias MatrixServer.{Repo, Account}
|
|
@ -1,20 +1,26 @@
|
|||
defmodule MatrixServerWeb.FederationClient do
|
||||
defmodule MatrixServerWeb.Federation.HTTPClient do
|
||||
use Tesla
|
||||
|
||||
alias MatrixServerWeb.Endpoint
|
||||
alias MatrixServerWeb.Federation.Request.GetSigningKeys
|
||||
alias MatrixServerWeb.Federation.Middleware.SignRequest
|
||||
alias MatrixServerWeb.Router.Helpers, as: RouteHelpers
|
||||
|
||||
# TODO: Maybe create database-backed homeserver struct to pass to client function.
|
||||
|
||||
@middleware [
|
||||
Tesla.Middleware.JSON
|
||||
]
|
||||
# TODO: Fix error propagation.
|
||||
|
||||
@adapter {Tesla.Adapter.Finch, name: MatrixServerWeb.HTTPClient}
|
||||
|
||||
def client(server_name) do
|
||||
Tesla.client([{Tesla.Middleware.BaseUrl, "http://" <> server_name} | @middleware], @adapter)
|
||||
Tesla.client(
|
||||
[
|
||||
{Tesla.Middleware.Opts, [server_name: server_name]},
|
||||
SignRequest,
|
||||
{Tesla.Middleware.BaseUrl, "http://" <> server_name},
|
||||
Tesla.Middleware.JSON
|
||||
],
|
||||
@adapter
|
||||
)
|
||||
end
|
||||
|
||||
def get_signing_keys(client) do
|
||||
|
@ -45,30 +51,11 @@ defmodule MatrixServerWeb.FederationClient do
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: Create tesla middleware to add signature and headers.
|
||||
def query_profile(client, server_name, user_id, field \\ nil) do
|
||||
origin = MatrixServer.server_name()
|
||||
def query_profile(client, user_id, field \\ nil) do
|
||||
path = RouteHelpers.query_path(Endpoint, :profile) |> Tesla.build_url(user_id: user_id)
|
||||
path = if field, do: Tesla.build_url(path, field: field), else: path
|
||||
|
||||
object_to_sign = %{
|
||||
method: "GET",
|
||||
uri: URI.decode_www_form(path),
|
||||
origin: origin,
|
||||
destination: server_name
|
||||
}
|
||||
|
||||
{:ok, signature, key_id} = MatrixServer.KeyServer.sign_object(object_to_sign)
|
||||
signatures = %{origin => %{key_id => signature}}
|
||||
auth_headers = create_signature_authorization_headers(signatures, origin)
|
||||
|
||||
Tesla.get(client, path, headers: auth_headers)
|
||||
end
|
||||
|
||||
defp create_signature_authorization_headers(signatures, origin) do
|
||||
Enum.map(signatures[origin], fn {key, sig} ->
|
||||
{"Authorization", "X-Matrix origin=#{origin},key=\"#{key}\",sig=\"#{sig}\""}
|
||||
end)
|
||||
Tesla.get(client, path)
|
||||
end
|
||||
|
||||
defp tesla_request(method, client, path, request_schema) do
|
38
lib/matrix_server_web/federation/sign_request_middleware.ex
Normal file
38
lib/matrix_server_web/federation/sign_request_middleware.ex
Normal file
|
@ -0,0 +1,38 @@
|
|||
defmodule MatrixServerWeb.Federation.Middleware.SignRequest do
|
||||
@behaviour Tesla.Middleware
|
||||
|
||||
def call(%Tesla.Env{opts: opts} = env, next, _opts) do
|
||||
sign = Keyword.get(opts, :sign, true)
|
||||
|
||||
case sign_request(env, sign) do
|
||||
%Tesla.Env{} = env -> Tesla.run(env, next)
|
||||
:error -> {:error, :sign_request}
|
||||
end
|
||||
end
|
||||
|
||||
defp sign_request(env, false), do: env
|
||||
|
||||
defp sign_request(%Tesla.Env{method: method, url: path, opts: opts} = env, true) do
|
||||
origin = MatrixServer.server_name()
|
||||
|
||||
object_to_sign = %{
|
||||
method: Atom.to_string(method) |> String.upcase(),
|
||||
origin: origin,
|
||||
uri: URI.decode_www_form(path),
|
||||
destination: Keyword.fetch!(opts, :server_name)
|
||||
}
|
||||
|
||||
with {:ok, sig, key_id} <- MatrixServer.KeyServer.sign_object(object_to_sign) do
|
||||
sigs = %{origin => %{key_id => sig}}
|
||||
auth_headers = create_signature_authorization_headers(sigs, origin)
|
||||
|
||||
Tesla.put_headers(env, auth_headers)
|
||||
end
|
||||
end
|
||||
|
||||
defp create_signature_authorization_headers(signatures, origin) do
|
||||
Enum.map(signatures[origin], fn {key, sig} ->
|
||||
{"Authorization", "X-Matrix origin=#{origin},key=\"#{key}\",sig=\"#{sig}\""}
|
||||
end)
|
||||
end
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
defmodule MatrixServerWeb.Router do
|
||||
use MatrixServerWeb, :router
|
||||
|
||||
alias MatrixServerWeb.Plug.AuthenticateClient
|
||||
alias MatrixServerWeb.Client.AuthenticateClientPlug
|
||||
|
||||
# TODO: might be able to handle malformed JSON with custom body reader:
|
||||
# https://elixirforum.com/t/write-malformed-json-in-the-body-plug/30578/13
|
||||
|
@ -12,7 +12,7 @@ defmodule MatrixServerWeb.Router do
|
|||
|
||||
pipeline :authenticate_client do
|
||||
plug :accepts, ["json"]
|
||||
plug AuthenticateClient
|
||||
plug AuthenticateClientPlug
|
||||
end
|
||||
|
||||
pipeline :authenticate_server do
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue