Provides security utilities for PhoenixGenApi.
Features
Admin gate — fail-closed authorization for dangerous runtime operations (toggling
detail_error, updating rate limit config, pushing configs).Push token validation — constant-time comparison to authenticate push requests from remote nodes.
MFA allowlist validation — restricts which
{module, function, args}tuples can be registered as function configurations, preventing a compromised node from registering dangerous MFAs (e.g.:os.cmd).
Configuration
All checks are opt-in and backward compatible. If the relevant application environment variables are not set, the checks are skipped:
config :phoenix_gen_api,
# Admin actions allowlist (fail-closed: default denies everything)
admin_actions: [:push_config],
# Push token — when set, push requests must include a matching token
push_token: "my-secret-token",
# MFA allowlist — when set, only listed {module, function} pairs are allowed.
# Module-level entries (just an atom) allow all functions in that module.
mfa_allowlist: [
MyApp.UserService,
{MyApp.OrderService, :create_order}
]Hardcoded Denylist
The following modules are always blocked unless explicitly allowed:
:os, :file, :code, :erlang, :net, :rpc, :global, :inet.
Environment Recommendations
- Development: You may enable all admin actions for convenience.
- Production: Enable only what's needed. Configure
push_tokenandmfa_allowlistto restrict push sources and allowed function targets.
Summary
Functions
Checks whether a given admin action is currently permitted.
Validates a push token using constant-time comparison.
Validates that an MFA tuple is allowed by the configured allowlist and not in the hardcoded denylist.
Types
Functions
@spec admin_action_allowed?(admin_action()) :: boolean()
Checks whether a given admin action is currently permitted.
Returns true if the action is in the configured allowlist, false otherwise.
When denied, a warning is logged.
Examples
iex> PhoenixGenApi.Security.admin_action_allowed?(:update_rate_limit_config)
false
iex> PhoenixGenApi.Security.admin_action_allowed?(:change_detail_error)
false
Validates a push token using constant-time comparison.
Returns true if:
- No
:push_tokenis configured (backward compatible — push allowed without token) - The provided token matches the configured token
Returns false if a token is configured but the provided token doesn't match
or is missing.
Uses constant-time comparison to prevent timing attacks.
Validates that an MFA tuple is allowed by the configured allowlist and not in the hardcoded denylist.
Parameters
mfa- A{module, function, args}tuple
Returns
:okif the MFA is allowed{:error, {:mfa_not_allowed, mfa}}if the MFA is not allowed
Behavior
- If no
:mfa_allowlistis configured, all MFAs pass the allowlist check (backward compatible) — but the hardcoded denylist is still enforced. - If
:mfa_allowlistIS configured, the{module, function}pair must match an entry. Entries can be:- A module atom (e.g.
MyApp.UserService) — allows all functions in that module - A
{module, function}tuple (e.g.{MyApp.OrderService, :create_order})
- A module atom (e.g.
- Modules in the hardcoded denylist (
:os,:file,:code,:erlang,:net,:rpc,:global,:inet) are ALWAYS blocked unless the allowlist explicitly includes them.