Commit 8db1f256 authored by Vincent Pelletier's avatar Vincent Pelletier Committed by Titouan Soulard

erp5_oauth2_authorisation: Do not edit OAuth2 Session on every refresh token issuance

Malevolent users may decide to only - and repeatedly - present an otherwise
valid refresh token, causing the issuance of a new access tokens everytime,
likely along with new refresh tokens, causing many ZODB writes.
Avoid this by pushing the token expiration date by one lifespan accuracy,
so there can only be one write per session per lifespan accuracy period.
parent a4b2bc3b
Pipeline #37950 passed with stage
in 0 seconds
...@@ -1180,8 +1180,9 @@ class OAuth2AuthorisationServerConnector(XMLObject): ...@@ -1180,8 +1180,9 @@ class OAuth2AuthorisationServerConnector(XMLObject):
algorithm=algorithm, algorithm=algorithm,
) )
def generateRefreshToken(request): def generateRefreshToken(request):
erp5_client_value = request.client.erp5_client_value
session_value = request.user.erp5_session_value session_value = request.user.erp5_session_value
expiration_timestamp = now + request.client.erp5_client_value.getRefreshTokenLifespan() expiration_timestamp = now + erp5_client_value.getRefreshTokenLifespan()
session_expiration_date = session_value.getPolicyExpirationDate() session_expiration_date = session_value.getPolicyExpirationDate()
if session_expiration_date is not None: if session_expiration_date is not None:
expiration_timestamp = min( expiration_timestamp = min(
...@@ -1193,7 +1194,9 @@ class OAuth2AuthorisationServerConnector(XMLObject): ...@@ -1193,7 +1194,9 @@ class OAuth2AuthorisationServerConnector(XMLObject):
session_refresh_token_expiration_date is None or session_refresh_token_expiration_date is None or
session_refresh_token_expiration_date < DateTime(expiration_timestamp) session_refresh_token_expiration_date < DateTime(expiration_timestamp)
): ):
session_value.setRefreshTokenExpirationDate(DateTime(expiration_timestamp)) session_value.setRefreshTokenExpirationDate(DateTime(
expiration_timestamp + erp5_client_value.getRefreshTokenLifespanAccuracy(),
))
_, algorithm, symetric_key = self.__getRefreshTokenKeyList()[0] _, algorithm, symetric_key = self.__getRefreshTokenKeyList()[0]
jwt_payload = { jwt_payload = {
JWT_PAYLOAD_AUTHORISATION_SESSION_ID_KEY: session_value.getId(), JWT_PAYLOAD_AUTHORISATION_SESSION_ID_KEY: session_value.getId(),
......
...@@ -868,8 +868,12 @@ class TestOAuth2(ERP5TypeTestCase): ...@@ -868,8 +868,12 @@ class TestOAuth2(ERP5TypeTestCase):
# OAuth2 Session is now validated # OAuth2 Session is now validated
self.assertEqual(user_session.getValidationState(), 'validated') self.assertEqual(user_session.getValidationState(), 'validated')
expiration_date = int(user_session.getExpirationDate()) expiration_date = int(user_session.getExpirationDate())
self.assertLessEqual(time_before + refresh_token_lifespan, expiration_date) refresh_token_base_offset = (
self.assertLessEqual(expiration_date, time_after + refresh_token_lifespan) refresh_token_lifespan +
oauth2_client_declaration_value.getRefreshTokenLifespanAccuracy()
)
self.assertLessEqual(time_before + refresh_token_base_offset, expiration_date)
self.assertLessEqual(expiration_date, time_after + refresh_token_base_offset)
# Request a new access token # Request a new access token
status, header_dict, cookie_dict, body = self._query( status, header_dict, cookie_dict, body = self._query(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment