Put API v2 rate limit token to cookies

pull/7946/head
Nikita Pozdniakov 1 year ago
parent c344d83d1b
commit cd19739347
No known key found for this signature in database
GPG Key ID: F344106F9804FE5F
  1. 3
      apps/block_scout_web/config/config.exs
  2. 4
      apps/block_scout_web/lib/block_scout_web/api_key_v2_router.ex
  3. 16
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/api_key_controller.ex
  4. 17
      apps/block_scout_web/lib/block_scout_web/views/access_helper.ex

@ -12,7 +12,8 @@ config :block_scout_web,
cookie_domain: System.get_env("SESSION_COOKIE_DOMAIN"),
# 604800 seconds, 1 week
session_cookie_ttl: 60 * 60 * 24 * 7,
invalid_session_key: "invalid_session"
invalid_session_key: "invalid_session",
api_v2_temp_token_key: "api_v2_temp_client_key"
config :block_scout_web,
admin_panel_enabled: System.get_env("ADMIN_PANEL_ENABLED", "") == "true"

@ -9,8 +9,6 @@ defmodule BlockScoutWeb.APIKeyV2Router do
plug(Logger, application: :api_v2)
plug(:accepts, ["json"])
plug(CheckApiV2)
plug(:fetch_session)
plug(:protect_from_forgery)
end
scope "/", as: :api_v2 do
@ -18,6 +16,6 @@ defmodule BlockScoutWeb.APIKeyV2Router do
alias BlockScoutWeb.API.V2
get("/", V2.APIKeyController, :get_key)
post("/", V2.APIKeyController, :get_key)
end
end

@ -2,10 +2,13 @@ defmodule BlockScoutWeb.API.V2.APIKeyController do
use BlockScoutWeb, :controller
alias BlockScoutWeb.AccessHelper
alias Plug.Crypto
@api_v2_temp_token_key Application.compile_env(:block_scout_web, :api_v2_temp_token_key)
action_fallback(BlockScoutWeb.API.V2.FallbackController)
plug(:fetch_cookies, signed: [@api_v2_temp_token_key])
def get_key(conn, params) do
helper = Application.get_env(:block_scout_web, :captcha_helper)
ttl = Application.get_env(:block_scout_web, :api_rate_limit)[:api_v2_token_ttl_seconds]
@ -14,11 +17,14 @@ defmodule BlockScoutWeb.API.V2.APIKeyController do
{:recaptcha, false} <- {:recaptcha, is_nil(recaptcha_response)},
{:recaptcha, true} <- {:recaptcha, helper.recaptcha_passed?(recaptcha_response)} do
conn
|> put_resp_cookie(@api_v2_temp_token_key, %{ip: AccessHelper.conn_to_ip_string(conn)},
max_age: ttl,
sign: true,
same_site: "Lax",
domain: Application.get_env(:block_scout_web, :cookie_domain)
)
|> json(%{
key:
Crypto.sign(conn.secret_key_base, conn.secret_key_base, %{ip: AccessHelper.conn_to_ip_string(conn)},
max_age: ttl
)
message: "OK"
})
end
end

@ -11,7 +11,7 @@ defmodule BlockScoutWeb.AccessHelper do
alias BlockScoutWeb.WebRouter.Helpers
alias Explorer.AccessHelper
alias Explorer.Account.Api.Key, as: ApiKey
alias Plug.{Conn, Crypto}
alias Plug.Conn
alias RemoteIp
@ -77,7 +77,7 @@ defmodule BlockScoutWeb.AccessHelper do
ip_string = conn_to_ip_string(conn)
plan = get_plan(conn.query_params)
token = get_ui_v2_token(conn, conn.query_params, ip_string)
token = get_ui_v2_token(conn, ip_string)
user_agent = get_user_agent(conn)
@ -167,18 +167,19 @@ defmodule BlockScoutWeb.AccessHelper do
to_string(:inet_parse.ntoa(ip))
end
defp get_ui_v2_token(conn, %{"token" => token}, ip_string) do
case is_api_v2_request?(conn) && Crypto.verify(conn.secret_key_base, conn.secret_key_base, token) do
{:ok, %{ip: ^ip_string}} ->
token
defp get_ui_v2_token(conn, ip_string) do
api_v2_temp_token_key = Application.get_env(:block_scout_web, :api_v2_temp_token_key)
conn = Conn.fetch_cookies(conn, signed: [api_v2_temp_token_key])
case is_api_v2_request?(conn) && conn.cookies[api_v2_temp_token_key] do
%{ip: ^ip_string} ->
conn.req_cookies[api_v2_temp_token_key]
_ ->
nil
end
end
defp get_ui_v2_token(_conn, _params, _ip_string), do: nil
defp get_user_agent(conn) do
case Conn.get_req_header(conn, "user-agent") do
[agent] ->

Loading…
Cancel
Save