defmodule FirebaseAuth do
@moduledoc """
Documentation for `FirebaseAuth`.
"""
alias FirebaseAuth.PublicKeyServer
@doc """
Verify the accessToken/idToken obtained after logging in with Firebase
"""
@spec verify_token(binary(), binary()) :: {:ok, map()} | {:error, term()}
def verify_token(token, project_id) when is_binary(token) do
with {:ok, %{"kid" => kid}} <- Joken.peek_header(token),
{:ok, public_key} <- PublicKeyServer.get_key(kid),
signer <- create_signer(public_key),
token_config <- gen_token_config(project_id) do
case Joken.verify_and_validate(token_config, token, signer) do
{:ok, claims} -> {:ok, claims}
{:error, _} = error -> error
end
end
end
defp gen_token_config(project_id) do
%{}
|> Joken.Config.add_claim("exp", nil, &(&1 > :os.system_time(:second)))
|> Joken.Config.add_claim("iat", nil, &(&1 < :os.system_time(:second)))
|> Joken.Config.add_claim("aud", nil, &(&1 == project_id))
|> Joken.Config.add_claim("iss", nil, &(&1 == "https://securetoken.google.com/#{project_id}"))
|> Joken.Config.add_claim("sub", nil, &(String.trim(&1) != ""))
|> Joken.Config.add_claim("auth_time", nil, &(&1 < :os.system_time(:second)))
end
defp create_signer(key) do
Joken.Signer.create("RS256", %{"pem" => key})
end
end