mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-30 00:27:11 +09:00
generate_bitbucket_authorize_url() takes a redirect_uri and leaves it out of the query string, so Bitbucket returns the user to whatever callback is registered on the OAuth consumer rather than the one the panel asked for. complete_bitbucket_callback() then posts that same redirect_uri to the token endpoint, so the two halves of one flow name different callbacks. Both sibling generators in the same file send it (generate_github_authorize_url line 207, generate_gitlab_authorize_url line 446), as does generate_auth_url in sso_service.py; Bitbucket was the only one that dropped it. GET /source-connections/bitbucket/authorize already rejects a request without redirect_uri, so the value was always present and always discarded. Adds the parameter, plus a regression test parametrised over all three providers so the next one added is held to the same contract.
49 lines
2.2 KiB
Python
49 lines
2.2 KiB
Python
"""Proving tests for the source-connection OAuth authorize URLs.
|
|
|
|
The two halves of one flow have to name the same callback. `/source-connections
|
|
/<provider>/authorize` requires a `redirect_uri` and hands it to the generator;
|
|
`/source-connections/<provider>/callback` posts that same value to the provider's
|
|
token endpoint (`complete_*_callback`). A generator that accepts the parameter
|
|
and leaves it out of the authorize URL makes the provider return the user to
|
|
whatever callback is registered on the OAuth app instead of the one the panel
|
|
asked for, while the token exchange still claims the one it asked for.
|
|
|
|
Parametrised across every provider so the next one added is covered by the same
|
|
assertion instead of a fourth copy of it.
|
|
"""
|
|
from urllib.parse import parse_qs, urlsplit
|
|
|
|
import pytest
|
|
|
|
from app.services.settings_service import SettingsService
|
|
from app.services.source_connection_service import SourceConnectionService as SC
|
|
|
|
# provider -> (client-id setting, client-secret setting, generator method)
|
|
PROVIDERS = [
|
|
('github', 'source_github_client_id', 'source_github_client_secret',
|
|
'generate_github_authorize_url'),
|
|
('gitlab', 'source_gitlab_client_id', 'source_gitlab_client_secret',
|
|
'generate_gitlab_authorize_url'),
|
|
('bitbucket', 'source_bitbucket_client_id', 'source_bitbucket_client_secret',
|
|
'generate_bitbucket_authorize_url'),
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize('provider,id_key,secret_key,generator', PROVIDERS)
|
|
def test_authorize_url_carries_the_callers_redirect_uri(
|
|
app, provider, id_key, secret_key, generator):
|
|
redirect_uri = f'https://panel.example/connections/callback/{provider}'
|
|
with app.test_request_context():
|
|
SettingsService.set(id_key, 'cid')
|
|
SettingsService.set(secret_key, 'sec')
|
|
# Classic OAuth screen: the GitHub App install path is a deliberate
|
|
# exception with its own coverage in test_github_app_manifest.py.
|
|
SettingsService.set('source_github_app_slug', '')
|
|
|
|
url, state = getattr(SC, generator)(redirect_uri)
|
|
|
|
params = parse_qs(urlsplit(url).query)
|
|
assert params['redirect_uri'] == [redirect_uri]
|
|
assert params['client_id'] == ['cid']
|
|
assert params['state'] == [state]
|