Let authenticators provide username and password separately

This commit is contained in:
Joscha 2021-05-15 18:24:03 +02:00
parent d63494908d
commit 8c32da7f19
4 changed files with 32 additions and 22 deletions

View File

@ -93,7 +93,7 @@ auth = auth:example
## The `auth:*` sections ## The `auth:*` sections
Sections whose names start with `auth:` are used to configure authenticators. An Sections whose names start with `auth:` are used to configure authenticators. An
authenticator provides login credentials to one or more crawlers. authenticator provides a username and a password to one or more crawlers.
Authenticators work similar to crawlers: A section represents an authenticator Authenticators work similar to crawlers: A section represents an authenticator
instance, whose name is the rest of the section name. The type is specified by instance, whose name is the rest of the section name. The type is specified by

View File

@ -42,6 +42,14 @@ class Authenticator(ABC):
async def credentials(self) -> Tuple[str, str]: async def credentials(self) -> Tuple[str, str]:
pass pass
async def username(self) -> str:
username, _ = await self.credentials()
return username
async def password(self) -> str:
_, password = await self.credentials()
return password
def invalidate_credentials(self) -> None: def invalidate_credentials(self) -> None:
""" """
Tell the authenticator that some or all of its credentials are invalid. Tell the authenticator that some or all of its credentials are invalid.

View File

@ -24,44 +24,46 @@ class SimpleAuthenticator(Authenticator):
) -> None: ) -> None:
super().__init__(name, section, config, conductor) super().__init__(name, section, config, conductor)
self.username = section.username() self._username = section.username()
self.password = section.password() self._password = section.password()
self.username_fixed = self.username is not None self._username_fixed = self.username is not None
self.password_fixed = self.password is not None self._password_fixed = self.password is not None
async def credentials(self) -> Tuple[str, str]: async def credentials(self) -> Tuple[str, str]:
if self.username is not None and self.password is not None: if self._username is not None and self._password is not None:
return self.username, self.password return self._username, self._password
async with self.conductor.exclusive_output(): async with self.conductor.exclusive_output():
if self.username is None: if self._username is None:
self.username = await ainput("Username: ") self._username = await ainput("Username: ")
else: else:
print(f"Username: {self.username}") print(f"Username: {self.username}")
if self.password is None: if self._password is None:
self.password = await agetpass("Password: ") self._password = await agetpass("Password: ")
return self.username, self.password # Intentionally returned inside the context manager so we know
# they're both not None
return self._username, self._password
def invalidate_credentials(self) -> None: def invalidate_credentials(self) -> None:
if self.username_fixed and self.password_fixed: if self._username_fixed and self._password_fixed:
raise AuthException("Configured credentials are invalid") raise AuthException("Configured credentials are invalid")
if not self.username_fixed: if not self._username_fixed:
self.username = None self._username = None
if not self.password_fixed: if not self._password_fixed:
self.password = None self._password = None
def invalidate_username(self) -> None: def invalidate_username(self) -> None:
if self.username_fixed: if self._username_fixed:
raise AuthException("Configured username is invalid") raise AuthException("Configured username is invalid")
else: else:
self.username = None self._username = None
def invalidate_password(self) -> None: def invalidate_password(self) -> None:
if self.password_fixed: if self._password_fixed:
raise AuthException("Configured password is invalid") raise AuthException("Configured password is invalid")
else: else:
self.password = None self._password = None

View File

@ -177,7 +177,7 @@ class KitShibbolethLogin:
if not self._tfa_auth: if not self._tfa_auth:
raise RuntimeError("No 'tfa_auth' present but you use two-factor authentication!") raise RuntimeError("No 'tfa_auth' present but you use two-factor authentication!")
_, tfa_token = await self._tfa_auth.credentials() tfa_token = await self._tfa_auth.password()
# Searching the form here so that this fails before asking for # Searching the form here so that this fails before asking for
# credentials rather than after asking. # credentials rather than after asking.