Skip to content

Commit cd204f4

Browse files
authored
Merge pull request #110 from soxofaan/oidc-specify-redirect-port
Allow specifying OAuth redirect port (and host)
2 parents 66d643d + 01af400 commit cd204f4

File tree

3 files changed

+30
-6
lines changed

3 files changed

+30
-6
lines changed

openeo/rest/auth/oidc.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,12 @@ class HttpServerThread(threading.Thread):
7272
Thread that runs a HTTP server (`http.server.HTTPServer`)
7373
"""
7474

75-
def __init__(self, RequestHandlerClass, server_address=('', 0)):
75+
def __init__(self, RequestHandlerClass, server_address: Tuple[str, int] = None):
7676
# Make it a daemon to minimize potential shutdown issues due to `serve_forever`
7777
super().__init__(daemon=True)
7878
self._RequestHandlerClass = RequestHandlerClass
7979
# Server address ('', 0): listen on all ips and let OS pick a free port
80-
self._server_address = server_address
80+
self._server_address = server_address or ('', 0)
8181
self._server = None
8282

8383
def start(self):
@@ -187,11 +187,13 @@ class OidcAuthCodePkceAuthenticator(OidcAuthenticator):
187187
AuthCodeResult = namedtuple("AuthCodeResult", ["auth_code", "nonce", "code_verifier", "redirect_uri"])
188188
AccessTokenResult = namedtuple("AccessTokenResult", ["access_token", "id_token", "refresh_token"])
189189

190-
def __init__(self, client_id: str, oidc_discovery_url: str, webbrowser_open: Callable = None, timeout=120):
190+
def __init__(self, client_id: str, oidc_discovery_url: str, webbrowser_open: Callable = None, timeout=120,
191+
server_address: Tuple[str, int] = None):
191192
self._client_id = client_id
192193
self._provider_info = requests.get(oidc_discovery_url).json()
193194
self._webbrowser_open = webbrowser_open or webbrowser.open
194195
self._authentication_timeout = timeout
196+
self._server_address = server_address
195197

196198
@staticmethod
197199
def hash_code_verifier(code: str) -> str:
@@ -222,7 +224,11 @@ def _get_auth_code(self) -> AuthCodeResult:
222224
# Set up HTTP server (in separate thread) to catch OAuth redirect URL
223225
callback_queue = Queue()
224226
RequestHandlerClass = OAuthRedirectRequestHandler.with_queue(callback_queue)
225-
with HttpServerThread(RequestHandlerClass=RequestHandlerClass) as http_server_thread:
227+
http_server_thread = HttpServerThread(
228+
RequestHandlerClass=RequestHandlerClass,
229+
server_address=self._server_address
230+
)
231+
with http_server_thread:
226232
port, host, fqdn = http_server_thread.server_address_info()
227233
# TODO: use fully qualified domain name instead of "localhost"?
228234
# Otherwise things won't work when the client is for example

openeo/rest/connection.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import shutil
88
import sys
99
import warnings
10-
from typing import Dict, List
10+
from typing import Dict, List, Tuple
1111
from urllib.parse import urljoin
1212

1313
import requests
@@ -197,14 +197,16 @@ def authenticate_basic(self, username: str, password: str) -> 'Connection':
197197
self.auth = BearerAuth(bearer=resp["access_token"])
198198
return self
199199

200-
def authenticate_OIDC(self, client_id: str, webbrowser_open=None, timeout=120) -> 'Connection':
200+
def authenticate_OIDC(self, client_id: str, webbrowser_open=None, timeout=120,
201+
server_address: Tuple[str, int] = None) -> 'Connection':
201202
"""
202203
Authenticates a user to the backend using OpenID Connect.
203204
204205
:param client_id: Client id to use for OpenID Connect authentication
205206
:param webbrowser_open: optional handler for the initial OAuth authentication request
206207
(opens a webbrowser by default)
207208
:param timeout: number of seconds after which to abort the authentication procedure
209+
:param server_address: optional tuple (hostname, port_number) to serve the OAuth redirect callback on
208210
"""
209211
# Local import to avoid importing the whole OpenID Connect dependency chain. TODO: just do global import?
210212
from openeo.rest.auth.oidc import OidcAuthCodePkceAuthenticator
@@ -216,6 +218,7 @@ def authenticate_OIDC(self, client_id: str, webbrowser_open=None, timeout=120) -
216218
oidc_discovery_url=oidc_discovery_url,
217219
webbrowser_open=webbrowser_open,
218220
timeout=timeout,
221+
server_address=server_address,
219222
)
220223
# Do the Oauth/OpenID Connect flow and use the access token as bearer token.
221224
tokens = authenticator.get_tokens()

tests/rest/auth/test_oidc.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,21 @@ def test_http_server_thread():
5050
server_thread.join()
5151

5252

53+
def test_http_server_thread_port():
54+
queue = Queue()
55+
server_thread = HttpServerThread(RequestHandlerClass=QueuingRequestHandler.with_queue(queue),
56+
server_address=('', 12345))
57+
server_thread.start()
58+
port, host, fqdn = server_thread.server_address_info()
59+
assert port == 12345
60+
url = 'http://{f}:{p}/foo/bar'.format(f=fqdn, p=port)
61+
response = requests.get(url)
62+
response.raise_for_status()
63+
assert list(drain_queue(queue)) == ['/foo/bar']
64+
server_thread.shutdown()
65+
server_thread.join()
66+
67+
5368
def test_oidc_flow(oidc_test_setup):
5469
# see test/rest/conftest.py for `oidc_test_setup` fixture
5570
client_id = "myclient"

0 commit comments

Comments
 (0)