Packages
pigeon
2.0.0
2.0.1
2.0.0
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.0
1.3.2
1.3.1
1.3.0
1.2.4
1.2.3
1.2.2
1.2.1
1.2.0
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.1.0-rc.1
1.1.0-rc.0
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.13.1
0.13.0
0.12.1
0.12.0
0.11.0
0.10.3
0.10.2
0.10.1
0.10.0
0.9.1
0.9.0
0.8.0
0.7.0
0.6.0
0.5.2
0.5.1
0.5.0
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
iOS (APNS), Android (FCM), and Amazon Android (ADM) push notifications for Elixir.
Current section
Files
Jump to
Current section
Files
lib/pigeon/apns/token.ex
defmodule Pigeon.APNS.Token do
@moduledoc false
import Joken.Config
alias Pigeon.APNS.JWTConfig
# seconds - 10 seconds short of one hour
@token_max_age 3_590
@type t :: {non_neg_integer(), binary() | nil}
@spec start_link((-> any())) :: Agent.on_start()
def start_link(_) do
Agent.start_link(fn -> %{} end, name: __MODULE__)
end
def child_spec(opts) do
%{
id: __MODULE__,
start: {__MODULE__, :start_link, [opts]},
type: :worker,
restart: :permanent,
shutdown: 5_000
}
end
@spec get(JWTConfig.t()) :: t
def get(%JWTConfig{} = config) do
token_storage_key =
config.key_identifier <> ":" <> config.team_id <> ":" <> config.uri
Agent.get_and_update(__MODULE__, fn map ->
{timestamp, saved_token} = Map.get(map, token_storage_key, {0, nil})
now = :os.system_time(:seconds)
age = now - timestamp
if age < @token_max_age do
{saved_token, map}
else
token = generate_apns_jwt(config)
{token, Map.put(map, token_storage_key, {now, token})}
end
end)
end
@spec generate_apns_jwt(JWTConfig.t()) :: binary
defp generate_apns_jwt(config) do
key = %{"pem" => config.key}
now = :os.system_time(:seconds)
signer =
Joken.Signer.create("ES256", key, %{"kid" => config.key_identifier})
{:ok, token, _claims} =
default_claims(iss: config.team_id, iat: now)
|> Joken.generate_and_sign(%{}, signer)
token
end
end