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

Commit f2466b2

Browse files
committed
Store auth provider id in login tokens
1 parent 3d4902b commit f2466b2

File tree

4 files changed

+52
-6
lines changed

4 files changed

+52
-6
lines changed

synapse/handlers/auth.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,7 @@ async def start_sso_ui_auth(self, request: SynapseRequest, session_id: str) -> s
14061406
async def complete_sso_login(
14071407
self,
14081408
registered_user_id: str,
1409+
auth_provider_id: str,
14091410
request: Request,
14101411
client_redirect_url: str,
14111412
extra_attributes: Optional[JsonDict] = None,
@@ -1415,6 +1416,9 @@ async def complete_sso_login(
14151416
14161417
Args:
14171418
registered_user_id: The registered user ID to complete SSO login for.
1419+
auth_provider_id: The id of the SSO Identity provider that was used for
1420+
login. This will be stored in the login token for future tracking in
1421+
prometheus metrics.
14181422
request: The request to complete.
14191423
client_redirect_url: The URL to which to redirect the user at the end of the
14201424
process.
@@ -1436,6 +1440,7 @@ async def complete_sso_login(
14361440

14371441
self._complete_sso_login(
14381442
registered_user_id,
1443+
auth_provider_id,
14391444
request,
14401445
client_redirect_url,
14411446
extra_attributes,
@@ -1446,6 +1451,7 @@ async def complete_sso_login(
14461451
def _complete_sso_login(
14471452
self,
14481453
registered_user_id: str,
1454+
auth_provider_id: str,
14491455
request: Request,
14501456
client_redirect_url: str,
14511457
extra_attributes: Optional[JsonDict] = None,
@@ -1472,7 +1478,7 @@ def _complete_sso_login(
14721478

14731479
# Create a login token
14741480
login_token = self.macaroon_gen.generate_short_term_login_token(
1475-
registered_user_id
1481+
registered_user_id, auth_provider_id=auth_provider_id
14761482
)
14771483

14781484
# Append the login token to the original redirect URL (i.e. with its query
@@ -1578,13 +1584,20 @@ def generate_access_token(
15781584
return macaroon.serialize()
15791585

15801586
def generate_short_term_login_token(
1581-
self, user_id: str, duration_in_ms: int = (2 * 60 * 1000)
1587+
self,
1588+
user_id: str,
1589+
duration_in_ms: int = (2 * 60 * 1000),
1590+
auth_provider_id: Optional[str] = None,
15821591
) -> str:
15831592
macaroon = self._generate_base_macaroon(user_id)
15841593
macaroon.add_first_party_caveat("type = login")
15851594
now = self.hs.get_clock().time_msec()
15861595
expiry = now + duration_in_ms
15871596
macaroon.add_first_party_caveat("time < %d" % (expiry,))
1597+
if auth_provider_id is not None:
1598+
macaroon.add_first_party_caveat(
1599+
"auth_provider_id = %s" % (auth_provider_id,)
1600+
)
15881601
return macaroon.serialize()
15891602

15901603
def verify_short_term_login_token(self, token: str) -> LoginTokenAttributes:

synapse/handlers/sso.py

+2
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ async def complete_sso_login_request(
456456

457457
await self._auth_handler.complete_sso_login(
458458
user_id,
459+
auth_provider_id,
459460
request,
460461
client_redirect_url,
461462
extra_login_attributes,
@@ -886,6 +887,7 @@ async def register_sso_user(self, request: Request, session_id: str) -> None:
886887

887888
await self._auth_handler.complete_sso_login(
888889
user_id,
890+
session.auth_provider_id,
889891
request,
890892
session.client_redirect_url,
891893
session.extra_login_attributes,

synapse/module_api/__init__.py

+27-4
Original file line numberDiff line numberDiff line change
@@ -203,11 +203,26 @@ def record_user_external_id(
203203
)
204204

205205
def generate_short_term_login_token(
206-
self, user_id: str, duration_in_ms: int = (2 * 60 * 1000)
206+
self,
207+
user_id: str,
208+
duration_in_ms: int = (2 * 60 * 1000),
209+
auth_provider_id: Optional[str] = None,
207210
) -> str:
208-
"""Generate a login token suitable for m.login.token authentication"""
211+
"""Generate a login token suitable for m.login.token authentication
212+
213+
Args:
214+
user_id: gives the ID of the user that the token is for
215+
216+
duration_in_ms: the time that the token will be valid for
217+
218+
auth_provider_id: the ID of the SSO IdP that the user used to authenticate
219+
to get this token, if any. This is encoded in the token so that
220+
/login can report stats on number of successful logins by IdP.
221+
"""
209222
return self._hs.get_macaroon_generator().generate_short_term_login_token(
210-
user_id, duration_in_ms
223+
user_id,
224+
duration_in_ms,
225+
auth_provider_id=auth_provider_id,
211226
)
212227

213228
@defer.inlineCallbacks
@@ -276,6 +291,7 @@ def complete_sso_login(
276291
"""
277292
self._auth_handler._complete_sso_login(
278293
registered_user_id,
294+
"<unknown>",
279295
request,
280296
client_redirect_url,
281297
)
@@ -286,6 +302,7 @@ async def complete_sso_login_async(
286302
request: SynapseRequest,
287303
client_redirect_url: str,
288304
new_user: bool = False,
305+
auth_provider_id: str = "<unknown>",
289306
):
290307
"""Complete a SSO login by redirecting the user to a page to confirm whether they
291308
want their access token sent to `client_redirect_url`, or redirect them to that
@@ -299,9 +316,15 @@ async def complete_sso_login_async(
299316
redirect them directly if whitelisted).
300317
new_user: set to true to use wording for the consent appropriate to a user
301318
who has just registered.
319+
auth_provider_id: the ID of the SSO IdP which was used to log in. This
320+
is used to track counts of sucessful logins by IdP.
302321
"""
303322
await self._auth_handler.complete_sso_login(
304-
registered_user_id, request, client_redirect_url, new_user=new_user
323+
registered_user_id,
324+
auth_provider_id,
325+
request,
326+
client_redirect_url,
327+
new_user=new_user,
305328
)
306329

307330
@defer.inlineCallbacks

tests/handlers/test_auth.py

+8
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,14 @@ def test_short_term_login_token_gives_user_id(self):
8080
AuthError,
8181
)
8282

83+
def test_short_term_login_token_gives_auth_provider(self):
84+
token = self.macaroon_generator.generate_short_term_login_token(
85+
"a_user", auth_provider_id="my_idp"
86+
)
87+
res = self.get_success(self.auth_handler.validate_short_term_login_token(token))
88+
self.assertEqual("a_user", res.user_id)
89+
self.assertEqual("my_idp", res.auth_provider_id)
90+
8391
def test_short_term_login_token_cannot_replace_user_id(self):
8492
token = self.macaroon_generator.generate_short_term_login_token("a_user", 5000)
8593
macaroon = pymacaroons.Macaroon.deserialize(token)

0 commit comments

Comments
 (0)