mirror of
https://git.anonymousland.org/anonymousland/synapse.git
synced 2025-05-07 22:14:57 -04:00
Save login tokens in database (#13844)
* Save login tokens in database Signed-off-by: Quentin Gliech <quenting@element.io> * Add upgrade notes * Track login token reuse in a Prometheus metric Signed-off-by: Quentin Gliech <quenting@element.io>
This commit is contained in:
parent
d902181de9
commit
8756d5c87e
11 changed files with 338 additions and 228 deletions
|
@ -24,7 +24,7 @@ from typing_extensions import Literal
|
|||
|
||||
from synapse.util import Clock, stringutils
|
||||
|
||||
MacaroonType = Literal["access", "delete_pusher", "session", "login"]
|
||||
MacaroonType = Literal["access", "delete_pusher", "session"]
|
||||
|
||||
|
||||
def get_value_from_macaroon(macaroon: pymacaroons.Macaroon, key: str) -> str:
|
||||
|
@ -111,19 +111,6 @@ class OidcSessionData:
|
|||
"""The session ID of the ongoing UI Auth ("" if this is a login)"""
|
||||
|
||||
|
||||
@attr.s(slots=True, frozen=True, auto_attribs=True)
|
||||
class LoginTokenAttributes:
|
||||
"""Data we store in a short-term login token"""
|
||||
|
||||
user_id: str
|
||||
|
||||
auth_provider_id: str
|
||||
"""The SSO Identity Provider that the user authenticated with, to get this token."""
|
||||
|
||||
auth_provider_session_id: Optional[str]
|
||||
"""The session ID advertised by the SSO Identity Provider."""
|
||||
|
||||
|
||||
class MacaroonGenerator:
|
||||
def __init__(self, clock: Clock, location: str, secret_key: bytes):
|
||||
self._clock = clock
|
||||
|
@ -165,35 +152,6 @@ class MacaroonGenerator:
|
|||
macaroon.add_first_party_caveat(f"pushkey = {pushkey}")
|
||||
return macaroon.serialize()
|
||||
|
||||
def generate_short_term_login_token(
|
||||
self,
|
||||
user_id: str,
|
||||
auth_provider_id: str,
|
||||
auth_provider_session_id: Optional[str] = None,
|
||||
duration_in_ms: int = (2 * 60 * 1000),
|
||||
) -> str:
|
||||
"""Generate a short-term login token used during SSO logins
|
||||
|
||||
Args:
|
||||
user_id: The user for which the token is valid.
|
||||
auth_provider_id: The SSO IdP the user used.
|
||||
auth_provider_session_id: The session ID got during login from the SSO IdP.
|
||||
|
||||
Returns:
|
||||
A signed token valid for using as a ``m.login.token`` token.
|
||||
"""
|
||||
now = self._clock.time_msec()
|
||||
expiry = now + duration_in_ms
|
||||
macaroon = self._generate_base_macaroon("login")
|
||||
macaroon.add_first_party_caveat(f"user_id = {user_id}")
|
||||
macaroon.add_first_party_caveat(f"time < {expiry}")
|
||||
macaroon.add_first_party_caveat(f"auth_provider_id = {auth_provider_id}")
|
||||
if auth_provider_session_id is not None:
|
||||
macaroon.add_first_party_caveat(
|
||||
f"auth_provider_session_id = {auth_provider_session_id}"
|
||||
)
|
||||
return macaroon.serialize()
|
||||
|
||||
def generate_oidc_session_token(
|
||||
self,
|
||||
state: str,
|
||||
|
@ -233,49 +191,6 @@ class MacaroonGenerator:
|
|||
|
||||
return macaroon.serialize()
|
||||
|
||||
def verify_short_term_login_token(self, token: str) -> LoginTokenAttributes:
|
||||
"""Verify a short-term-login macaroon
|
||||
|
||||
Checks that the given token is a valid, unexpired short-term-login token
|
||||
minted by this server.
|
||||
|
||||
Args:
|
||||
token: The login token to verify.
|
||||
|
||||
Returns:
|
||||
A set of attributes carried by this token, including the
|
||||
``user_id`` and informations about the SSO IDP used during that
|
||||
login.
|
||||
|
||||
Raises:
|
||||
MacaroonVerificationFailedException if the verification failed
|
||||
"""
|
||||
macaroon = pymacaroons.Macaroon.deserialize(token)
|
||||
|
||||
v = self._base_verifier("login")
|
||||
v.satisfy_general(lambda c: c.startswith("user_id = "))
|
||||
v.satisfy_general(lambda c: c.startswith("auth_provider_id = "))
|
||||
v.satisfy_general(lambda c: c.startswith("auth_provider_session_id = "))
|
||||
satisfy_expiry(v, self._clock.time_msec)
|
||||
v.verify(macaroon, self._secret_key)
|
||||
|
||||
user_id = get_value_from_macaroon(macaroon, "user_id")
|
||||
auth_provider_id = get_value_from_macaroon(macaroon, "auth_provider_id")
|
||||
|
||||
auth_provider_session_id: Optional[str] = None
|
||||
try:
|
||||
auth_provider_session_id = get_value_from_macaroon(
|
||||
macaroon, "auth_provider_session_id"
|
||||
)
|
||||
except MacaroonVerificationFailedException:
|
||||
pass
|
||||
|
||||
return LoginTokenAttributes(
|
||||
user_id=user_id,
|
||||
auth_provider_id=auth_provider_id,
|
||||
auth_provider_session_id=auth_provider_session_id,
|
||||
)
|
||||
|
||||
def verify_guest_token(self, token: str) -> str:
|
||||
"""Verify a guest access token macaroon
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue