• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / supavisor / e5e7ebfe80dbec4965226225050d4ef5c8216e88-PR-605

21 Feb 2025 02:35PM UTC coverage: 45.973% (-0.03%) from 46.003%
e5e7ebfe80dbec4965226225050d4ef5c8216e88-PR-605

Pull #605

github

hauleth
fix: remaining SSL connections that need to set `verify_none` option
Pull Request #605: fix: remaining SSL connections that need to set `verify_none` option

2 of 9 new or added lines in 3 files covered. (22.22%)

267 existing lines in 26 files now uncovered.

959 of 2086 relevant lines covered (45.97%)

635.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

65.52
/lib/supavisor/jwt.ex
1
defmodule Supavisor.Jwt do
2
  @moduledoc """
3
  Parse JWT and verify claims
4
  """
5
  require Logger
6

7
  defmodule Token do
8
    @moduledoc false
9
    use Joken.Config
10

11
    def default_signer(secret),
UNCOV
12
      do: Joken.Signer.create("HS256", secret)
3✔
13

UNCOV
14
    def gen!(claims \\ %{}, secret)
1✔
15

16
    def gen!(claims, secret) when is_binary(secret),
UNCOV
17
      do: gen!(claims, default_signer(secret))
3✔
18

19
    def gen!(claims, signer) do
UNCOV
20
      default = %{"exp" => Joken.current_time() + 3600}
3✔
21

UNCOV
22
      generate_and_sign!(Map.merge(default, claims), signer)
3✔
23
    end
24

25
    @impl true
26
    def token_config do
27
      Application.fetch_env!(:supavisor, :jwt_claim_validators)
28
      |> Enum.reduce(%{}, fn {claim_key, expected_val}, claims ->
29
        add_claim_validator(claims, claim_key, expected_val)
×
30
      end)
UNCOV
31
      |> add_claim_validator("exp")
14✔
32
    end
33

34
    defp add_claim_validator(claims, "exp") do
UNCOV
35
      add_claim(claims, "exp", nil, &(&1 > current_time()))
14✔
36
    end
37

38
    defp add_claim_validator(claims, claim_key, expected_val) do
39
      add_claim(claims, claim_key, nil, &(&1 == expected_val))
×
40
    end
41
  end
42

43
  @hs_algorithms ["HS256", "HS384", "HS512"]
44

45
  @spec authorize(String.t(), String.t()) :: {:ok, map()} | {:error, any()}
46
  def authorize(token, secret) when is_binary(token) do
47
    token
48
    |> clean_token()
UNCOV
49
    |> verify(secret)
12✔
50
  end
51

52
  defp clean_token(token) do
UNCOV
53
    Regex.replace(~r/\s|\n/, URI.decode(token), "")
12✔
54
  end
55

56
  def authorize_conn(token, secret) do
57
    case authorize(token, secret) do
×
58
      {:ok, claims} ->
59
        required = MapSet.new(["role", "exp"])
×
60
        claims_keys = Map.keys(claims) |> MapSet.new()
×
61

62
        if MapSet.subset?(required, claims_keys) do
×
63
          {:ok, claims}
64
        else
65
          {:error, "Fields `role` and `exp` are required in JWT"}
66
        end
67

68
      {:error, reason} ->
×
69
        {:error, reason}
70
    end
71
  end
72

73
  @spec verify(String.t(), String.t()) :: {:ok, map()} | {:error, any()}
74
  def verify(token, secret) when is_binary(token) do
UNCOV
75
    with {:ok, _claims} <- check_claims_format(token),
12✔
UNCOV
76
         {:ok, header} <- check_header_format(token),
11✔
UNCOV
77
         {:ok, signer} <- generate_signer(header, secret) do
11✔
UNCOV
78
      Token.verify_and_validate(token, signer)
11✔
79
    end
80
  end
81

82
  def verify(_token, _secret), do: {:error, :token_not_a_string}
×
83

84
  defp check_header_format(token) do
UNCOV
85
    case Joken.peek_header(token) do
11✔
UNCOV
86
      {:ok, header} when is_map(header) -> {:ok, header}
11✔
87
      _error -> {:error, :expected_header_map}
×
88
    end
89
  end
90

91
  defp check_claims_format(token) do
UNCOV
92
    case Joken.peek_claims(token) do
12✔
UNCOV
93
      {:ok, claims} when is_map(claims) -> {:ok, claims}
11✔
UNCOV
94
      _error -> {:error, :expected_claims_map}
1✔
95
    end
96
  end
97

UNCOV
98
  defp generate_signer(%{"typ" => "JWT", "alg" => alg}, jwt_secret) when alg in @hs_algorithms do
11✔
99
    {:ok, Joken.Signer.create(alg, jwt_secret)}
100
  end
101

102
  defp generate_signer(_header, _secret), do: {:error, :error_generating_signer}
×
103
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc