Packages

A small library for verifying FirebaseAuth ID tokens. See Firebase documention: https://firebase.google.com/docs/auth/admin/verify-id-tokens#verify_id_tokens_using_a_third-party_jwt_library

Retired package: Deprecated - No longer maintained\! Seek other alternatives or fork/take over

Current section

Files

Jump to
firebase_auth_verifier lib firebase_auth_verifier.ex
Raw

lib/firebase_auth_verifier.ex

defmodule FirebaseAuthVerifier do
@moduledoc Keyword.fetch!(Mix.Project.config(), :description)
alias FirebaseAuthVerifier.CertificateManager
alias FirebaseAuthVerifier.SignerSource
@doc """
Verifies a JWT token, returning either `{:ok, claims}`, where `claims` is the decoded
map of claims in the JWT, if it passes verification, or `{:error, term()}` if it does not.
"""
@spec verify(binary(), non_neg_integer(), SignerSource.t())
:: {:ok, %{required(binary()) => term()}} | {:error, term()}
def verify(jwt, retries \\ 3, callback \\ CertificateManager)
def verify(jwt, retries, callback) when is_integer(retries) and retries > 0 do
verify_p(jwt, retries, callback)
end
def verify(_, _, _callback),
do: {:error, :bad_arguments}
defp verify_p(_jwt, 0, _callback),
do: {:error, :timeout}
defp verify_p(jwt, n, callback) when is_integer(n) do
try do
signers = callback.get_signers() |> Enum.map(fn {_key, v} -> v end)
try_to_verify(jwt, signers)
catch
:exit, _reason ->
verify_p(jwt, n - 1, callback)
end
end
defp try_to_verify(_jwt, []), do: {:error, :no_valid_signer}
defp try_to_verify(jwt, [signer|rest]) do
case Joken.Signer.verify(jwt, signer) do
{:ok, claims = %{"aud" => aud, "exp" => exp, "sub" => subject_id}} ->
Logger.metadata(subject_id: subject_id)
project_id = Application.get_env(:firebase_auth_verifier, :project_id) ||
raise FirebaseAuthVerifier.ConfigurationError, message: "no project_id configured"
res = exp
|> DateTime.from_unix!()
|> DateTime.diff(DateTime.utc_now())
cond do
res < 0 ->
{:error, :expired_token}
project_id != aud ->
{:error, :invalid_aud}
true ->
{:ok, claims}
end
{:error, _reason} ->
try_to_verify(jwt, rest)
end
end
end