Skip to content

Commit

Permalink
OIDC device code flow: hide progress bar on completed (or timed out) …
Browse files Browse the repository at this point in the history
…authentication
  • Loading branch information
soxofaan committed Apr 10, 2024
1 parent 15639db commit f2db0bd
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 19 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- OIDC device code flow: hide progress bar on completed (or timed out) authentication

### Removed

### Fixed
Expand Down
25 changes: 14 additions & 11 deletions openeo/rest/auth/oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -737,11 +737,13 @@ def show_instructions(self, info: VerificationInfo) -> None:
def set_status(self, status: str):
self._status = status

def show_progress(self, status: Optional[str] = None):
def show_progress(self, status: Optional[str] = None, include_bar: bool = True):
if status:
self.set_status(status)
progress_bar = self._progress_bar.get(fraction=1.0 - self.elapsed() / self.timeout)
text = f"{progress_bar} {self._status}"
text = self._status
if include_bar:
progress_bar = self._progress_bar.get(fraction=1.0 - self.elapsed() / self.timeout)
text = f"{progress_bar} {text}"
self._display(f"{text[:self._max_width]: <{self._max_width}s}", end="\r")

def close(self):
Expand Down Expand Up @@ -775,13 +777,15 @@ def _instructions(self, info: VerificationInfo) -> str:
def show_instructions(self, info: VerificationInfo) -> None:
self._instructions_display.update({"text/html": self._instructions(info=info)}, raw=True)

def show_progress(self, status: Optional[str] = None):
# TODO Add emoticons to status?
def show_progress(self, status: Optional[str] = None, include_bar: bool = True):
if status:
self.set_status(status)
progress_bar = self._progress_bar.get(fraction=1.0 - self.elapsed() / self.timeout)
icon = self._status_icon(self._status)
self._progress_display.update({"text/html": f"<code>{progress_bar}</code> {icon} {self._status}"}, raw=True)
text = f"{icon} {self._status}"
if include_bar:
progress_bar = self._progress_bar.get(fraction=1.0 - self.elapsed() / self.timeout)
text = f"<code>{progress_bar}</code> {text}"
self._progress_display.update({"text/html": text}, raw=True)

def _status_icon(self, status: str) -> str:
status = status.lower()
Expand All @@ -790,7 +794,7 @@ def _status_icon(self, status: str) -> str:
elif "success" in status:
return "\u2705" # Green check mark
elif "timed out" in status:
return "\u274C" # Red cross mark
return "\u274C" # Red cross mark
else:
return ""

Expand Down Expand Up @@ -906,8 +910,7 @@ def get_tokens(self, request_refresh_token: bool = False) -> AccessTokenResult:
resp = self._requests.post(url=token_endpoint, data=post_data, timeout=5)
if resp.status_code == 200:
log.info(f"[{elapsed():5.1f}s] Authorized successfully.")
poll_ui.show_progress(status="Authorized successfully")
# TODO remove progress bar when authorized succesfully?
poll_ui.show_progress(status="Authorized successfully", include_bar=False)
return self._get_access_token_result(data=resp.json())
else:
try:
Expand All @@ -927,5 +930,5 @@ def get_tokens(self, request_refresh_token: bool = False) -> AccessTokenResult:
)
next_poll = elapsed() + poll_interval

poll_ui.show_progress(status="Timed out")
poll_ui.show_progress(status="Timed out", include_bar=False)
raise OidcDeviceCodePollTimeout(f"Timeout ({self._max_poll_time:.1f}s) while polling for access token.")
6 changes: 3 additions & 3 deletions tests/rest/auth/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ def test_oidc_auth_device_flow(auth_config, refresh_token_store, requests_mock,
"Using client ID 'z3-cl13nt'",
f"Visit https://authit.test/dc and enter user code '{user_code}' to authenticate.",
"[#####################################] Authorization pending \r[#####################################] Polling \r",
"[####################################-] Authorized successfully \r\n",
"Authorized successfully \r\n"
"The OpenID Connect device flow was successful.",
"Stored refresh token in {p!r}".format(p=str(refresh_token_store.path)),
]
Expand Down Expand Up @@ -369,7 +369,7 @@ def test_oidc_auth_device_flow_default_client(
"Will try to use default client.",
f"Visit https://authit.test/dc and enter user code '{user_code}' to authenticate.",
"[#####################################] Authorization pending \r[#####################################] Polling \r",
"[####################################-] Authorized successfully \r\n",
"Authorized successfully \r\n",
"The OpenID Connect device flow was successful.",
"Stored refresh token in {p!r}".format(p=str(refresh_token_store.path)),
]
Expand Down Expand Up @@ -418,7 +418,7 @@ def test_oidc_auth_device_flow_no_config_all_defaults(
"Will try to use default client.",
f"Visit https://authit.test/dc and enter user code '{user_code}' to authenticate.",
"[#####################################] Authorization pending \r[#####################################] Polling \r",
"[####################################-] Authorized successfully \r\n",
"Authorized successfully \r\n",
"The OpenID Connect device flow was successful.",
"Stored refresh token in {p!r}".format(p=str(refresh_token_store.path)),
]
Expand Down
8 changes: 4 additions & 4 deletions tests/rest/auth/test_oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ def test_oidc_device_flow_with_client_secret(requests_mock, caplog, support_veri

assert display.lines[-3:] == [
(1011, "[#################--------------------] Polling ", "\r"),
(1011, "[#################--------------------] Authorized successfully ", "\r"),
(1011, "Authorized successfully ", "\r"),
(1011, "", "\n"),
]

Expand Down Expand Up @@ -475,7 +475,7 @@ def test_oidc_device_flow_with_pkce(requests_mock, caplog, support_verification_

assert display.lines[-3:] == [
(1016, "[###########################----------] Polling ", "\r"),
(1016, "[###########################----------] Authorized successfully ", "\r"),
(1016, "Authorized successfully ", "\r"),
(1016, "", "\n"),
]

Expand Down Expand Up @@ -552,7 +552,7 @@ def test_oidc_device_flow_without_pkce_nor_secret(

assert display.lines[-3:] == [
(1043.5, "[##########################-----------] Polling ", "\r"),
(1043.5, "[##########################-----------] Authorized successfully ", "\r"),
(1043.5, "Authorized successfully ", "\r"),
(1043.5, "", "\n"),
]

Expand Down Expand Up @@ -674,7 +674,7 @@ def test_oidc_device_flow_auto_detect(

assert display.lines[-3:] == [
(1033, "[#################################----] Polling ", "\r"),
(1033, "[#################################----] Authorized successfully ", "\r"),
(1033, "Authorized successfully ", "\r"),
(1033, "", "\n"),
]

Expand Down
2 changes: 1 addition & 1 deletion tests/rest/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def assert_oidc_device_code_flow(url: str = "https://oidc.test/dc", elapsed: flo
stdout, _ = capsys.readouterr()
assert f"Visit {url} and enter" in stdout
assert re.search(r"\[#+-*\] Authorization pending *\r\[#+-*\] Polling *\r", stdout)
assert re.search(r"\[#+-*\] Authorized successfully *\r\n", stdout)
assert re.search(r"Authorized successfully *\r\n", stdout)
assert time_machine.coordinates.time() - start >= elapsed

return assert_oidc_device_code_flow
Expand Down

0 comments on commit f2db0bd

Please sign in to comment.