sign.ex (2026B)
1 # Zenflows is designed to implement the Valueflows vocabulary, 2 # written and maintained by srfsh <info@dyne.org>. 3 # Copyright (C) 2021-2023 Dyne.org foundation <foundation@dyne.org>. 4 # 5 # This program is free software: you can redistribute it and/or modify 6 # it under the terms of the GNU Affero General Public License as published by 7 # the Free Software Foundation, either version 3 of the License, or 8 # (at your option) any later version. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU Affero General Public License for more details. 14 # 15 # You should have received a copy of the GNU Affero General Public License 16 # along with this program. If not, see <https://www.gnu.org/licenses/>. 17 18 defmodule Zenflows.GQL.MW.Sign do 19 @moduledoc """ 20 Absinthe middleware to verify GraphQL calls. 21 """ 22 23 @behaviour Absinthe.Middleware 24 25 alias Zenflows.Restroom 26 alias Zenflows.VF.Person 27 28 @missing_headers_auth_call "couldn't aunthenticate: zenflows-user and/or zenflows-sign headers are missing" 29 30 @impl true 31 def call(res, _opts) do 32 if res.context.authenticate_calls? do 33 with {:ok, username, sign, body} <- fetch_ctx(res), 34 {:ok, per} <- fetch_user(username), 35 :ok <- verify_gql(body, sign, per) do 36 put_in(res.context[:req_user], per) 37 else x -> 38 Absinthe.Resolution.put_result(res, x) 39 end 40 else 41 res 42 end 43 end 44 45 defp fetch_ctx(res) do 46 case res.context do 47 %{gql_user: username, gql_sign: sign, gql_body: body} -> 48 {:ok, username, sign, body} 49 _ -> {:error, @missing_headers_auth_call} 50 end 51 end 52 53 defp fetch_user(username) do 54 case Person.Domain.one(user: username) do 55 {:ok, user} -> {:ok, user} 56 _ -> {:error, "user not found"} 57 end 58 end 59 60 defp verify_gql(body, sign, per) do 61 case Restroom.verify_graphql(body, sign, per.eddsa_public_key) do 62 :ok -> :ok 63 {:error, reason} -> 64 {:error, 65 """ 66 authentication error. 67 68 details: 69 70 #{reason} 71 """} 72 end 73 end 74 end