Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2624 from matrix-org/rav/password_provider_notify…
Browse files Browse the repository at this point in the history
…_logout

Notify auth providers on logout
  • Loading branch information
dbkr authored Nov 2, 2017
2 parents 1f080a6 + bc8a5c0 commit b19d9e2
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 7 deletions.
10 changes: 10 additions & 0 deletions docs/password_auth_providers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,13 @@ Password auth provider classes may optionally provide the following methods.

The method should return a Twisted ``Deferred`` object, which resolves to
``True`` if authentication is successful, and ``False`` if not.

``someprovider.on_logged_out``\(*user_id*, *device_id*, *access_token*)

This method, if implemented, is called when a user logs out. It is passed
the qualified user ID, the ID of the deactivated device (if any: access
tokens are occasionally created without an associated device ID), and the
(now deactivated) access token.

It may return a Twisted ``Deferred`` object; the logout request will wait
for the deferred to complete but the result is ignored.
26 changes: 24 additions & 2 deletions synapse/handlers/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,7 @@ def deactivate_account(self, user_id):
yield self.store.user_delete_threepids(user_id)
yield self.store.user_set_password_hash(user_id, None)

@defer.inlineCallbacks
def delete_access_token(self, access_token):
"""Invalidate a single access token
Expand All @@ -696,8 +697,19 @@ def delete_access_token(self, access_token):
Returns:
Deferred
"""
return self.store.delete_access_token(access_token)
user_info = yield self.auth.get_user_by_access_token(access_token)
yield self.store.delete_access_token(access_token)

# see if any of our auth providers want to know about this
for provider in self.password_providers:
if hasattr(provider, "on_logged_out"):
yield provider.on_logged_out(
user_id=str(user_info["user"]),
device_id=user_info["device_id"],
access_token=access_token,
)

@defer.inlineCallbacks
def delete_access_tokens_for_user(self, user_id, except_token_id=None,
device_id=None):
"""Invalidate access tokens belonging to a user
Expand All @@ -712,10 +724,20 @@ def delete_access_tokens_for_user(self, user_id, except_token_id=None,
Returns:
Deferred
"""
return self.store.user_delete_access_tokens(
tokens_and_devices = yield self.store.user_delete_access_tokens(
user_id, except_token_id=except_token_id, device_id=device_id,
)

# see if any of our auth providers want to know about this
for provider in self.password_providers:
if hasattr(provider, "on_logged_out"):
for token, device_id in tokens_and_devices:
yield provider.on_logged_out(
user_id=user_id,
device_id=device_id,
access_token=token,
)

@defer.inlineCallbacks
def add_threepid(self, user_id, medium, address, validated_at):
# 'Canonicalise' email addresses down to lower case.
Expand Down
13 changes: 8 additions & 5 deletions synapse/storage/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ def user_delete_access_tokens(self, user_id, except_token_id=None,
If None, tokens associated with any device (or no device) will
be deleted
Returns:
defer.Deferred:
defer.Deferred[list[str, str|None]]: a list of the deleted tokens
and device IDs
"""
def f(txn):
keyvalues = {
Expand All @@ -272,21 +273,23 @@ def f(txn):
values.append(except_token_id)

txn.execute(
"SELECT token FROM access_tokens WHERE %s" % where_clause,
"SELECT token, device_id FROM access_tokens WHERE %s" % where_clause,
values
)
rows = self.cursor_to_dict(txn)
tokens_and_devices = [(r[0], r[1]) for r in txn]

for row in rows:
for token, _ in tokens_and_devices:
self._invalidate_cache_and_stream(
txn, self.get_user_by_access_token, (row["token"],)
txn, self.get_user_by_access_token, (token,)
)

txn.execute(
"DELETE FROM access_tokens WHERE %s" % where_clause,
values
)

return tokens_and_devices

yield self.runInteraction(
"user_delete_access_tokens", f,
)
Expand Down

0 comments on commit b19d9e2

Please sign in to comment.