Current section
Files
Jump to
Current section
Files
lib/utils/cookie.ex
defmodule ExDjango.Utils.Cookie do
alias ExDjango.Utils.Baseconv
alias ExDjango.Utils.Signing
alias ExDjango.Utils.Zlib
alias ExDjango.Session
def get_session(cookie, secret_key, max_age, salt) do
case verify(cookie, secret_key, max_age, salt) do
{:ok, data} -> data |> Session.decode()
{:error, _} -> %{}
end
end
def verify(session_id, secret_key, max_age) do
verify(session_id, secret_key, max_age, Signing.default_salt())
end
def verify(session_id, secret_key, max_age, salt) do
case String.split(session_id, ":") do
[payload, timestamp, signature] ->
case Signing.base64_hmac(salt, secret_key, payload <> ":" <> timestamp) do
x when x == signature ->
case verify_timestamp(timestamp, max_age) do
:error -> {:error, "Session Expired"}
:ok -> {:ok, decode_payload(payload)}
end
_ -> {:error, "Invalid Signature"}
end
_ -> {:error, "Invalid Cookie"}
end
end
def create(payload, secret_key), do: create(payload, secret_key, Signing.default_salt())
def create(payload, secret_key, salt) do
first_part = create_data(payload) <> ":" <> create_timestamp()
signature = Signing.base64_hmac(salt, secret_key, first_part)
first_part <> ":" <> signature
end
def create_data(payload) do
data = payload |> Zlib.compress() |> Signing.b64_encode()
".#{data}"
end
def create_timestamp() do
secs = :erlang.system_time(:seconds)
Baseconv.encode(:base62, secs)
end
def verify_timestamp(timestamp, max_age) do
result = :ok
if max_age != nil do
min_secs = :erlang.system_time(:seconds) - max_age
secs = Baseconv.decode(:base62, timestamp)
if secs < min_secs, do: result = :error
end
result
end
def decode_payload(payload) do
if String.starts_with?(payload, ".") do
{_, payload} = String.split_at(payload, 1)
Signing.b64_decode(payload) |> Zlib.decompress()
else
Signing.b64_decode(payload)
end
end
end