tusker_push/lib/tusker_push/apns/token.ex

58 lines
1.2 KiB
Elixir

defmodule TuskerPush.Apns.Token do
use GenServer
require Logger
def start_link(_) do
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
end
def current do
GenServer.call(__MODULE__, :current)
end
@impl true
def init(_) do
Logger.debug("Apns.Token initialized, scheduling update")
Process.send_after(self(), :refresh, 1000 * 60 * 45)
{:ok, generate_token()}
end
@impl true
def handle_info(:refresh, _old_token) do
Logger.debug("Apns.Token regenerated")
Process.send_after(self(), :refresh, 1000 * 60 * 45)
{:noreply, generate_token()}
end
@impl true
def handle_call(:current, _from, token) do
{:reply, token, token}
end
defp generate_token do
# can't use Joken because it always inserts "typ": "JWT" which APNS doesn't like
config = Application.fetch_env!(:tusker_push, :apns)
jwk = JOSE.JWK.from_pem(config[:key_pem])
jws =
JOSE.JWS.from_map(%{
"kid" => config[:key_id],
"alg" => "ES256"
})
claims = %{
"iss" => config[:team_id],
"iat" => DateTime.utc_now() |> DateTime.to_unix()
}
{_, result} =
JOSE.JWT.sign(jwk, jws, claims)
|> JOSE.JWS.compact()
result
end
end