Stores the OpenFeed signing key as a row in an Ash resource.
Multi-node safe, because every node reads the same row. This is the default the installer picks, for that reason.
The resource
mix ash_openfeed.install generates one. By hand it is:
defmodule MyApp.OpenFeed.Key do
use Ash.Resource,
domain: MyApp.OpenFeed,
data_layer: AshPostgres.DataLayer
postgres do
table "openfeed_keys"
repo MyApp.Repo
end
actions do
defaults [:read, :destroy, create: :*, update: :*]
end
attributes do
uuid_primary_key :id
attribute :name, :string, allow_nil?: false, default: "default"
attribute :jwk, :string, allow_nil?: false, sensitive?: true
timestamps()
end
identities do
identity :unique_name, [:name]
end
endConfigure it
openfeed do
key_store {AshOpenFeed.KeyStore.Ash, resource: MyApp.OpenFeed.Key}
endOptions
:resource(required) — the Ash resource holding keys.:name— which key row. Defaults to"default". Use distinct names to hold a key per tenant.:tenant,:actor,:authorize?— passed toAsh.read/2.:cache— seeOpenFeed.KeyStore. Defaults totrue, which matters here because otherwise every DPoP proof is a database round trip.
Encrypt it
A private key in a database table deserves encryption more than the tokens do,
because it is the thing that makes a stolen token useless. sensitive? keeps
it out of inspect output but does not encrypt it:
use Ash.Resource, extensions: [AshCloak.Resource]
cloak do
vault MyApp.Vault
attributes [:jwk]
endIf your vault key and your database live in the same blast radius, consider
OpenFeed.KeyStore.Env instead, so the signing key is not recoverable from a
database backup alone.