mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-10 20:35:17 +02:00
feat: enhance OAuth callback handling for Airtable, Linear, and Notion connectors if user deny access
- Updated callback routes to handle optional error parameters for OAuth flows, improving user experience during authorization failures. - Implemented error logging and redirection logic to provide feedback when access is denied or errors occur. - Added validation for required parameters to ensure proper handling of authorization codes and state parameters. - Enhanced documentation in the callback functions to clarify the purpose of each parameter.
This commit is contained in:
parent
b81af397c0
commit
ec7599362d
3 changed files with 114 additions and 9 deletions
|
|
@ -134,8 +134,9 @@ async def connect_airtable(space_id: int, user: User = Depends(current_active_us
|
|||
@router.get("/auth/airtable/connector/callback")
|
||||
async def airtable_callback(
|
||||
request: Request,
|
||||
code: str,
|
||||
state: str,
|
||||
code: str | None = None,
|
||||
error: str | None = None,
|
||||
state: str | None = None,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
):
|
||||
"""
|
||||
|
|
@ -143,7 +144,8 @@ async def airtable_callback(
|
|||
|
||||
Args:
|
||||
request: FastAPI request object
|
||||
code: Authorization code from Airtable
|
||||
code: Authorization code from Airtable (if user granted access)
|
||||
error: Error code from Airtable (if user denied access or error occurred)
|
||||
state: State parameter containing user/space info
|
||||
session: Database session
|
||||
|
||||
|
|
@ -151,6 +153,39 @@ async def airtable_callback(
|
|||
Redirect response to frontend
|
||||
"""
|
||||
try:
|
||||
# Handle OAuth errors (e.g., user denied access)
|
||||
if error:
|
||||
logger.warning(f"Airtable OAuth error: {error}")
|
||||
# Try to decode state to get space_id for redirect, but don't fail if it's invalid
|
||||
space_id = None
|
||||
if state:
|
||||
try:
|
||||
decoded_state = base64.urlsafe_b64decode(state.encode()).decode()
|
||||
data = json.loads(decoded_state)
|
||||
space_id = data.get("space_id")
|
||||
except Exception:
|
||||
pass # If state is invalid, we'll redirect without space_id
|
||||
|
||||
# Redirect to frontend with error parameter
|
||||
if space_id:
|
||||
return RedirectResponse(
|
||||
url=f"{config.NEXT_FRONTEND_URL}/dashboard/{space_id}/new-chat?modal=connectors&tab=all&error=airtable_oauth_denied"
|
||||
)
|
||||
else:
|
||||
return RedirectResponse(
|
||||
url=f"{config.NEXT_FRONTEND_URL}/dashboard?error=airtable_oauth_denied"
|
||||
)
|
||||
|
||||
# Validate required parameters for successful flow
|
||||
if not code:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="Missing authorization code"
|
||||
)
|
||||
if not state:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="Missing state parameter"
|
||||
)
|
||||
|
||||
# Decode and parse the state
|
||||
try:
|
||||
decoded_state = base64.urlsafe_b64decode(state.encode()).decode()
|
||||
|
|
|
|||
|
|
@ -104,8 +104,9 @@ async def connect_linear(space_id: int, user: User = Depends(current_active_user
|
|||
@router.get("/auth/linear/connector/callback")
|
||||
async def linear_callback(
|
||||
request: Request,
|
||||
code: str,
|
||||
state: str,
|
||||
code: str | None = None,
|
||||
error: str | None = None,
|
||||
state: str | None = None,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
):
|
||||
"""
|
||||
|
|
@ -113,7 +114,8 @@ async def linear_callback(
|
|||
|
||||
Args:
|
||||
request: FastAPI request object
|
||||
code: Authorization code from Linear
|
||||
code: Authorization code from Linear (if user granted access)
|
||||
error: Error code from Linear (if user denied access or error occurred)
|
||||
state: State parameter containing user/space info
|
||||
session: Database session
|
||||
|
||||
|
|
@ -121,6 +123,39 @@ async def linear_callback(
|
|||
Redirect response to frontend
|
||||
"""
|
||||
try:
|
||||
# Handle OAuth errors (e.g., user denied access)
|
||||
if error:
|
||||
logger.warning(f"Linear OAuth error: {error}")
|
||||
# Try to decode state to get space_id for redirect, but don't fail if it's invalid
|
||||
space_id = None
|
||||
if state:
|
||||
try:
|
||||
decoded_state = base64.urlsafe_b64decode(state.encode()).decode()
|
||||
data = json.loads(decoded_state)
|
||||
space_id = data.get("space_id")
|
||||
except Exception:
|
||||
pass # If state is invalid, we'll redirect without space_id
|
||||
|
||||
# Redirect to frontend with error parameter
|
||||
if space_id:
|
||||
return RedirectResponse(
|
||||
url=f"{config.NEXT_FRONTEND_URL}/dashboard/{space_id}/new-chat?modal=connectors&tab=all&error=linear_oauth_denied"
|
||||
)
|
||||
else:
|
||||
return RedirectResponse(
|
||||
url=f"{config.NEXT_FRONTEND_URL}/dashboard?error=linear_oauth_denied"
|
||||
)
|
||||
|
||||
# Validate required parameters for successful flow
|
||||
if not code:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="Missing authorization code"
|
||||
)
|
||||
if not state:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="Missing state parameter"
|
||||
)
|
||||
|
||||
# Decode and parse the state
|
||||
try:
|
||||
decoded_state = base64.urlsafe_b64decode(state.encode()).decode()
|
||||
|
|
|
|||
|
|
@ -100,8 +100,9 @@ async def connect_notion(space_id: int, user: User = Depends(current_active_user
|
|||
@router.get("/auth/notion/connector/callback")
|
||||
async def notion_callback(
|
||||
request: Request,
|
||||
code: str,
|
||||
state: str,
|
||||
code: str | None = None,
|
||||
error: str | None = None,
|
||||
state: str | None = None,
|
||||
session: AsyncSession = Depends(get_async_session),
|
||||
):
|
||||
"""
|
||||
|
|
@ -109,7 +110,8 @@ async def notion_callback(
|
|||
|
||||
Args:
|
||||
request: FastAPI request object
|
||||
code: Authorization code from Notion
|
||||
code: Authorization code from Notion (if user granted access)
|
||||
error: Error code from Notion (if user denied access or error occurred)
|
||||
state: State parameter containing user/space info
|
||||
session: Database session
|
||||
|
||||
|
|
@ -117,6 +119,39 @@ async def notion_callback(
|
|||
Redirect response to frontend
|
||||
"""
|
||||
try:
|
||||
# Handle OAuth errors (e.g., user denied access)
|
||||
if error:
|
||||
logger.warning(f"Notion OAuth error: {error}")
|
||||
# Try to decode state to get space_id for redirect, but don't fail if it's invalid
|
||||
space_id = None
|
||||
if state:
|
||||
try:
|
||||
decoded_state = base64.urlsafe_b64decode(state.encode()).decode()
|
||||
data = json.loads(decoded_state)
|
||||
space_id = data.get("space_id")
|
||||
except Exception:
|
||||
pass # If state is invalid, we'll redirect without space_id
|
||||
|
||||
# Redirect to frontend with error parameter
|
||||
if space_id:
|
||||
return RedirectResponse(
|
||||
url=f"{config.NEXT_FRONTEND_URL}/dashboard/{space_id}/new-chat?modal=connectors&tab=all&error=notion_oauth_denied"
|
||||
)
|
||||
else:
|
||||
return RedirectResponse(
|
||||
url=f"{config.NEXT_FRONTEND_URL}/dashboard?error=notion_oauth_denied"
|
||||
)
|
||||
|
||||
# Validate required parameters for successful flow
|
||||
if not code:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="Missing authorization code"
|
||||
)
|
||||
if not state:
|
||||
raise HTTPException(
|
||||
status_code=400, detail="Missing state parameter"
|
||||
)
|
||||
|
||||
# Decode and parse the state
|
||||
try:
|
||||
decoded_state = base64.urlsafe_b64decode(state.encode()).decode()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue