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

Commit 92a2f05

Browse files
committed
Remove support for default values in macaroons
1 parent 94226a4 commit 92a2f05

File tree

4 files changed

+19
-53
lines changed

4 files changed

+19
-53
lines changed

synapse/handlers/auth.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1614,7 +1614,7 @@ def verify_short_term_login_token(self, token: str) -> LoginTokenAttributes:
16141614
"""
16151615
macaroon = pymacaroons.Macaroon.deserialize(token)
16161616
user_id = get_value_from_macaroon(macaroon, "user_id")
1617-
auth_provider_id = get_value_from_macaroon(macaroon, "auth_provider_id", None)
1617+
auth_provider_id = get_value_from_macaroon(macaroon, "auth_provider_id")
16181618

16191619
v = pymacaroons.Verifier()
16201620
v.satisfy_exact("gen = 1")

synapse/handlers/oidc_handler.py

+7-16
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,7 @@ async def handle_redirect_request(
746746
idp_id=self.idp_id,
747747
nonce=nonce,
748748
client_redirect_url=client_redirect_url.decode(),
749-
ui_auth_session_id=ui_auth_session_id,
749+
ui_auth_session_id=ui_auth_session_id or "",
750750
),
751751
)
752752

@@ -1021,10 +1021,9 @@ def generate_oidc_session_token(
10211021
macaroon.add_first_party_caveat(
10221022
"client_redirect_url = %s" % (session_data.client_redirect_url,)
10231023
)
1024-
if session_data.ui_auth_session_id:
1025-
macaroon.add_first_party_caveat(
1026-
"ui_auth_session_id = %s" % (session_data.ui_auth_session_id,)
1027-
)
1024+
macaroon.add_first_party_caveat(
1025+
"ui_auth_session_id = %s" % (session_data.ui_auth_session_id,)
1026+
)
10281027
now = self._clock.time_msec()
10291028
expiry = now + duration_in_ms
10301029
macaroon.add_first_party_caveat("time < %d" % (expiry,))
@@ -1058,8 +1057,6 @@ def verify_oidc_session_token(
10581057
v.satisfy_general(lambda c: c.startswith("nonce = "))
10591058
v.satisfy_general(lambda c: c.startswith("idp_id = "))
10601059
v.satisfy_general(lambda c: c.startswith("client_redirect_url = "))
1061-
# Sometimes there's a UI auth session ID, it seems to be OK to attempt
1062-
# to always satisfy this.
10631060
v.satisfy_general(lambda c: c.startswith("ui_auth_session_id = "))
10641061
satisfy_expiry(v, self._clock.time_msec)
10651062

@@ -1069,13 +1066,7 @@ def verify_oidc_session_token(
10691066
nonce = get_value_from_macaroon(macaroon, "nonce")
10701067
idp_id = get_value_from_macaroon(macaroon, "idp_id")
10711068
client_redirect_url = get_value_from_macaroon(macaroon, "client_redirect_url")
1072-
try:
1073-
ui_auth_session_id = get_value_from_macaroon(
1074-
macaroon, "ui_auth_session_id"
1075-
) # type: Optional[str]
1076-
except KeyError:
1077-
ui_auth_session_id = None
1078-
1069+
ui_auth_session_id = get_value_from_macaroon(macaroon, "ui_auth_session_id")
10791070
return OidcSessionData(
10801071
nonce=nonce,
10811072
idp_id=idp_id,
@@ -1097,8 +1088,8 @@ class OidcSessionData:
10971088
# The URL the client gave when it initiated the flow. ("" if this is a UI Auth)
10981089
client_redirect_url = attr.ib(type=str)
10991090

1100-
# The session ID of the ongoing UI Auth (None if this is a login)
1101-
ui_auth_session_id = attr.ib(type=Optional[str], default=None)
1091+
# The session ID of the ongoing UI Auth ("" if this is a login)
1092+
ui_auth_session_id = attr.ib(type=str)
11021093

11031094

11041095
UserAttributeDict = TypedDict(

synapse/util/macaroons.py

+9-34
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,13 @@
1616

1717
"""Utilities for manipulating macaroons"""
1818

19-
import enum
20-
from typing import Callable, Optional, TypeVar, Union, overload
19+
from typing import Callable, Optional
2120

2221
import pymacaroons
2322
from pymacaroons.exceptions import MacaroonVerificationFailedException
2423

25-
_TV = TypeVar("_TV")
2624

27-
28-
class _Sentinel(enum.Enum):
29-
# defining a sentinel in this way allows mypy to correctly handle the typing
30-
sentinel = object()
31-
32-
33-
_SENTINEL = object()
34-
35-
36-
@overload
3725
def get_value_from_macaroon(macaroon: pymacaroons.Macaroon, key: str) -> str:
38-
...
39-
40-
41-
@overload
42-
def get_value_from_macaroon(
43-
macaroon: pymacaroons.Macaroon, key: str, default: _TV
44-
) -> Union[str, _TV]:
45-
...
46-
47-
48-
def get_value_from_macaroon(
49-
macaroon: pymacaroons.Macaroon,
50-
key: str,
51-
default=_SENTINEL,
52-
):
5326
"""Extracts a caveat value from a macaroon token.
5427
5528
Checks that there is exactly one caveat of the form "key = <val>" in the macaroon,
@@ -60,12 +33,11 @@ def get_value_from_macaroon(
6033
key: the key of the caveat to extract
6134
6235
Returns:
63-
The extracted value, or `default`
36+
The extracted value
6437
6538
Raises:
66-
KeyError: if `default` was not given, and the caveat was not in the macaroon
6739
MacaroonVerificationFailedException: if there are conflicting values for the
68-
caveat in the macaroon
40+
caveat in the macaroon, or if the caveat was not found in the macaroon.
6941
"""
7042
prefix = key + " = "
7143
result = None # type: Optional[str]
@@ -86,9 +58,12 @@ def get_value_from_macaroon(
8658

8759
if result is not None:
8860
return result
89-
if default is _SENTINEL:
90-
raise KeyError("No %s caveat in macaroon" % (key,))
91-
return default
61+
62+
# If the caveat is not there, we raise a MacaroonVerificationFailedException.
63+
# Note that it is insecure to generate a macaroon without all the caveats you
64+
# might need (because there is nothing stopping people from adding extra caveats),
65+
# so if the caveat isn't there, something odd must be going on.
66+
raise MacaroonVerificationFailedException("No %s caveat in macaroon" % (key,))
9267

9368

9469
def satisfy_expiry(v: pymacaroons.Verifier, get_time_ms: Callable[[], int]) -> None:

tests/handlers/test_oidc.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515
import json
16-
from typing import Optional
1716
from urllib.parse import parse_qs, urlparse
1817

1918
from mock import ANY, Mock, patch
@@ -862,7 +861,7 @@ def _generate_oidc_session_token(
862861
state: str,
863862
nonce: str,
864863
client_redirect_url: str,
865-
ui_auth_session_id: Optional[str] = None,
864+
ui_auth_session_id: str = "",
866865
) -> str:
867866
from synapse.handlers.oidc_handler import OidcSessionData
868867

@@ -905,6 +904,7 @@ async def _make_callback_with_userinfo(
905904
idp_id="oidc",
906905
nonce="nonce",
907906
client_redirect_url=client_redirect_url,
907+
ui_auth_session_id="",
908908
),
909909
)
910910
request = _build_callback_request("code", state, session)

0 commit comments

Comments
 (0)