Fix URL encoding in Jira OAuth authorization URLs (#12399)

Co-authored-by: openhands <openhands@all-hands.dev>
Co-authored-by: Rohit Malhotra <rohitvinodmalhotra@gmail.com>
This commit is contained in:
John-Mason P. Shackelford
2026-02-19 16:40:29 -05:00
committed by GitHub
parent 8927ac2230
commit 89a6890269
4 changed files with 118 additions and 10 deletions

View File

@@ -4,7 +4,7 @@ import json
import os
import re
import uuid
from urllib.parse import urlparse
from urllib.parse import urlencode, urlparse
import requests
from fastapi import APIRouter, BackgroundTasks, Header, HTTPException, Request, status
@@ -371,9 +371,7 @@ async def create_jira_workspace(request: Request, workspace_data: JiraWorkspaceC
'prompt': 'consent',
}
auth_url = (
f"{JIRA_AUTH_URL}?{'&'.join([f'{k}={v}' for k, v in auth_params.items()])}"
)
auth_url = f'{JIRA_AUTH_URL}?{urlencode(auth_params)}'
return JSONResponse(
content={
@@ -432,9 +430,7 @@ async def create_workspace_link(request: Request, link_data: JiraLinkCreate):
'response_type': 'code',
'prompt': 'consent',
}
auth_url = (
f"{JIRA_AUTH_URL}?{'&'.join([f'{k}={v}' for k, v in auth_params.items()])}"
)
auth_url = f'{JIRA_AUTH_URL}?{urlencode(auth_params)}'
return JSONResponse(
content={

View File

@@ -2,7 +2,7 @@ import json
import os
import re
import uuid
from urllib.parse import urlparse
from urllib.parse import urlencode, urlparse
import requests
from fastapi import (
@@ -316,7 +316,7 @@ async def create_jira_dc_workspace(
'response_type': 'code',
}
auth_url = f"{JIRA_DC_AUTH_URL}?{'&'.join([f'{k}={v}' for k, v in auth_params.items()])}"
auth_url = f'{JIRA_DC_AUTH_URL}?{urlencode(auth_params)}'
return JSONResponse(
content={
@@ -436,7 +436,7 @@ async def create_workspace_link(request: Request, link_data: JiraDcLinkCreate):
'state': state,
'response_type': 'code',
}
auth_url = f"{JIRA_DC_AUTH_URL}?{'&'.join([f'{k}={v}' for k, v in auth_params.items()])}"
auth_url = f'{JIRA_DC_AUTH_URL}?{urlencode(auth_params)}'
return JSONResponse(
content={

View File

@@ -1220,3 +1220,60 @@ async def test_validate_workspace_update_permissions_no_current_link(mock_manage
result = await _validate_workspace_update_permissions('user1', 'test-workspace')
assert result == mock_workspace
# Tests for OAuth URL encoding
class TestJiraDcOAuthUrlEncoding:
"""Tests to verify OAuth authorization URLs are properly URL-encoded."""
@pytest.mark.asyncio
@patch('server.routes.integration.jira_dc.get_user_auth')
@patch('server.routes.integration.jira_dc.redis_client')
@patch('server.routes.integration.jira_dc.JIRA_DC_ENABLE_OAUTH', True)
async def test_create_jira_dc_workspace_url_encoding(
self, mock_redis, mock_get_auth, mock_request, mock_user_auth
):
"""Test that create_jira_dc_workspace properly URL-encodes the authorization URL."""
mock_get_auth.return_value = mock_user_auth
mock_redis.setex.return_value = True
workspace_data = JiraDcWorkspaceCreate(
workspace_name='test-workspace',
webhook_secret='secret',
svc_acc_email='svc@test.com',
svc_acc_api_key='key',
is_active=True,
)
response = await create_jira_dc_workspace(mock_request, workspace_data)
content = json.loads(response.body)
auth_url = content['authorizationUrl']
# Verify no raw spaces in the URL (spaces should be encoded as + or %20)
assert ' ' not in auth_url
# Verify scope parameter contains encoded scopes (+ is valid URL encoding for space)
assert 'scope=read%3Ame+read%3Ajira-user+read%3Ajira-work' in auth_url
# Verify redirect_uri is properly encoded
assert 'redirect_uri=https%3A%2F%2F' in auth_url
@pytest.mark.asyncio
@patch('server.routes.integration.jira_dc.get_user_auth')
@patch('server.routes.integration.jira_dc.redis_client')
@patch('server.routes.integration.jira_dc.JIRA_DC_ENABLE_OAUTH', True)
async def test_create_workspace_link_url_encoding(
self, mock_redis, mock_get_auth, mock_request, mock_user_auth
):
"""Test that create_workspace_link properly URL-encodes the authorization URL."""
mock_get_auth.return_value = mock_user_auth
mock_redis.setex.return_value = True
link_data = JiraDcLinkCreate(workspace_name='test-workspace')
response = await create_workspace_link(mock_request, link_data)
content = json.loads(response.body)
auth_url = content['authorizationUrl']
# Verify no raw spaces in the URL (spaces should be encoded as + or %20)
assert ' ' not in auth_url
# Verify scope parameter contains encoded scopes (+ is valid URL encoding for space)
assert 'scope=read%3Ame+read%3Ajira-user+read%3Ajira-work' in auth_url
# Verify redirect_uri is properly encoded
assert 'redirect_uri=https%3A%2F%2F' in auth_url

View File

@@ -1323,3 +1323,58 @@ async def test_validate_workspace_update_permissions_no_current_link(mock_manage
result = await _validate_workspace_update_permissions('user1', 'test-workspace')
assert result == mock_workspace
# Tests for OAuth URL encoding
class TestJiraOAuthUrlEncoding:
"""Tests to verify OAuth authorization URLs are properly URL-encoded."""
@pytest.mark.asyncio
@patch('server.routes.integration.jira.get_user_auth')
@patch('server.routes.integration.jira.redis_client')
async def test_create_jira_workspace_url_encoding(
self, mock_redis, mock_get_auth, mock_request, mock_user_auth
):
"""Test that create_jira_workspace properly URL-encodes the authorization URL."""
mock_get_auth.return_value = mock_user_auth
mock_redis.setex.return_value = True
workspace_data = JiraWorkspaceCreate(
workspace_name='test-workspace',
webhook_secret='secret',
svc_acc_email='svc@test.com',
svc_acc_api_key='key',
is_active=True,
)
response = await create_jira_workspace(mock_request, workspace_data)
content = json.loads(response.body)
auth_url = content['authorizationUrl']
# Verify no raw spaces in the URL (spaces should be encoded as + or %20)
assert ' ' not in auth_url
# Verify scope parameter contains encoded scopes (+ is valid URL encoding for space)
assert 'scope=read%3Ame+read%3Ajira-user+read%3Ajira-work' in auth_url
# Verify redirect_uri is properly encoded
assert 'redirect_uri=https%3A%2F%2F' in auth_url
@pytest.mark.asyncio
@patch('server.routes.integration.jira.get_user_auth')
@patch('server.routes.integration.jira.redis_client')
async def test_create_workspace_link_url_encoding(
self, mock_redis, mock_get_auth, mock_request, mock_user_auth
):
"""Test that create_workspace_link properly URL-encodes the authorization URL."""
mock_get_auth.return_value = mock_user_auth
mock_redis.setex.return_value = True
link_data = JiraLinkCreate(workspace_name='test-workspace')
response = await create_workspace_link(mock_request, link_data)
content = json.loads(response.body)
auth_url = content['authorizationUrl']
# Verify no raw spaces in the URL (spaces should be encoded as + or %20)
assert ' ' not in auth_url
# Verify scope parameter contains encoded scopes (+ is valid URL encoding for space)
assert 'scope=read%3Ame+read%3Ajira-user+read%3Ajira-work' in auth_url
# Verify redirect_uri is properly encoded
assert 'redirect_uri=https%3A%2F%2F' in auth_url