An Ash extension for resources that store dynamic OIDC connection
configuration — used by AshAuthentication.Strategy.DynamicOidc to look up
the OIDC client config at request time instead of pinning it at compile time.
This is the resource layer for the data-driven SSO pattern: each row is one customer's OIDC client configuration (base_url, client_id, client_secret, plus optional display name/icon for UI). At sign-in time the strategy queries the resource — typically scoped by the current Ash tenant — and builds an ephemeral OAuth2 strategy from the matched row.
Usage
defmodule MyApp.Accounts.OidcConnection do
use Ash.Resource,
data_layer: AshPostgres.DataLayer,
extensions: [AshAuthentication.OidcConnection],
domain: MyApp.Accounts
oidc_connection do
# All defaults shown — override only what you need.
base_url_field :base_url
client_id_field :client_id
client_secret_field :client_secret
display_name_field :display_name
icon_url_field :icon_url
end
postgres do
table "oidc_connections"
repo MyApp.Repo
end
endThe extension generates default attributes (string columns for
base_url, client_id, client_secret, display_name, icon_url) and a
default :read action. You're free to:
- Replace any field with an Ash calculation (e.g. one that decrypts the client_secret on load) and point the field config at it.
- Add multitenancy, custom attributes, additional actions, and authorization policies as you see fit.
Authorization
If you enable Ash.Policy.Authorizer on this resource, you must allow the
framework to read connections during the OIDC flow. The simplest way is a
bypass:
policies do
bypass AshAuthentication.Checks.AshAuthenticationInteraction do
authorize_if always()
end
# ... your own policies for admin UI write operations
endSecret storage
Storing client_secret as a plaintext string is convenient but dangerous if
the database is compromised. Encrypt it at rest with ash_cloak (or
cloak_ecto), and point client_secret_field at a calculation that
decrypts on load.
Multitenancy
This extension does not require multitenancy. If your resource is multitenant, the strategy will scope connection lookups by the current Ash tenant automatically. If it isn't, the strategy will look up connections globally — useful for single-tenant deployments with multiple IdPs.