在Elixir/Erlang中验证Firebase ID令牌

5

我已经为前端身份验证设置了Firebase,并将身份令牌(即JWT)发送到我的Phoenix后端。

现在我在尝试验证JWT时遇到了困难。

Google关于此事的说明在这里。简而言之,获取公开可访问的证书并使用它来验证JWT签名是否使用正确的私钥进行签名。

到目前为止,我已完成以下工作:

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

我有些迷茫。我需要将公共证书转换为公钥吗?如何创建使用RS256签名算法和公共证书的Joken.Signer?我也欢迎不使用Joken的解决方案。

谢谢!

2个回答

4
稍微更通俗易懂的@fetching_water解决方案的版本,使用了更多的模式匹配并使用了Hackney而不是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

3
我找到了JOSE库 :D
为了完成代码...
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代码可能需要优化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接