add an expiring cache to `_introspect_token`
parent
4ce32ade5a
commit
9db3a90782
|
@ -39,6 +39,7 @@ from synapse.logging.context import make_deferred_yieldable
|
||||||
from synapse.types import Requester, UserID, create_requester
|
from synapse.types import Requester, UserID, create_requester
|
||||||
from synapse.util import json_decoder
|
from synapse.util import json_decoder
|
||||||
from synapse.util.caches.cached_call import RetryOnExceptionCachedCall
|
from synapse.util.caches.cached_call import RetryOnExceptionCachedCall
|
||||||
|
from synapse.util.caches.expiringcache import ExpiringCache
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from synapse.server import HomeServer
|
from synapse.server import HomeServer
|
||||||
|
@ -106,6 +107,14 @@ class MSC3861DelegatedAuth(BaseAuth):
|
||||||
|
|
||||||
self._issuer_metadata = RetryOnExceptionCachedCall(self._load_metadata)
|
self._issuer_metadata = RetryOnExceptionCachedCall(self._load_metadata)
|
||||||
|
|
||||||
|
self._clock = hs.get_clock()
|
||||||
|
self._token_cache: ExpiringCache[str, IntrospectionToken] = ExpiringCache(
|
||||||
|
cache_name="introspection_token_cache",
|
||||||
|
clock=self._clock,
|
||||||
|
max_len=10000,
|
||||||
|
expiry_ms=5 * 60 * 1000,
|
||||||
|
)
|
||||||
|
|
||||||
if isinstance(auth_method, PrivateKeyJWTWithKid):
|
if isinstance(auth_method, PrivateKeyJWTWithKid):
|
||||||
# Use the JWK as the client secret when using the private_key_jwt method
|
# Use the JWK as the client secret when using the private_key_jwt method
|
||||||
assert self._config.jwk, "No JWK provided"
|
assert self._config.jwk, "No JWK provided"
|
||||||
|
@ -144,6 +153,18 @@ class MSC3861DelegatedAuth(BaseAuth):
|
||||||
Returns:
|
Returns:
|
||||||
The introspection response
|
The introspection response
|
||||||
"""
|
"""
|
||||||
|
# check the cache before doing a request
|
||||||
|
introspection_token = self._token_cache.get(token, None)
|
||||||
|
|
||||||
|
expired = False
|
||||||
|
if introspection_token:
|
||||||
|
# check the expiration field of the token (if it exists)
|
||||||
|
exp = introspection_token.get("exp", None)
|
||||||
|
if exp:
|
||||||
|
time_now = self._clock.time_msec()
|
||||||
|
expired = time_now > exp
|
||||||
|
|
||||||
|
if not introspection_token or expired:
|
||||||
metadata = await self._issuer_metadata.get()
|
metadata = await self._issuer_metadata.get()
|
||||||
introspection_endpoint = metadata.get("introspection_endpoint")
|
introspection_endpoint = metadata.get("introspection_endpoint")
|
||||||
raw_headers: Dict[str, str] = {
|
raw_headers: Dict[str, str] = {
|
||||||
|
@ -157,7 +178,10 @@ class MSC3861DelegatedAuth(BaseAuth):
|
||||||
|
|
||||||
# Fill the body/headers with credentials
|
# Fill the body/headers with credentials
|
||||||
uri, raw_headers, body = self._client_auth.prepare(
|
uri, raw_headers, body = self._client_auth.prepare(
|
||||||
method="POST", uri=introspection_endpoint, headers=raw_headers, body=body
|
method="POST",
|
||||||
|
uri=introspection_endpoint,
|
||||||
|
headers=raw_headers,
|
||||||
|
body=body,
|
||||||
)
|
)
|
||||||
headers = Headers({k: [v] for (k, v) in raw_headers.items()})
|
headers = Headers({k: [v] for (k, v) in raw_headers.items()})
|
||||||
|
|
||||||
|
@ -187,7 +211,17 @@ class MSC3861DelegatedAuth(BaseAuth):
|
||||||
"The introspection endpoint returned an invalid JSON response."
|
"The introspection endpoint returned an invalid JSON response."
|
||||||
)
|
)
|
||||||
|
|
||||||
return IntrospectionToken(**resp)
|
expiration = resp.get("exp", None)
|
||||||
|
if expiration:
|
||||||
|
if self._clock.time_msec() > expiration:
|
||||||
|
raise InvalidClientTokenError("Token is expired.")
|
||||||
|
|
||||||
|
introspection_token = IntrospectionToken(**resp)
|
||||||
|
|
||||||
|
# add token to cache
|
||||||
|
self._token_cache[token] = introspection_token
|
||||||
|
|
||||||
|
return introspection_token
|
||||||
|
|
||||||
async def is_server_admin(self, requester: Requester) -> bool:
|
async def is_server_admin(self, requester: Requester) -> bool:
|
||||||
return "urn:synapse:admin:*" in requester.scope
|
return "urn:synapse:admin:*" in requester.scope
|
||||||
|
|
Loading…
Reference in New Issue