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