Skip to content

Instantly share code, notes, and snippets.

@coryodaniel
Created August 23, 2021 18:40
Show Gist options
  • Save coryodaniel/a162ebf27bf06665eba3ef3cd73d94a9 to your computer and use it in GitHub Desktop.
Save coryodaniel/a162ebf27bf06665eba3ef3cd73d94a9 to your computer and use it in GitHub Desktop.
Kratos Sessions whoami client for elixir
defmodule Kratos do
defmodule Behaviour do
@moduledoc """
Defines function signature for secrets adapters
"""
@callback who_am_i(String.t()) :: {:ok, map()} | {:error, :unauthenticated}
end
@behaviour Kratos.Behaviour
def config(), do: Application.get_env(:massdriver, Kratos)
def adapter(), do: Keyword.get(config(), :adapter)
def url(), do: Keyword.get(config(), :url)
def who_am_i(cookie), do: adapter().who_am_i(cookie)
defmodule HTTPAdapter do
@behaviour Kratos.Behaviour
def who_am_i(cookie) do
headers = [{"Cookie", cookie}]
result = HTTPoison.get(Kratos.url(), headers, [])
with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <- result,
{:ok, session} <- Jason.decode(body) do
{:ok, session}
else
{:error, %HTTPoison.Error{}} ->
{:error, :unauthenticated}
{:error, %Jason.DecodeError{}} ->
{:error, :unauthenticated}
_no_active_session ->
{:error, :unauthenticated}
end
end
end
defmodule MockAdapter do
@behaviour Kratos.Behaviour
def start_link() do
Agent.start_link(fn -> %{} end, name: __MODULE__)
end
def build_session(email) do
now = DateTime.utc_now()
expires_at = DateTime.add(now, 30 * 60, :second)
%{
"id" => Ecto.UUID.generate(),
"active" => true,
"expires_at" => DateTime.to_iso8601(expires_at),
"authenticated_at" => DateTime.to_iso8601(now),
"issued_at" => DateTime.to_iso8601(now),
"identity" => %{
"id" => Ecto.UUID.generate(),
"schema_id" => "default",
"schema_url" => "http://127.0.0.1:4433/schemas/default",
"state" => "active",
"state_changed_at" => DateTime.to_iso8601(now),
"traits" => %{
"email" => email,
"name" => %{}
},
"created_at" => DateTime.to_iso8601(now),
"updated_at" => DateTime.to_iso8601(now)
},
"verifiable_addresses" => [
%{
"id" => "e5ed11bf-43d3-483e-be9c-5f9a9c46c0b3",
"value" => "cory@coryodaniel.com",
"verified" => false,
"via" => "email",
"status" => "sent",
"verified_at" => nil,
"created_at" => "2021-08-17T05:54:59.867799Z",
"updated_at" => "2021-08-17T05:54:59.867799Z"
}
]
}
end
@doc """
Inserts a session into the Agent store.
## Examples
Given an email, a session map will be generated an inserted
Kratos.MockAdapter.insert_session("session_cookie=foo", "bar@example.com")
Otherwise a map from `build_session/1` is expected
session = Kratos.MockAdapter.build_session("bar@example.com")
# modify session as desired
Kratos.MockAdapter.insert_session("session_cookie=foo", session)
"""
def insert_session(cookie, email) when is_binary(email) do
session = build_session(email)
insert_session(cookie, session)
end
def insert_session(cookie, session = %{}) do
Agent.update(__MODULE__, fn map -> Map.put(map, cookie, session) end)
end
def who_am_i(cookie) do
session = Agent.get(__MODULE__, fn map -> Map.get(map, cookie) end)
case session do
nil ->
{:error, :unauthenticated}
session ->
{:ok, session}
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment