Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """Provide an authentication layer for Home Assistant."""
2 
3 from __future__ import annotations
4 
5 import asyncio
6 from collections import OrderedDict
7 from collections.abc import Mapping
8 from datetime import datetime, timedelta
9 from functools import partial
10 import time
11 from typing import Any, cast
12 
13 import jwt
14 
15 from homeassistant.core import (
16  CALLBACK_TYPE,
17  HassJob,
18  HassJobType,
19  HomeAssistant,
20  callback,
21 )
22 from homeassistant.data_entry_flow import FlowHandler, FlowManager, FlowResultType
23 from homeassistant.helpers.event import async_track_point_in_utc_time
24 from homeassistant.util import dt as dt_util
25 
26 from . import auth_store, jwt_wrapper, models
27 from .const import ACCESS_TOKEN_EXPIRATION, GROUP_ID_ADMIN, REFRESH_TOKEN_EXPIRATION
28 from .mfa_modules import MultiFactorAuthModule, auth_mfa_module_from_config
29 from .models import AuthFlowContext, AuthFlowResult
30 from .providers import AuthProvider, LoginFlow, auth_provider_from_config
31 from .providers.homeassistant import HassAuthProvider
32 
33 EVENT_USER_ADDED = "user_added"
34 EVENT_USER_UPDATED = "user_updated"
35 EVENT_USER_REMOVED = "user_removed"
36 
37 type _MfaModuleDict = dict[str, MultiFactorAuthModule]
38 type _ProviderKey = tuple[str, str | None]
39 type _ProviderDict = dict[_ProviderKey, AuthProvider]
40 
41 
42 class InvalidAuthError(Exception):
43  """Raised when a authentication error occurs."""
44 
45 
46 class InvalidProvider(Exception):
47  """Authentication provider not found."""
48 
49 
51  hass: HomeAssistant,
52  provider_configs: list[dict[str, Any]],
53  module_configs: list[dict[str, Any]],
54 ) -> AuthManager:
55  """Initialize an auth manager from config.
56 
57  CORE_CONFIG_SCHEMA will make sure no duplicated auth providers or
58  mfa modules exist in configs.
59  """
60  store = auth_store.AuthStore(hass)
61  await store.async_load()
62  if provider_configs:
63  providers = await asyncio.gather(
64  *(
65  auth_provider_from_config(hass, store, config)
66  for config in provider_configs
67  )
68  )
69  else:
70  providers = []
71  # So returned auth providers are in same order as config
72  provider_hash: _ProviderDict = OrderedDict()
73  for provider in providers:
74  key = (provider.type, provider.id)
75  provider_hash[key] = provider
76 
77  if isinstance(provider, HassAuthProvider):
78  # Can be removed in 2026.7 with the legacy mode of homeassistant auth provider
79  # We need to initialize the provider to create the repair if needed as otherwise
80  # the provider will be initialized on first use, which could be rare as users
81  # don't frequently change auth settings
82  await provider.async_initialize()
83 
84  if module_configs:
85  modules = await asyncio.gather(
86  *(auth_mfa_module_from_config(hass, config) for config in module_configs)
87  )
88  else:
89  modules = []
90  # So returned auth modules are in same order as config
91  module_hash: _MfaModuleDict = OrderedDict()
92  for module in modules:
93  module_hash[module.id] = module
94 
95  manager = AuthManager(hass, store, provider_hash, module_hash)
96  await manager.async_setup()
97  return manager
98 
99 
101  FlowManager[AuthFlowContext, AuthFlowResult, tuple[str, str]]
102 ):
103  """Manage authentication flows."""
104 
105  _flow_result = AuthFlowResult
106 
107  def __init__(self, hass: HomeAssistant, auth_manager: AuthManager) -> None:
108  """Init auth manager flows."""
109  super().__init__(hass)
110  self.auth_managerauth_manager = auth_manager
111 
112  async def async_create_flow(
113  self,
114  handler_key: tuple[str, str],
115  *,
116  context: AuthFlowContext | None = None,
117  data: dict[str, Any] | None = None,
118  ) -> LoginFlow:
119  """Create a login flow."""
120  auth_provider = self.auth_managerauth_manager.get_auth_provider(*handler_key)
121  if not auth_provider:
122  raise KeyError(f"Unknown auth provider {handler_key}")
123  return await auth_provider.async_login_flow(context)
124 
125  async def async_finish_flow(
126  self,
127  flow: FlowHandler[AuthFlowContext, AuthFlowResult, tuple[str, str]],
128  result: AuthFlowResult,
129  ) -> AuthFlowResult:
130  """Return a user as result of login flow.
131 
132  This method is called when a flow step returns FlowResultType.ABORT or
133  FlowResultType.CREATE_ENTRY.
134  """
135  flow = cast(LoginFlow, flow)
136 
137  if result["type"] != FlowResultType.CREATE_ENTRY:
138  return result
139 
140  # we got final result
141  if isinstance(result["data"], models.Credentials):
142  result["result"] = result["data"]
143  return result
144 
145  auth_provider = self.auth_managerauth_manager.get_auth_provider(*result["handler"])
146  if not auth_provider:
147  raise KeyError(f"Unknown auth provider {result['handler']}")
148 
149  credentials = await auth_provider.async_get_or_create_credentials(
150  cast(Mapping[str, str], result["data"]),
151  )
152 
153  if flow.context.get("credential_only"):
154  result["result"] = credentials
155  return result
156 
157  # multi-factor module cannot enabled for new credential
158  # which has not linked to a user yet
159  if auth_provider.support_mfa and not credentials.is_new:
160  user = await self.auth_managerauth_manager.async_get_user_by_credentials(credentials)
161  if user is not None:
162  modules = await self.auth_managerauth_manager.async_get_enabled_mfa(user)
163 
164  if modules:
165  flow.credential = credentials
166  flow.user = user
167  flow.available_mfa_modules = modules
168  return await flow.async_step_select_mfa_module()
169 
170  result["result"] = credentials
171  return result
172 
173 
175  """Manage the authentication for Home Assistant."""
176 
177  def __init__(
178  self,
179  hass: HomeAssistant,
180  store: auth_store.AuthStore,
181  providers: _ProviderDict,
182  mfa_modules: _MfaModuleDict,
183  ) -> None:
184  """Initialize the auth manager."""
185  self.hasshass = hass
186  self._store_store = store
187  self._providers_providers = providers
188  self._mfa_modules_mfa_modules = mfa_modules
189  self.login_flowlogin_flow = AuthManagerFlowManager(hass, self)
190  self._revoke_callbacks: dict[str, set[CALLBACK_TYPE]] = {}
191  self._expire_callback_expire_callback: CALLBACK_TYPE | None = None
192  self._remove_expired_job_remove_expired_job = HassJob(
193  self._async_remove_expired_refresh_tokens_async_remove_expired_refresh_tokens, job_type=HassJobType.Callback
194  )
195 
196  async def async_setup(self) -> None:
197  """Set up the auth manager."""
198  hass = self.hasshass
199  hass.async_add_shutdown_job(
200  HassJob(
201  self._async_cancel_expiration_schedule_async_cancel_expiration_schedule, job_type=HassJobType.Callback
202  )
203  )
204  self._async_track_next_refresh_token_expiration_async_track_next_refresh_token_expiration()
205 
206  @property
207  def auth_providers(self) -> list[AuthProvider]:
208  """Return a list of available auth providers."""
209  return list(self._providers_providers.values())
210 
211  @property
212  def auth_mfa_modules(self) -> list[MultiFactorAuthModule]:
213  """Return a list of available auth modules."""
214  return list(self._mfa_modules_mfa_modules.values())
215 
217  self, provider_type: str, provider_id: str | None
218  ) -> AuthProvider | None:
219  """Return an auth provider, None if not found."""
220  return self._providers_providers.get((provider_type, provider_id))
221 
222  def get_auth_providers(self, provider_type: str) -> list[AuthProvider]:
223  """Return a List of auth provider of one type, Empty if not found."""
224  return [
225  provider
226  for (p_type, _), provider in self._providers_providers.items()
227  if p_type == provider_type
228  ]
229 
230  def get_auth_mfa_module(self, module_id: str) -> MultiFactorAuthModule | None:
231  """Return a multi-factor auth module, None if not found."""
232  return self._mfa_modules_mfa_modules.get(module_id)
233 
234  async def async_get_users(self) -> list[models.User]:
235  """Retrieve all users."""
236  return await self._store_store.async_get_users()
237 
238  async def async_get_user(self, user_id: str) -> models.User | None:
239  """Retrieve a user."""
240  return await self._store_store.async_get_user(user_id)
241 
242  async def async_get_owner(self) -> models.User | None:
243  """Retrieve the owner."""
244  users = await self.async_get_usersasync_get_users()
245  return next((user for user in users if user.is_owner), None)
246 
247  async def async_get_group(self, group_id: str) -> models.Group | None:
248  """Retrieve all groups."""
249  return await self._store_store.async_get_group(group_id)
250 
252  self, credentials: models.Credentials
253  ) -> models.User | None:
254  """Get a user by credential, return None if not found."""
255  for user in await self.async_get_usersasync_get_users():
256  for creds in user.credentials:
257  if creds.id == credentials.id:
258  return user
259 
260  return None
261 
263  self,
264  name: str,
265  *,
266  group_ids: list[str] | None = None,
267  local_only: bool | None = None,
268  ) -> models.User:
269  """Create a system user."""
270  user = await self._store_store.async_create_user(
271  name=name,
272  system_generated=True,
273  is_active=True,
274  group_ids=group_ids or [],
275  local_only=local_only,
276  )
277 
278  self.hasshass.bus.async_fire(EVENT_USER_ADDED, {"user_id": user.id})
279 
280  return user
281 
282  async def async_create_user(
283  self,
284  name: str,
285  *,
286  group_ids: list[str] | None = None,
287  local_only: bool | None = None,
288  ) -> models.User:
289  """Create a user."""
290  kwargs: dict[str, Any] = {
291  "name": name,
292  "is_active": True,
293  "group_ids": group_ids or [],
294  "local_only": local_only,
295  }
296 
297  if await self._user_should_be_owner_user_should_be_owner():
298  kwargs["is_owner"] = True
299 
300  user = await self._store_store.async_create_user(**kwargs)
301 
302  self.hasshass.bus.async_fire(EVENT_USER_ADDED, {"user_id": user.id})
303 
304  return user
305 
307  self, credentials: models.Credentials
308  ) -> models.User:
309  """Get or create a user."""
310  if not credentials.is_new:
311  user = await self.async_get_user_by_credentialsasync_get_user_by_credentials(credentials)
312  if user is None:
313  raise ValueError("Unable to find the user.")
314  return user
315 
316  auth_provider = self._async_get_auth_provider_async_get_auth_provider(credentials)
317 
318  if auth_provider is None:
319  raise RuntimeError("Credential with unknown provider encountered")
320 
321  info = await auth_provider.async_user_meta_for_credentials(credentials)
322 
323  user = await self._store_store.async_create_user(
324  credentials=credentials,
325  name=info.name,
326  is_active=info.is_active,
327  group_ids=[GROUP_ID_ADMIN if info.group is None else info.group],
328  local_only=info.local_only,
329  )
330 
331  self.hasshass.bus.async_fire(EVENT_USER_ADDED, {"user_id": user.id})
332 
333  return user
334 
335  async def async_link_user(
336  self, user: models.User, credentials: models.Credentials
337  ) -> None:
338  """Link credentials to an existing user."""
339  linked_user = await self.async_get_user_by_credentialsasync_get_user_by_credentials(credentials)
340  if linked_user == user:
341  return
342  if linked_user is not None:
343  raise ValueError("Credential is already linked to a user")
344 
345  await self._store_store.async_link_user(user, credentials)
346 
347  async def async_remove_user(self, user: models.User) -> None:
348  """Remove a user."""
349  tasks = [
350  self.async_remove_credentialsasync_remove_credentials(credentials)
351  for credentials in user.credentials
352  ]
353 
354  if tasks:
355  await asyncio.gather(*tasks)
356 
357  await self._store_store.async_remove_user(user)
358 
359  self.hasshass.bus.async_fire(EVENT_USER_REMOVED, {"user_id": user.id})
360 
361  async def async_update_user(
362  self,
363  user: models.User,
364  name: str | None = None,
365  is_active: bool | None = None,
366  group_ids: list[str] | None = None,
367  local_only: bool | None = None,
368  ) -> None:
369  """Update a user."""
370  kwargs: dict[str, Any] = {
371  attr_name: value
372  for attr_name, value in (
373  ("name", name),
374  ("group_ids", group_ids),
375  ("local_only", local_only),
376  )
377  if value is not None
378  }
379  await self._store_store.async_update_user(user, **kwargs)
380 
381  if is_active is not None:
382  if is_active is True:
383  await self.async_activate_userasync_activate_user(user)
384  else:
385  await self.async_deactivate_userasync_deactivate_user(user)
386 
387  self.hasshass.bus.async_fire(EVENT_USER_UPDATED, {"user_id": user.id})
388 
389  @callback
391  self, credentials: models.Credentials, data: dict[str, Any]
392  ) -> None:
393  """Update credentials data."""
394  self._store_store.async_update_user_credentials_data(credentials, data=data)
395 
396  async def async_activate_user(self, user: models.User) -> None:
397  """Activate a user."""
398  await self._store_store.async_activate_user(user)
399 
400  async def async_deactivate_user(self, user: models.User) -> None:
401  """Deactivate a user."""
402  if user.is_owner:
403  raise ValueError("Unable to deactivate the owner")
404  await self._store_store.async_deactivate_user(user)
405 
406  async def async_remove_credentials(self, credentials: models.Credentials) -> None:
407  """Remove credentials."""
408  provider = self._async_get_auth_provider_async_get_auth_provider(credentials)
409 
410  if provider is not None and hasattr(provider, "async_will_remove_credentials"):
411  await provider.async_will_remove_credentials(credentials)
412 
413  await self._store_store.async_remove_credentials(credentials)
414 
416  self, user: models.User, mfa_module_id: str, data: Any
417  ) -> None:
418  """Enable a multi-factor auth module for user."""
419  if user.system_generated:
420  raise ValueError(
421  "System generated users cannot enable multi-factor auth module."
422  )
423 
424  if (module := self.get_auth_mfa_moduleget_auth_mfa_module(mfa_module_id)) is None:
425  raise ValueError(f"Unable find multi-factor auth module: {mfa_module_id}")
426 
427  await module.async_setup_user(user.id, data)
428 
430  self, user: models.User, mfa_module_id: str
431  ) -> None:
432  """Disable a multi-factor auth module for user."""
433  if user.system_generated:
434  raise ValueError(
435  "System generated users cannot disable multi-factor auth module."
436  )
437 
438  if (module := self.get_auth_mfa_moduleget_auth_mfa_module(mfa_module_id)) is None:
439  raise ValueError(f"Unable find multi-factor auth module: {mfa_module_id}")
440 
441  await module.async_depose_user(user.id)
442 
443  async def async_get_enabled_mfa(self, user: models.User) -> dict[str, str]:
444  """List enabled mfa modules for user."""
445  modules: dict[str, str] = OrderedDict()
446  for module_id, module in self._mfa_modules_mfa_modules.items():
447  if await module.async_is_user_setup(user.id):
448  modules[module_id] = module.name
449  return modules
450 
452  self,
453  user: models.User,
454  client_id: str | None = None,
455  client_name: str | None = None,
456  client_icon: str | None = None,
457  token_type: str | None = None,
458  access_token_expiration: timedelta = ACCESS_TOKEN_EXPIRATION,
459  credential: models.Credentials | None = None,
460  ) -> models.RefreshToken:
461  """Create a new refresh token for a user."""
462  if not user.is_active:
463  raise ValueError("User is not active")
464 
465  if user.system_generated and client_id is not None:
466  raise ValueError(
467  "System generated users cannot have refresh tokens connected "
468  "to a client."
469  )
470 
471  if token_type is None:
472  if user.system_generated:
473  token_type = models.TOKEN_TYPE_SYSTEM
474  else:
475  token_type = models.TOKEN_TYPE_NORMAL
476 
477  if token_type is models.TOKEN_TYPE_NORMAL:
478  expire_at = time.time() + REFRESH_TOKEN_EXPIRATION
479  else:
480  expire_at = None
481 
482  if user.system_generated != (token_type == models.TOKEN_TYPE_SYSTEM):
483  raise ValueError(
484  "System generated users can only have system type refresh tokens"
485  )
486 
487  if token_type == models.TOKEN_TYPE_NORMAL and client_id is None:
488  raise ValueError("Client is required to generate a refresh token.")
489 
490  if (
491  token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN
492  and client_name is None
493  ):
494  raise ValueError("Client_name is required for long-lived access token")
495 
496  if token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN:
497  for token in user.refresh_tokens.values():
498  if (
499  token.client_name == client_name
500  and token.token_type == models.TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN
501  ):
502  # Each client_name can only have one
503  # long_lived_access_token type of refresh token
504  raise ValueError(f"{client_name} already exists")
505 
506  return await self._store_store.async_create_refresh_token(
507  user,
508  client_id,
509  client_name,
510  client_icon,
511  token_type,
512  access_token_expiration,
513  expire_at,
514  credential,
515  )
516 
517  @callback
518  def async_get_refresh_token(self, token_id: str) -> models.RefreshToken | None:
519  """Get refresh token by id."""
520  return self._store_store.async_get_refresh_token(token_id)
521 
522  @callback
524  self, token: str
525  ) -> models.RefreshToken | None:
526  """Get refresh token by token."""
527  return self._store_store.async_get_refresh_token_by_token(token)
528 
529  @callback
530  def async_remove_refresh_token(self, refresh_token: models.RefreshToken) -> None:
531  """Delete a refresh token."""
532  self._store_store.async_remove_refresh_token(refresh_token)
533 
534  callbacks = self._revoke_callbacks.pop(refresh_token.id, ())
535  for revoke_callback in callbacks:
536  revoke_callback()
537 
538  @callback
540  self, refresh_token: models.RefreshToken, *, enable_expiry: bool
541  ) -> None:
542  """Enable or disable expiry of a refresh token."""
543  self._store_store.async_set_expiry(refresh_token, enable_expiry=enable_expiry)
544 
545  @callback
546  def _async_remove_expired_refresh_tokens(self, _: datetime | None = None) -> None:
547  """Remove expired refresh tokens."""
548  now = time.time()
549  for token in self._store_store.async_get_refresh_tokens():
550  if (expire_at := token.expire_at) is not None and expire_at <= now:
551  self.async_remove_refresh_tokenasync_remove_refresh_token(token)
552  self._async_track_next_refresh_token_expiration_async_track_next_refresh_token_expiration()
553 
554  @callback
556  """Initialise all token expiration scheduled tasks."""
557  next_expiration = time.time() + REFRESH_TOKEN_EXPIRATION
558  for token in self._store_store.async_get_refresh_tokens():
559  if (
560  expire_at := token.expire_at
561  ) is not None and expire_at < next_expiration:
562  next_expiration = expire_at
563 
565  self.hasshass,
566  self._remove_expired_job_remove_expired_job,
567  dt_util.utc_from_timestamp(next_expiration),
568  )
569 
570  @callback
572  """Cancel tracking of expired refresh tokens."""
573  if self._expire_callback_expire_callback:
574  self._expire_callback_expire_callback()
575  self._expire_callback_expire_callback = None
576 
577  @callback
579  self, callbacks: set[CALLBACK_TYPE], callback_: CALLBACK_TYPE
580  ) -> None:
581  """Unregister a callback."""
582  callbacks.remove(callback_)
583 
584  @callback
586  self, refresh_token_id: str, revoke_callback: CALLBACK_TYPE
587  ) -> CALLBACK_TYPE:
588  """Register a callback to be called when the refresh token id is revoked."""
589  if refresh_token_id not in self._revoke_callbacks:
590  self._revoke_callbacks[refresh_token_id] = set()
591 
592  callbacks = self._revoke_callbacks[refresh_token_id]
593  callbacks.add(revoke_callback)
594  return partial(self._async_unregister_async_unregister, callbacks, revoke_callback)
595 
596  @callback
598  self, refresh_token: models.RefreshToken, remote_ip: str | None = None
599  ) -> str:
600  """Create a new access token."""
601  self.async_validate_refresh_tokenasync_validate_refresh_token(refresh_token, remote_ip)
602 
603  self._store_store.async_log_refresh_token_usage(refresh_token, remote_ip)
604 
605  now = int(time.time())
606  expire_seconds = int(refresh_token.access_token_expiration.total_seconds())
607  return jwt.encode(
608  {
609  "iss": refresh_token.id,
610  "iat": now,
611  "exp": now + expire_seconds,
612  },
613  refresh_token.jwt_key,
614  algorithm="HS256",
615  )
616 
617  @callback
619  self, refresh_token: models.RefreshToken
620  ) -> AuthProvider | None:
621  """Get the auth provider for the given refresh token.
622 
623  Raises an exception if the expected provider is no longer available or return
624  None if no provider was expected for this refresh token.
625  """
626  if refresh_token.credential is None:
627  return None
628 
629  provider = self.get_auth_providerget_auth_provider(
630  refresh_token.credential.auth_provider_type,
631  refresh_token.credential.auth_provider_id,
632  )
633  if provider is None:
634  raise InvalidProvider(
635  f"Auth provider {refresh_token.credential.auth_provider_type},"
636  f" {refresh_token.credential.auth_provider_id} not available"
637  )
638  return provider
639 
640  @callback
642  self, refresh_token: models.RefreshToken, remote_ip: str | None = None
643  ) -> None:
644  """Validate that a refresh token is usable.
645 
646  Will raise InvalidAuthError on errors.
647  """
648  if provider := self._async_resolve_provider_async_resolve_provider(refresh_token):
649  provider.async_validate_refresh_token(refresh_token, remote_ip)
650 
651  @callback
652  def async_validate_access_token(self, token: str) -> models.RefreshToken | None:
653  """Return refresh token if an access token is valid."""
654  try:
655  unverif_claims = jwt_wrapper.unverified_hs256_token_decode(token)
656  except jwt.InvalidTokenError:
657  return None
658 
659  refresh_token = self.async_get_refresh_tokenasync_get_refresh_token(
660  cast(str, unverif_claims.get("iss"))
661  )
662 
663  if refresh_token is None:
664  jwt_key = ""
665  issuer = ""
666  else:
667  jwt_key = refresh_token.jwt_key
668  issuer = refresh_token.id
669 
670  try:
671  jwt_wrapper.verify_and_decode(
672  token, jwt_key, leeway=10, issuer=issuer, algorithms=["HS256"]
673  )
674  except jwt.InvalidTokenError:
675  return None
676 
677  if refresh_token is None or not refresh_token.user.is_active:
678  return None
679 
680  return refresh_token
681 
682  @callback
684  self, credentials: models.Credentials
685  ) -> AuthProvider | None:
686  """Get auth provider from a set of credentials."""
687  auth_provider_key = (
688  credentials.auth_provider_type,
689  credentials.auth_provider_id,
690  )
691  return self._providers_providers.get(auth_provider_key)
692 
693  async def _user_should_be_owner(self) -> bool:
694  """Determine if user should be owner.
695 
696  A user should be an owner if it is the first non-system user that is
697  being created.
698  """
699  for user in await self._store_store.async_get_users():
700  if not user.system_generated:
701  return False
702 
703  return True
AuthFlowResult async_finish_flow(self, FlowHandler[AuthFlowContext, AuthFlowResult, tuple[str, str]] flow, AuthFlowResult result)
Definition: __init__.py:129
LoginFlow async_create_flow(self, tuple[str, str] handler_key, *AuthFlowContext|None context=None, dict[str, Any]|None data=None)
Definition: __init__.py:118
None __init__(self, HomeAssistant hass, AuthManager auth_manager)
Definition: __init__.py:107
models.RefreshToken|None async_get_refresh_token(self, str token_id)
Definition: __init__.py:518
None async_set_expiry(self, models.RefreshToken refresh_token, *bool enable_expiry)
Definition: __init__.py:541
None async_update_user_credentials_data(self, models.Credentials credentials, dict[str, Any] data)
Definition: __init__.py:392
None _async_unregister(self, set[CALLBACK_TYPE] callbacks, CALLBACK_TYPE callback_)
Definition: __init__.py:580
AuthProvider|None get_auth_provider(self, str provider_type, str|None provider_id)
Definition: __init__.py:218
models.RefreshToken|None async_validate_access_token(self, str token)
Definition: __init__.py:652
str async_create_access_token(self, models.RefreshToken refresh_token, str|None remote_ip=None)
Definition: __init__.py:599
models.User async_get_or_create_user(self, models.Credentials credentials)
Definition: __init__.py:308
None async_remove_user(self, models.User user)
Definition: __init__.py:347
models.RefreshToken|None async_get_refresh_token_by_token(self, str token)
Definition: __init__.py:525
None async_enable_user_mfa(self, models.User user, str mfa_module_id, Any data)
Definition: __init__.py:417
None async_remove_refresh_token(self, models.RefreshToken refresh_token)
Definition: __init__.py:530
AuthProvider|None _async_resolve_provider(self, models.RefreshToken refresh_token)
Definition: __init__.py:620
None _async_track_next_refresh_token_expiration(self)
Definition: __init__.py:555
None async_link_user(self, models.User user, models.Credentials credentials)
Definition: __init__.py:337
models.User|None async_get_user_by_credentials(self, models.Credentials credentials)
Definition: __init__.py:253
None async_validate_refresh_token(self, models.RefreshToken refresh_token, str|None remote_ip=None)
Definition: __init__.py:643
AuthProvider|None _async_get_auth_provider(self, models.Credentials credentials)
Definition: __init__.py:685
MultiFactorAuthModule|None get_auth_mfa_module(self, str module_id)
Definition: __init__.py:230
None async_disable_user_mfa(self, models.User user, str mfa_module_id)
Definition: __init__.py:431
None _async_remove_expired_refresh_tokens(self, datetime|None _=None)
Definition: __init__.py:546
dict[str, str] async_get_enabled_mfa(self, models.User user)
Definition: __init__.py:443
models.User|None async_get_owner(self)
Definition: __init__.py:242
None _async_cancel_expiration_schedule(self)
Definition: __init__.py:571
None async_activate_user(self, models.User user)
Definition: __init__.py:396
list[AuthProvider] get_auth_providers(self, str provider_type)
Definition: __init__.py:222
models.Group|None async_get_group(self, str group_id)
Definition: __init__.py:247
models.User async_create_system_user(self, str name, *list[str]|None group_ids=None, bool|None local_only=None)
Definition: __init__.py:268
None async_deactivate_user(self, models.User user)
Definition: __init__.py:400
None __init__(self, HomeAssistant hass, auth_store.AuthStore store, _ProviderDict providers, _MfaModuleDict mfa_modules)
Definition: __init__.py:183
models.User|None async_get_user(self, str user_id)
Definition: __init__.py:238
models.RefreshToken async_create_refresh_token(self, models.User user, str|None client_id=None, str|None client_name=None, str|None client_icon=None, str|None token_type=None, timedelta access_token_expiration=ACCESS_TOKEN_EXPIRATION, models.Credentials|None credential=None)
Definition: __init__.py:460
list[models.User] async_get_users(self)
Definition: __init__.py:234
None async_update_user(self, models.User user, str|None name=None, bool|None is_active=None, list[str]|None group_ids=None, bool|None local_only=None)
Definition: __init__.py:368
models.User async_create_user(self, str name, *list[str]|None group_ids=None, bool|None local_only=None)
Definition: __init__.py:288
list[MultiFactorAuthModule] auth_mfa_modules(self)
Definition: __init__.py:212
CALLBACK_TYPE async_register_revoke_token_callback(self, str refresh_token_id, CALLBACK_TYPE revoke_callback)
Definition: __init__.py:587
list[AuthProvider] auth_providers(self)
Definition: __init__.py:207
None async_remove_credentials(self, models.Credentials credentials)
Definition: __init__.py:406
MultiFactorAuthModule auth_mfa_module_from_config(HomeAssistant hass, dict[str, Any] config)
Definition: __init__.py:130
AuthProvider auth_provider_from_config(HomeAssistant hass, AuthStore store, dict[str, Any] config)
Definition: __init__.py:146
AuthManager auth_manager_from_config(HomeAssistant hass, list[dict[str, Any]] provider_configs, list[dict[str, Any]] module_configs)
Definition: __init__.py:54
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
CALLBACK_TYPE async_track_point_in_utc_time(HomeAssistant hass, HassJob[[datetime], Coroutine[Any, Any, None]|None]|Callable[[datetime], Coroutine[Any, Any, None]|None] action, datetime point_in_time)
Definition: event.py:1542