在Elixir/Erlang中验证Firebase ID令牌

hpxqektj  于 2022-12-08  发布在  Erlang
关注(0)|答案(2)|浏览(159)

I've set up Firebase for frontend authentication and I am sending the ID token, which is a JWT, to my phoenix backend.
I am now stuck trying to verify the JWT.
Google instructions regarding the matter are here. tldr, grab the publicly accessible certificate and use it to verify the JWT signature was signed with the correct private key.
I have this so far

def verify(token) do
  {:ok, resp} = HTTPoison.get(@cert_url)
  %{body: body} = resp
  body = Poison.Parser.parse!(body, %{})
  {:ok, header} = Joken.peek_header(token)
  cert = body[header["kid"]]
end

I'm lost there. Do I need to convert the public certificate to a public key? How do I create a Joken.Signer with RS256 signing algorithm and the public certificate? I am open to solutions that don't use Joken as well.
Thank you!

vql8enpb

vql8enpb1#

@fetching_water的解决方案的一个稍微更习惯的版本,它使用更多的模式匹配,并使用哈克尼而不是HTTPoison:

@cert_url "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com"

def verify!(token) do
  {:ok, 200, _headers, ref} = :hackney.get(@cert_url)
  {:ok, body} = :hackney.body(ref)
  {:ok, %{"kid" => kid}} = Joken.peek_header(token)

  {true, %{fields: fields}, _} =
    body
    |> Jason.decode!()
    |> JOSE.JWK.from_firebase()
    |> Map.fetch!(kid)
    |> JOSE.JWT.verify(token)

  fields
end
nwlls2ji

nwlls2ji2#

I found the JOSE library :D
To finish up the code…

def verify(token) do
  {:ok, resp} = HTTPoison.get(@cert_url)
  %{body: body} = resp
  certs = Poison.Parser.parse!(body, %{})
  {:ok, header} = Joken.peek_header(token)
  jwks = JOSE.JWK.from_firebase(certs)
  jwk = jwks[header["kid"]] |> JOSE.JWK.to_map |> elem(1)
  {true, jose_jwt, _} = JOSE.JWT.verify(jwk, token)
  fields = JOSE.JWT.to_map(jose_jwt) |> elem(1)
  {:ok, fields}
end

Elixir code can probably be cleaned up ^_^

相关问题