Skip to content

Commit

Permalink
♻️ Expired confirmation tokens are logged and INVITATION tokens do no…
Browse files Browse the repository at this point in the history
…t expire (#3440)
  • Loading branch information
pcrespov authored Oct 13, 2022
1 parent 2169876 commit 576c686
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@ async def validate_confirmation_code(
{"code": code}
)
if confirmation and is_confirmation_expired(cfg, confirmation):
log.info(
"Confirmation code '%s' %s. Deleting ...",
code,
"consumed" if confirmation else "expired",
)
await db.delete_confirmation(confirmation)
log.warning(
"Used expired token [%s]. Deleted from confirmations table.",
confirmation,
)
return None
return confirmation

Expand Down Expand Up @@ -68,6 +67,10 @@ async def is_confirmation_allowed(
return True
if is_confirmation_expired(cfg, confirmation):
await db.delete_confirmation(confirmation)
log.warning(
"Used expired token [%s]. Deleted from confirmations table.",
confirmation,
)
return True


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ async def check_registration(
confirm: Optional[str],
db: AsyncpgStorage,
cfg: LoginOptions,
):
) -> None:
# email : required & formats
# password: required & secure[min length, ...]

Expand Down Expand Up @@ -115,6 +115,12 @@ async def check_registration(
if is_confirmation_expired(cfg, _confirmation):
await db.delete_confirmation(_confirmation)
await db.delete_user(user)
log.warning(
"Time to confirm a registration is overdue. Used expired token [%s]."
"Deleted token from confirmations table and %s from users table.",
_confirmation,
f"{user=}",
)
return

# If the email is already taken, return a 409 - HTTPConflict
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from datetime import timedelta
from typing import Literal, Optional
from typing import Final, Literal, Optional

from aiohttp import web
from pydantic import BaseModel, validator
Expand All @@ -10,9 +10,10 @@

from .._constants import APP_SETTINGS_KEY

_DAYS = 1.0 # in days
_MINUTES = 1.0 / 24.0 / 60.0 # in days

_DAYS: Final[float] = 1.0 # in days
_MINUTES: Final[float] = 1.0 / 24.0 / 60.0 # in days
_YEARS: Final[float] = 365 * _DAYS
_UNLIMITED: Final[float] = 99 * _YEARS

APP_LOGIN_OPTIONS_KEY = f"{__name__}.APP_LOGIN_OPTIONS_KEY"

Expand Down Expand Up @@ -76,9 +77,9 @@ class LoginOptions(BaseModel):
SMTP_USERNAME: Optional[str] = Field(...)
SMTP_PASSWORD: Optional[SecretStr] = Field(...)

# lifetime limits are in days
# NOTE: lifetime limits are expressed in days (use constants above)
REGISTRATION_CONFIRMATION_LIFETIME: PositiveFloat = 5 * _DAYS
INVITATION_CONFIRMATION_LIFETIME: PositiveFloat = 15 * _DAYS
INVITATION_CONFIRMATION_LIFETIME: PositiveFloat = _UNLIMITED
RESET_PASSWORD_CONFIRMATION_LIFETIME: PositiveFloat = 20 * _MINUTES
CHANGE_EMAIL_CONFIRMATION_LIFETIME: PositiveFloat = 5 * _DAYS

Expand All @@ -89,7 +90,6 @@ def get_confirmation_lifetime(
value = getattr(self, f"{action.upper()}_CONFIRMATION_LIFETIME")
return timedelta(days=value)

# TODO: translation?
MSG_LOGGED_IN: str = "You are logged in"
MSG_LOGGED_OUT: str = "You are logged out"
MSG_2FA_CODE_SENT: str = "Code sent by SMS to {phone_number}"
Expand Down

0 comments on commit 576c686

Please sign in to comment.