From 5e555a8f9a36eba414d35d3883f8c68430f8f17c Mon Sep 17 00:00:00 2001 From: Anish Sarkar <104695310+AnishSarkar22@users.noreply.github.com> Date: Sat, 31 Jan 2026 16:24:43 +0530 Subject: [PATCH] fix: improve notification for token expiration and revocation errors for multiple connectors --- .../connectors/google_drive/credentials.py | 9 +++++++ .../routes/airtable_add_connector_route.py | 13 +++++++++ .../app/routes/clickup_add_connector_route.py | 11 ++++++++ .../routes/confluence_add_connector_route.py | 13 +++++++++ .../app/routes/jira_add_connector_route.py | 13 +++++++++ .../app/routes/linear_add_connector_route.py | 13 +++++++++ .../app/routes/notion_add_connector_route.py | 13 +++++++++ .../app/routes/slack_add_connector_route.py | 27 +++++++++++++++++++ .../app/routes/teams_add_connector_route.py | 13 +++++++++ 9 files changed, 125 insertions(+) diff --git a/surfsense_backend/app/connectors/google_drive/credentials.py b/surfsense_backend/app/connectors/google_drive/credentials.py index 7e6335f6d..5b1900ab2 100644 --- a/surfsense_backend/app/connectors/google_drive/credentials.py +++ b/surfsense_backend/app/connectors/google_drive/credentials.py @@ -132,6 +132,15 @@ async def get_valid_credentials( await session.commit() except Exception as e: + error_str = str(e) + # Check if this is an invalid_grant error (token expired/revoked) + if ( + "invalid_grant" in error_str.lower() + or "token has been expired or revoked" in error_str.lower() + ): + raise Exception( + "Google Drive authentication failed. Please re-authenticate." + ) from e raise Exception(f"Failed to refresh Google OAuth credentials: {e!s}") from e return credentials diff --git a/surfsense_backend/app/routes/airtable_add_connector_route.py b/surfsense_backend/app/routes/airtable_add_connector_route.py index 64fa104d8..423d61fb2 100644 --- a/surfsense_backend/app/routes/airtable_add_connector_route.py +++ b/surfsense_backend/app/routes/airtable_add_connector_route.py @@ -442,11 +442,24 @@ async def refresh_airtable_token( if token_response.status_code != 200: error_detail = token_response.text + error_code = "" try: error_json = token_response.json() error_detail = error_json.get("error_description", error_detail) + error_code = error_json.get("error", "") except Exception: pass + # Check if this is a token expiration/revocation error + error_lower = (error_detail + error_code).lower() + if ( + "invalid_grant" in error_lower + or "expired" in error_lower + or "revoked" in error_lower + ): + raise HTTPException( + status_code=401, + detail="Airtable authentication failed. Please re-authenticate.", + ) raise HTTPException( status_code=400, detail=f"Token refresh failed: {error_detail}" ) diff --git a/surfsense_backend/app/routes/clickup_add_connector_route.py b/surfsense_backend/app/routes/clickup_add_connector_route.py index f962f65fb..1b2e6795d 100644 --- a/surfsense_backend/app/routes/clickup_add_connector_route.py +++ b/surfsense_backend/app/routes/clickup_add_connector_route.py @@ -417,6 +417,17 @@ async def refresh_clickup_token( error_detail = error_json.get("error", error_detail) except Exception: pass + # Check if this is a token expiration/revocation error + error_lower = error_detail.lower() + if ( + "invalid_grant" in error_lower + or "expired" in error_lower + or "revoked" in error_lower + ): + raise HTTPException( + status_code=401, + detail="ClickUp authentication failed. Please re-authenticate.", + ) raise HTTPException( status_code=400, detail=f"Token refresh failed: {error_detail}" ) diff --git a/surfsense_backend/app/routes/confluence_add_connector_route.py b/surfsense_backend/app/routes/confluence_add_connector_route.py index 6c5830b17..24e0f858a 100644 --- a/surfsense_backend/app/routes/confluence_add_connector_route.py +++ b/surfsense_backend/app/routes/confluence_add_connector_route.py @@ -428,13 +428,26 @@ async def refresh_confluence_token( if token_response.status_code != 200: error_detail = token_response.text + error_code = "" try: error_json = token_response.json() error_detail = error_json.get( "error_description", error_json.get("error", error_detail) ) + error_code = error_json.get("error", "") except Exception: pass + # Check if this is a token expiration/revocation error + error_lower = (error_detail + error_code).lower() + if ( + "invalid_grant" in error_lower + or "expired" in error_lower + or "revoked" in error_lower + ): + raise HTTPException( + status_code=401, + detail="Confluence authentication failed. Please re-authenticate.", + ) raise HTTPException( status_code=400, detail=f"Token refresh failed: {error_detail}" ) diff --git a/surfsense_backend/app/routes/jira_add_connector_route.py b/surfsense_backend/app/routes/jira_add_connector_route.py index fb66f4da7..58903606a 100644 --- a/surfsense_backend/app/routes/jira_add_connector_route.py +++ b/surfsense_backend/app/routes/jira_add_connector_route.py @@ -446,13 +446,26 @@ async def refresh_jira_token( if token_response.status_code != 200: error_detail = token_response.text + error_code = "" try: error_json = token_response.json() error_detail = error_json.get( "error_description", error_json.get("error", error_detail) ) + error_code = error_json.get("error", "") except Exception: pass + # Check if this is a token expiration/revocation error + error_lower = (error_detail + error_code).lower() + if ( + "invalid_grant" in error_lower + or "expired" in error_lower + or "revoked" in error_lower + ): + raise HTTPException( + status_code=401, + detail="Jira authentication failed. Please re-authenticate.", + ) raise HTTPException( status_code=400, detail=f"Token refresh failed: {error_detail}" ) diff --git a/surfsense_backend/app/routes/linear_add_connector_route.py b/surfsense_backend/app/routes/linear_add_connector_route.py index fc9501bfb..dd5f7443c 100644 --- a/surfsense_backend/app/routes/linear_add_connector_route.py +++ b/surfsense_backend/app/routes/linear_add_connector_route.py @@ -403,11 +403,24 @@ async def refresh_linear_token( if token_response.status_code != 200: error_detail = token_response.text + error_code = "" try: error_json = token_response.json() error_detail = error_json.get("error_description", error_detail) + error_code = error_json.get("error", "") except Exception: pass + # Check if this is a token expiration/revocation error + error_lower = (error_detail + error_code).lower() + if ( + "invalid_grant" in error_lower + or "expired" in error_lower + or "revoked" in error_lower + ): + raise HTTPException( + status_code=401, + detail="Linear authentication failed. Please re-authenticate.", + ) raise HTTPException( status_code=400, detail=f"Token refresh failed: {error_detail}" ) diff --git a/surfsense_backend/app/routes/notion_add_connector_route.py b/surfsense_backend/app/routes/notion_add_connector_route.py index aac821793..81017af50 100644 --- a/surfsense_backend/app/routes/notion_add_connector_route.py +++ b/surfsense_backend/app/routes/notion_add_connector_route.py @@ -407,11 +407,24 @@ async def refresh_notion_token( if token_response.status_code != 200: error_detail = token_response.text + error_code = "" try: error_json = token_response.json() error_detail = error_json.get("error_description", error_detail) + error_code = error_json.get("error", "") except Exception: pass + # Check if this is a token expiration/revocation error + error_lower = (error_detail + error_code).lower() + if ( + "invalid_grant" in error_lower + or "expired" in error_lower + or "revoked" in error_lower + ): + raise HTTPException( + status_code=401, + detail="Notion authentication failed. Please re-authenticate.", + ) raise HTTPException( status_code=400, detail=f"Token refresh failed: {error_detail}" ) diff --git a/surfsense_backend/app/routes/slack_add_connector_route.py b/surfsense_backend/app/routes/slack_add_connector_route.py index 62d2ccaaa..e7f19e8b0 100644 --- a/surfsense_backend/app/routes/slack_add_connector_route.py +++ b/surfsense_backend/app/routes/slack_add_connector_route.py @@ -418,6 +418,19 @@ async def refresh_slack_token( error_detail = error_json.get("error", error_detail) except Exception: pass + # Check if this is a token expiration/revocation error + error_lower = error_detail.lower() + if ( + "invalid_grant" in error_lower + or "invalid_auth" in error_lower + or "token_revoked" in error_lower + or "expired" in error_lower + or "revoked" in error_lower + ): + raise HTTPException( + status_code=401, + detail="Slack authentication failed. Please re-authenticate.", + ) raise HTTPException( status_code=400, detail=f"Token refresh failed: {error_detail}" ) @@ -427,6 +440,20 @@ async def refresh_slack_token( # Slack OAuth v2 returns success status in the JSON if not token_json.get("ok", False): error_msg = token_json.get("error", "Unknown error") + # Check if this is a token expiration/revocation error + error_lower = error_msg.lower() + if ( + "invalid_grant" in error_lower + or "invalid_auth" in error_lower + or "invalid_refresh_token" in error_lower + or "token_revoked" in error_lower + or "expired" in error_lower + or "revoked" in error_lower + ): + raise HTTPException( + status_code=401, + detail="Slack authentication failed. Please re-authenticate.", + ) raise HTTPException( status_code=400, detail=f"Slack OAuth refresh error: {error_msg}" ) diff --git a/surfsense_backend/app/routes/teams_add_connector_route.py b/surfsense_backend/app/routes/teams_add_connector_route.py index 9ce84e171..77ce4965e 100644 --- a/surfsense_backend/app/routes/teams_add_connector_route.py +++ b/surfsense_backend/app/routes/teams_add_connector_route.py @@ -420,11 +420,24 @@ async def refresh_teams_token( if token_response.status_code != 200: error_detail = token_response.text + error_code = "" try: error_json = token_response.json() error_detail = error_json.get("error_description", error_detail) + error_code = error_json.get("error", "") except Exception: pass + # Check if this is a token expiration/revocation error + error_lower = (error_detail + error_code).lower() + if ( + "invalid_grant" in error_lower + or "expired" in error_lower + or "revoked" in error_lower + ): + raise HTTPException( + status_code=401, + detail="Microsoft Teams authentication failed. Please re-authenticate.", + ) raise HTTPException( status_code=400, detail=f"Token refresh failed: {error_detail}" )