Skip to content

Commit

Permalink
Enforce refresh token clean-up (#130)
Browse files Browse the repository at this point in the history
* Enforce refresh token clean-up

Also do not try to refresh if the access token is still valid

* Add some docstring

* Linting

* Update requirements

* Avoid oauthenticator 17
  • Loading branch information
enolfc authored Sep 11, 2024
1 parent 72515b1 commit bebde36
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 3 deletions.
19 changes: 18 additions & 1 deletion egi_notebooks_hub/egiauthenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@


class JWTHandler(BaseHandler):
"""Handler for authentication with JWT tokens"""

async def exchange_for_refresh_token(self, access_token):
self.log.debug("Exchanging access token for refresh")
http_client = AsyncHTTPClient()
Expand Down Expand Up @@ -237,7 +239,7 @@ async def jwt_authenticate(self, handler, data=None):
username = self.user_info_to_username(user_info)
username = self.normalize_username(username)

# check if there any refresh_token in the token_info dict
# check if there is any refresh_token in the token_info dict
refresh_token = data.get("refresh_token", None)
if self.enable_auth_state and not refresh_token:
self.log.debug(
Expand Down Expand Up @@ -303,6 +305,17 @@ async def refresh_user(self, user, handler=None):
)
return True

try:
if jwt.decode(
access_token,
options=dict(verify_signature=False, verify_exp=True),
):
# access token is good, no need to keep going
self.log.debug("Access token is still good, no refresh needed")
return True
except jwt.exceptions.InvalidTokenError as e:
self.log.debug(f"Invalid access token, will try to refresh: {e}")

now = time.time()
refresh_info = auth_state.get("refresh_info", {})
# if the token is still valid, avoid refreshing
Expand Down Expand Up @@ -343,6 +356,10 @@ async def refresh_user(self, user, handler=None):
resp = await http_client.fetch(req)
except HTTPClientError as e:
self.log.warning("Unable to refresh token, maybe expired: %s", e)
if e.response:
self.log.warning("Response from server: %s", e.response.body)
# clear here the existing auth state so it's no longer valid
await user.save_auth_state(None)
return False
refresh_info = json.loads(resp.body.decode("utf8", "replace"))
refresh_info["expiry_time"] = now + refresh_info["expires_in"]
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
jupyterhub>=4.0.2
oauthenticator>=16.3.0
oauthenticator>=16.3.0,<17
jupyterhub-kubespawner>=6.1.0
xmltodict
fastapi
fastapi[standard]
pydantic-settings
pbr

0 comments on commit bebde36

Please sign in to comment.