1 """Pluggable auth modules for Home Assistant."""
3 from __future__
import annotations
9 import voluptuous
as vol
10 from voluptuous.humanize
import humanize_error
12 from homeassistant
import data_entry_flow, requirements
21 MULTI_FACTOR_AUTH_MODULES: Registry[str, type[MultiFactorAuthModule]] =
Registry()
23 MULTI_FACTOR_AUTH_MODULE_SCHEMA = vol.Schema(
25 vol.Required(CONF_TYPE): str,
26 vol.Optional(CONF_NAME): str,
28 vol.Optional(CONF_ID): str,
30 extra=vol.ALLOW_EXTRA,
33 DATA_REQS: HassKey[set[str]] =
HassKey(
"mfa_auth_module_reqs_processed")
35 _LOGGER = logging.getLogger(__name__)
39 """Multi-factor Auth Module of validation function."""
41 DEFAULT_TITLE =
"Unnamed auth module"
44 def __init__(self, hass: HomeAssistant, config: dict[str, Any]) ->
None:
45 """Initialize an auth module."""
51 """Return id of the auth module.
53 Default is same as type
59 """Return type of the module."""
60 return self.
configconfig[CONF_TYPE]
64 """Return the name of the auth module."""
71 """Return a voluptuous schema to define mfa auth module's input."""
72 raise NotImplementedError
75 """Return a data entry flow handler for setup module.
77 Mfa module should extend SetupFlow
79 raise NotImplementedError
82 """Set up user for mfa auth module."""
83 raise NotImplementedError
86 """Remove user from mfa module."""
87 raise NotImplementedError
90 """Return whether user is setup."""
91 raise NotImplementedError
93 async
def async_validate(self, user_id: str, user_input: dict[str, Any]) -> bool:
94 """Return True if validation passed."""
95 raise NotImplementedError
99 """Handler for the setup flow."""
102 self, auth_module: MultiFactorAuthModule, setup_schema: vol.Schema, user_id: str
104 """Initialize the setup flow."""
110 self, user_input: dict[str, str] |
None =
None
112 """Handle the first step of setup flow.
114 Return self.async_show_form(step_id='init') if user_input is None.
115 Return self.async_create_entry(data={'result': result}) if finish.
117 errors: dict[str, str] = {}
120 result = await self.
_auth_module_auth_module.async_setup_user(self.
_user_id_user_id, user_input)
124 step_id=
"init", data_schema=self.
_setup_schema_setup_schema, errors=errors
129 hass: HomeAssistant, config: dict[str, Any]
130 ) -> MultiFactorAuthModule:
131 """Initialize an auth module from a config."""
132 module_name: str = config[CONF_TYPE]
136 config = module.CONFIG_SCHEMA(config)
137 except vol.Invalid
as err:
139 "Invalid configuration for multi-factor module %s: %s",
145 return MULTI_FACTOR_AUTH_MODULES[module_name](hass, config)
149 """Load an mfa auth module."""
150 module_path = f
"homeassistant.auth.mfa_modules.{module_name}"
154 except ImportError
as err:
155 _LOGGER.error(
"Unable to load mfa module %s: %s", module_name, err)
157 f
"Unable to load mfa module {module_name}: {err}"
160 if hass.config.skip_pip
or not hasattr(module,
"REQUIREMENTS"):
163 processed = hass.data.get(DATA_REQS)
164 if processed
and module_name
in processed:
167 processed = hass.data[DATA_REQS] = set()
169 await requirements.async_process_requirements(
170 hass, module_path, module.REQUIREMENTS
173 processed.add(module_name)
None async_depose_user(self, str user_id)
SetupFlow async_setup_flow(self, str user_id)
bool async_validate(self, str user_id, dict[str, Any] user_input)
None __init__(self, HomeAssistant hass, dict[str, Any] config)
bool async_is_user_setup(self, str user_id)
vol.Schema input_schema(self)
Any async_setup_user(self, str user_id, Any setup_data)
None __init__(self, MultiFactorAuthModule auth_module, vol.Schema setup_schema, str user_id)
FlowResult async_step_init(self, dict[str, str]|None user_input=None)
_FlowResultT async_show_form(self, *str|None step_id=None, vol.Schema|None data_schema=None, dict[str, str]|None errors=None, Mapping[str, str]|None description_placeholders=None, bool|None last_step=None, str|None preview=None)
_FlowResultT async_create_entry(self, *str|None title=None, Mapping[str, Any] data, str|None description=None, Mapping[str, str]|None description_placeholders=None)
types.ModuleType _load_mfa_module(HomeAssistant hass, str module_name)
MultiFactorAuthModule auth_mfa_module_from_config(HomeAssistant hass, dict[str, Any] config)
web.Response get(self, web.Request request, str config_key)
str humanize_error(HomeAssistant hass, vol.Invalid validation_error, str domain, dict config, str|None link, int max_sub_error_length=MAX_VALIDATION_ERROR_ITEM_LENGTH)
ModuleType async_import_module(HomeAssistant hass, str name)