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

malach-it / boruta_auth / 954161a5b397cc94069ec938dc16fcb785e37074-PR-29

18 Jan 2025 10:28PM UTC coverage: 85.651% (-4.3%) from 89.944%
954161a5b397cc94069ec938dc16fcb785e37074-PR-29

Pull #29

github

patatoid
refactor verifiable credentials status tokens
Pull Request #29: Agent credentials PoC

188 of 304 new or added lines in 20 files covered. (61.84%)

3 existing lines in 1 file now uncovered.

1552 of 1812 relevant lines covered (85.65%)

85.85 hits per line

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

0.0
/lib/boruta/adapters/universal/signatures.ex
1
defmodule Boruta.Universal.Signatures do
2
  @behaviour Boruta.Oauth.Signatures
3

4
  defmodule Token do
5
    @moduledoc false
6

7
    use Joken.Config
8

NEW
9
    def token_config, do: %{}
×
10
  end
11

12
  @moduledoc false
13

14
  alias Boruta.Oauth.Client
15
  alias Boruta.Universal.Signatures.SigningKey
16

17
  @signature_algorithms [
18
    EdDSA: [type: :asymmetric, hash_algorithm: :SHA256, binary_size: 16],
19
  ]
20

21
  @spec signature_algorithms() :: list(atom())
NEW
22
  def signature_algorithms, do: Keyword.keys(@signature_algorithms)
×
23

24
  @spec hash_alg(Client.t()) :: hash_alg :: atom()
25
  def hash_alg(%Client{id_token_signature_alg: signature_alg}),
NEW
26
    do: @signature_algorithms[String.to_atom(signature_alg)][:hash_algorithm]
×
27

28
  @spec hash_binary_size(Client.t()) :: binary_size :: integer()
29
  def hash_binary_size(%Client{id_token_signature_alg: signature_alg}),
NEW
30
    do: @signature_algorithms[String.to_atom(signature_alg)][:binary_size]
×
31

32
  @spec hash(string :: String.t(), client :: Client.t()) :: hash :: String.t()
33
  def hash(string, client) do
34
    hash_alg(client)
35
    |> Atom.to_string()
36
    |> String.downcase()
37
    |> String.to_atom()
38
    |> :crypto.hash(string)
39
    |> binary_part(0, hash_binary_size(client))
NEW
40
    |> Base.url_encode64(padding: false)
×
41
  end
42

43
  @spec id_token_sign(payload :: map(), client :: Client.t()) ::
44
          jwt :: String.t() | {:error, reason :: String.t()}
45
  def id_token_sign(
46
        payload,
47
        %Client{} = client
48
      ) do
NEW
49
    with {:ok, key} <- get_signing_key(client, :id_token),
×
NEW
50
         {:ok, token} <- SigningKey.encode_and_sign_with_key(key, payload) do
×
NEW
51
        token
×
52

53
      else
54
      {:error, error} ->
55
        {:error, "Could not sign the given payload with client credentials: #{inspect(error)}"}
56
    end
57
  end
58

59
  @spec userinfo_sign(payload :: map(), client :: Client.t()) ::
60
          jwt :: String.t() | {:error, reason :: String.t()}
61
  def userinfo_sign(
62
        payload,
63
        %Client{
64
          userinfo_signed_response_alg: signature_alg
65
        } = client
66
      ) do
NEW
67
    with {:ok, signing_key} <- get_signing_key(client, :userinfo) do
×
NEW
68
      signer =
×
69
        case userinfo_signature_type(client) do
70
          :symmetric ->
NEW
71
            Joken.Signer.create(signature_alg, signing_key.secret)
×
72

73
          :asymmetric ->
NEW
74
            Joken.Signer.create(
×
75
              signature_alg,
NEW
76
              %{"pem" => signing_key.private_key},
×
77
              %{
NEW
78
                "kid" => signing_key.kid,
×
NEW
79
                "trust_chain" => signing_key.trust_chain
×
80
              }
81
            )
82
        end
83

NEW
84
      case Token.encode_and_sign(payload, signer) do
×
85
        {:ok, token, _payload} ->
NEW
86
          token
×
87

NEW
88
        {:error, error} ->
×
89
          {:error, "Could not sign the given payload with client credentials: #{inspect(error)}"}
90
      end
91
    end
92
  end
93

94
  @spec verifiable_credential_sign(payload :: map(), client :: Client.t(), format :: String.t()) ::
95
          jwt :: String.t() | {:error, reason :: String.t()}
96
  def verifiable_credential_sign(
97
        credential,
98
        %Client{} = client,
99
        _format
100
      ) do
NEW
101
        with {:ok, key} <- get_signing_key(client, :verifiable_credential),
×
NEW
102
             {:ok, credential} <- SigningKey.encode_and_sign_with_key(key, credential) do
×
NEW
103
        credential
×
104
    end
105
  end
106

107
  @spec userinfo_signature_type(Client.t()) :: userinfo_token_signature_type :: atom()
108
  def userinfo_signature_type(%Client{userinfo_signed_response_alg: signature_alg}),
NEW
109
    do: @signature_algorithms[String.to_atom(signature_alg)][:type]
×
110

111
  @spec id_token_signature_type(Client.t()) :: id_token_signature_type :: atom()
112
  def id_token_signature_type(%Client{id_token_signature_alg: signature_alg}),
NEW
113
    do: @signature_algorithms[String.to_atom(signature_alg)][:type]
×
114

NEW
115
  defp get_signing_key(client, :id_token) do
×
116
    {:ok,
117
     %SigningKey{
118
       type: :internal,
NEW
119
       private_key: client.private_key,
×
NEW
120
       public_key: client.public_key,
×
NEW
121
       secret: client.secret,
×
NEW
122
       kid: client.did
×
123
     }}
124
  end
125

NEW
126
  defp get_signing_key(client, :userinfo) do
×
127
    {:ok,
128
     %SigningKey{
129
       type: :internal,
NEW
130
       private_key: client.private_key,
×
NEW
131
       public_key: client.public_key,
×
NEW
132
       secret: client.secret,
×
NEW
133
       kid: client.did
×
134
     }}
135
  end
136

NEW
137
  defp get_signing_key(client, :verifiable_credential) do
×
138
    {:ok,
139
     %SigningKey{
140
       type: :universal,
NEW
141
       private_key: client.private_key,
×
NEW
142
       public_key: client.public_key,
×
NEW
143
       kid: client.did
×
144
     }}
145
  end
146
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